Miscelazione di funzioni C in una classe Objective-C
-
03-07-2019 - |
Domanda
Sto scrivendo una classe Objective-C ma utilizza un'API scritta in C. Questo va principalmente bene poiché la combinazione di chiamate C con chiamate Objective-C causa pochi problemi.
Tuttavia, una delle chiamate API richiede un metodo di richiamata (esempio):
success = CFHostSetClient(host, MyCFHostClientCallBack, &context);
Dove MyCFHostClientCallBack
è una funzione C definita in questo modo:
static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
- Can / Come posso chiamare un metodo Objective-C al posto di questo?
- Posso / Devo mescolare le funzioni C con le mie chiamate Objective-C?
- Come mescolo le funzioni C con i metodi Objective-C?
Soluzione
È possibile combinare metodi e funzioni C e Objective-C, ecco un semplice esempio che utilizza l'API SQLite all'interno di un'app per iPhone: ( sito del corso )
Scarica il File zip (09_MySQLiteTableView. zip)
Le funzioni C devono essere dichiarate al di fuori del @implementation
in un file Objective-C (.m).
int MyCFunction(int num, void *data)
{
//code here...
}
@implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
@end
Poiché la funzione C è al di fuori del @implementation
non può chiamare metodi come
[self doSomething]
e non ha accesso agli ivar.
Questo può essere risolto fintanto che la funzione di richiamata accetta un parametro di tipo userInfo
o context
, normalmente di tipo void *
. Può essere utilizzato per inviare qualsiasi oggetto Objective-C alla funzione C.
Come nel codice campione , questo può essere manipolato con le normali operazioni Objective-C.
Inoltre, leggi questa risposta: Mixing C funzioni in una classe Objective-C
Altri suggerimenti
Per chiamare il codice Objective-C da un callback C, dovrei usare qualcosa del tipo:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
@implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
Can / Come posso chiamare un metodo Objective-C al posto di questo?
Non puoi.
Posso / dovrei mescolare la funzione C con la mia chiamata Objective-C?
Sì. Scrivi una funzione C e usala come callback per la funzione CF.
Come mescolo la funzione C con i metodi Objective-C?
Puoi impostare self
come puntatore info
nella struttura del tuo contesto. Questo verrà passato al callback. Quindi, nel callback, reindirizzare il puntatore info
su id
:
MyClass *self = (id)info;
È quindi possibile inviare messaggi self
. Tuttavia, non è ancora possibile accedere direttamente alle variabili di istanza, poiché una funzione C è al di fuori della sezione @implementation
. Dovrai renderli proprietà. Puoi farlo con un'estensione di classe a>. (Contrariamente a quanto dice quel documento, non dichiareresti l'estensione all'interno di @implementation
, ma nello stesso file con esso, generalmente proprio sopra di esso.)
Ciò che ho sempre trovato utile in questa situazione è creare un wrapper Obj-C in cima all'API C. Implementa ciò di cui hai bisogno per utilizzare le funzioni C e crea una classe C (o due) Objective-C su di essa, in modo che tutto ciò che il mondo esterno vedrà. Ad esempio, nel caso di un callback come questo, è possibile creare una funzione C che chiama i metodi delegati Obj-C su altri oggetti.