Search code examples
objective-cnsstringnsarray

NSString stringWithFormat and NSArray


I need a method for generating string from the format-string and it's arguments inside NSArray but I did't find any working solution on the StackOverflow. They don't build nor throw exceptions (first, second).


Solution

  • So I write my solution and I want to share it with you.

    @implementation NSString (AX_NSString)
    
    + (instancetype)ax_stringWithFormat:(NSString *)format array:(NSArray *)arrayArguments {
        NSMethodSignature *methodSignature = [self ax_generateSignatureForArguments:arrayArguments];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    
        [invocation setTarget:self];
        [invocation setSelector:@selector(stringWithFormat:)];
    
        [invocation setArgument:&format atIndex:2];
        for (NSInteger i = 0; i < [arrayArguments count]; i++) {
            id obj = arrayArguments[i];
            [invocation setArgument:(&obj) atIndex:i+3];
        }
    
        [invocation invoke];
    
        __autoreleasing NSString *string;
        [invocation getReturnValue:&string];
    
        return string;
    }
    
    //https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
    + (NSMethodSignature *)ax_generateSignatureForArguments:(NSArray *)arguments {
        NSInteger count = [arguments count];
        NSInteger sizeptr = sizeof(void *);
        NSInteger sumArgInvoke = count + 3; //self + _cmd + (NSString *)format
        NSInteger offsetReturnType = sumArgInvoke * sizeptr;
    
        NSMutableString *mstring = [[NSMutableString alloc] init];
        [mstring appendFormat:@"@%zd@0:%zd", offsetReturnType, sizeptr];
        for (NSInteger i = 2; i < sumArgInvoke; i++) {
            [mstring appendFormat:@"@%zd", sizeptr * i];
        }
        return [NSMethodSignature signatureWithObjCTypes:[mstring UTF8String]];
    }
    
    @end