web-dev-qa-db-fra.com

Mélanger les fonctions C dans une classe Objective-C

J'écris une classe Objective-C mais elle utilise une API écrite en C. C'est très bien car le mélange d'appels C avec des appels Objective-C provoque peu de problèmes.

Cependant, l'un des appels API nécessite une méthode de rappel (exemple):

success = CFHostSetClient(Host, MyCFHostClientCallBack, &context);

MyCFHostClientCallBack est une fonction C définie comme ceci:

static void MyCFHostClientCallBack(CFHostRef Host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
  1. Puis-je/comment appeler une méthode Objective-C à la place de cela?
  2. Puis-je/dois-je mélanger des fonctions C avec mes appels Objective-C?
  3. Comment mélanger les fonctions C avec les méthodes Objective-C?
38
rjstelling

Mélanger les méthodes et les fonctions C et Objective-C est possible, voici un exemple simple qui utilise l'API SQLite dans une application iPhone: ( site du cours )

Téléchargez le fichier Zip (09_MySQLiteTableView.Zip)

Les fonctions C doivent être déclarées en dehors de @implementation dans un fichier Objective-C (.m).

int MyCFunction(int num, void *data)
{
     //code here...
}

@implementation

- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
      //code here
}

@end

Parce que la fonction C est en dehors du @implementation il ne peut pas appeler des méthodes comme

[self doSomething]

et n'a pas accès aux ivars.

Cela peut être contourné tant que la fonction de rappel prend un paramètre de type userInfo ou context, normalement de type void*. Cela peut être utilisé pour envoyer n'importe quel objet Objective-C à la fonction C.

Comme dans le exemple de code , cela peut être manipulé avec des opérations Objective-C normales.

De plus, veuillez lire cette réponse: Mélanger les fonctions C dans une classe Objective-C

48
rjstelling

Pour appeler du code Objective-C à partir d'un rappel C, j'utiliserais quelque chose comme:

void * refToSelf;
int cCallback()
{
    [refToSelf someMethod:someArg];
}

@implementation SomeClass
- (id) init
{
     self = [super init];
     refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
25
diciu

Puis-je/comment appeler une méthode Objective-C à la place de cela?

Vous ne pouvez pas.

Puis-je/dois-je mélanger la fonction C avec mon appel Objective-C?

Oui. Écrivez une fonction C et utilisez-la comme rappel de la fonction CF.

Comment mélanger la fonction C avec les méthodes Objective-C?

Vous pouvez définir self comme pointeur info dans votre structure de contexte. Cela sera transmis au rappel. Ensuite, dans le rappel, redéfinissez le pointeur info sur id:

MyClass *self = (id)info;

Vous pouvez ensuite envoyer des messages self. Cependant, vous ne pouvez toujours pas accéder directement aux variables d'instance, car une fonction C est en dehors de @implementation section. Vous devrez en faire des propriétés. Vous pouvez le faire avec une extension de classe . (Contrairement à ce que dit ce document, vous ne déclareriez pas l'extension à l'intérieur de @implementation, mais dans le même fichier, généralement juste au-dessus.)

8
Peter Hosey

Ce que j'ai toujours trouvé utile dans cette situation, c'est de créer un wrapper Obj-C au-dessus de l'API C. Implémentez ce dont vous avez besoin pour utiliser les fonctions C et créez une classe Objective-C (ou deux) par-dessus, afin que tout le monde extérieur le voie. Par exemple, dans le cas d'un rappel comme celui-ci, vous pouvez créer une fonction C qui appelle des méthodes de délégation Obj-C sur d'autres objets.

5
Marc Charbonneau