2015-01-27 17 views
13

Come posso chiamare le funzioni iOS non pubbliche e accedere alle propietarie non pubbliche da Swift? In particolare, vorrei utilizzare una classe non pubblica nel framework QuartzCore.Come accedere alle API private iOS in Swift?

Una soluzione che mi è venuta in mente è creare un progetto Objective-C "bridging" che avvolga queste API non pubbliche in quelle pubbliche e che richiami queste funzioni Objective-C da Swift. Tuttavia, la mia soluzione è pura Swift ora e preferirei mantenerla in questo modo. Esiste un modo più preciso? (ad esempio aggiungendo qualcosa a Objective-C bridging header file)

Nota: So cosa stai pensando, le API private sono private perché non dovrebbero essere utilizzate. Conosco i rischi, sono a conoscenza di tutte le donwsides, le restrizioni sull'app store ecc. Dopo tutto quello che ho considerato attentamente e molte ricerche, purtroppo sembra ancora il modo migliore per andare in questo caso particolare.

+0

Se si aggiunge correttamente la dichiarazione dei metodi privati ​​per un colpo di testa colmare file, come se fossero in una categoria (chiamato, ad esempio, 'PrivateButImmaUseTheseAnyway'), funziona? –

+0

@ TheParamagneticCroissant Non sono sicuro di aver capito cosa intendi. Non sapevo se è possibile dichiarare solo un metodo nel file di intestazione del bridging. Ho provato a dichiarare l'intera classe privata - ho ricevuto un errore di compilazione dicendo che la classe non esiste ma forse non l'ho fatto correttamente. – drasto

+0

Voglio dire, dichiarate la classe privata insieme a una categoria, come questa: '@interface NSPrivateClass (PrivateStuff)', e aggiungete la dichiarazione dei metodi privati ​​lì. –

risposta

7

È possibile ottenere lezioni private utilizzando NSClassFromString: e interagire con loro utilizzando performSelector.

15

Si può fare lo stesso trucco che si farebbe se il progetto fosse in Objective-C.

Creare un file di intestazione e inserire la dichiarazione di una categoria nella classe, insieme alla dichiarazione dei metodi privati ​​che si desidera esporre. Quindi, dì al compilatore Swift di importare questa intestazione di bridging.

A scopo dimostrativo, ho intenzione di esplorare l'interno di NSBigMutableString, una sottoclasse privata di NSMutableString e chiamerò il suo metodo _isMarkedAsImmutable.

Si noti che qui, l'intera classe stessa è privata, quindi devo prima dichiararla come sottoclasse della sua vera superclasse. Per questo motivo, avrei potuto dichiarare il metodo anche nella dichiarazione della classe stessa; che, tuttavia, non avrebbe dimostrato l'utilizzo della trick-category (Private).

Se la tua classe è pubblica, ovviamente avrai solo bisogno della categoria e non dovrai (ri) dichiarare la classe stessa.

Bridge.h:

#import <Foundation/Foundation.h> 

@interface NSMutableString (Private) 
- (BOOL)_isMarkedAsImmutable; // this is a lie 
@end 

@interface NSBigMutableString : NSMutableString 
@end 

s.swift:

let s = NSBigMutableString() 
println(s._isMarkedAsImmutable()) 

Compilare ed eseguire:

$ xcrun -sdk macosx swiftc -o foo -import-objc-header Bridge.h s.swift 
$ ./foo 
false 
$