Skip to content

Instantly share code, notes, and snippets.

@paxswill
Created August 12, 2011 18:50
Show Gist options
  • Save paxswill/1142691 to your computer and use it in GitHub Desktop.
Save paxswill/1142691 to your computer and use it in GitHub Desktop.
And time for another episode of Stupid Obj-C Tricks! In this episode, we combine C varargs with Obj-C dynamic method resolution to hack together a cons like construct for strings. Explanation: http://paxswill.com/blog/2011/08/14/nsstring-cons/
//
// main.m
// NSStringCons
//
// Created by Will Ross on 8/12/11.
// Copyright (c) 2011 Naval Research Lab. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NSString+Cons.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *one = @"1";
NSString *two = @"2";
NSString *three = @"3";
NSLog(@"one:\t%@", one);
NSLog(@"two:\t%@", two);
NSLog(@"three:\t%@", three);
NSLog(@"all:\t%@", [one:two:three:nil]);
[pool drain];
return 0;
}
//
// NSString+Cons.h
// NSStringCons
//
// Created by Will Ross on 8/12/11.
// Copyright (c) 2011 Naval Research Lab. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (Cons)
+(BOOL)resolveInstanceMethod:(SEL)sel;
@end
//
// NSString+Cons.m
// NSStringCons
//
// Created by Will Ross on 8/12/11.
// Copyright (c) 2011 Naval Research Lab. All rights reserved.
//
#import "NSString+Cons.h"
#import <stdarg.h>
#import <objc/runtime.h>
id stringCons(id self, SEL selector, ...);
@implementation NSString (Cons)
+(BOOL)resolveInstanceMethod:(SEL)sel{
// Check that the selector is just ':' characters
const char *checkName = sel_getName(sel);
BOOL isCons = YES;
int i = 0;
char c = checkName[i];
while(c != '\0'){
if(c != ':'){
isCons = NO;
break;
}
c = checkName[++i];
}
// Add the method, or pass this message up the chain
if(isCons){
// Make the type string
size_t typesSize = 4 + i;
char *types = malloc(sizeof(char) * typesSize);
types[0] = '@';
types[1] = '@';
types[2] = ':';
for(int j = 3; j < typesSize - 1; ++j){
types[j] = '@';
}
types[typesSize - 1] = '\0';
// Add the method
class_addMethod([self class], sel, stringCons, types);
return YES;
}else{
return [super resolveInstanceMethod:sel];
}
}
@end
id stringCons(id self, SEL selector, ...){
va_list strings;
NSMutableString *fullString = [[NSMutableString alloc] initWithString:self];
va_start(strings, selector);
id currentString = nil;
// End on nil
while((currentString = va_arg(strings, id))){
[fullString appendString:currentString];
}
va_end(strings);
return fullString;
}
GNU gdb 6.3.50-20050815 (Apple version gdb-1706) (Tue Jul 19 23:33:12 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys001
sharedlibrary apply-load-rules all
[Switching to process 54318 thread 0x0]
2011-08-12 21:07:25.691 NSStringCons[54318:707] one: 1
2011-08-12 21:07:25.693 NSStringCons[54318:707] two: 2
2011-08-12 21:07:25.694 NSStringCons[54318:707] three: 3
2011-08-12 21:07:25.695 NSStringCons[54318:707] all: 123
Program ended with exit code: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment