Search code examples
objective-cstructprotocols

How to pass unnamed struct in Objective-C protocol method?


Given the example objective C protocol below:

@protocol testp
- (void)testMethod:(struct {int a;})arg1 reply:(void (^)(NSError *))arg2;
@end

Assuming I've already setup the protocol connection. How can I call the method? The issue is the struct type, I'm familiar with passing basic arguments like int or NSString, however I'm unsure how to handle the unnamed struct in the protocol.

If I use:

struct {  int a; } test = {1};
[p testMethod:test reply:^(NSError* error ){
        NSLog(@"error: %@", error);
}];

I get the following error:

error: sending 'struct (unnamed struct at .. to parameter of incompatible type 'struct (unnamed struct at ..


Solution

  • The anonymous struct declared in the method signature..

     - (void)testMethod:(struct { int a; })arg1 reply:(void (^)(NSError *))arg2;
    

    ..and in front of the invocation..

    struct {  int a; } test = { 1 };
    

    ..are two different structures, which are not compatible. For anonymous structures one option you may employ is to pass a pointer to a struct, like this:

     - (void)method:(struct { int a; } *)str reply:(void (^)(NSError *))arg2;
    ...
    struct { int a; } val = { 1 };
    [obj method:&val reply:^(NSError *error) {
        NSLog(@"error: %@", error);
    }];
    
    

    It should compile, probably with warning about incompatible pointers, but will work just fine as long as the memory layout matches. This approach is very fragile and unreliable, however, and I can't see any reason to not use a named structure:

    typedef struct {
        int val;
    } TDWStruct;
    
    @protocol TDWReplyable <NSObject>
    
    - (void)method:(TDWStruct)str reply:(void (^)(NSError *))arg2;
    
    @end
    
    ...
    
    TDWStruct val = { 1 };
    [obj method:val reply:^(NSError *error) {
        NSLog(@"error: %@", error);
    }];