2012-01-10 83 views
4

我想在運行時添加一個屬性實現方法。添加我使用+ resolveInstanceMethod,class_addMethod來做。但在代碼下面,在dynamicN()和dynamicSetN()中,它們不能被編譯,我不知道如何使用C函數來設置/獲取實例變量而不合成屬性。如何生成動態屬性getter/setter?

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

float dynamicN(id self, SEL _cmd) 
{ 
    NSString *methodName = NSStringFromSelector(_cmd); 
    NSLog(@"%@,%@", methodName, [self description]); 
    // return [self n]; 
} 

void dynamicSetN(id self, SEL _cmd, float sname) 
{ 
    printf("setName start;\n"); 
    // self.n = sname; 
} 


@interface bird : NSObject 
{ 
    int height; 
    float n; 
} 

@property float n; 
@property int height; 

@end 

@implementation bird 
@synthesize height = height; 
@dynamic n; 

- (id)init 
{ 
    if (self = [super init]) { 
     n = 1.0; 
     height = 3; 
    } 
    return self; 
} 

- (float) n { 
    return n; 
} 

+ (BOOL) resolveInstanceMethod:(SEL)aSEL 
{ 
    if (aSEL == @selector(n)) { 
     //class_addMethod([self class], aSEL, (IMP) dynamicN, "[email protected]:"); 
     //return YES; 
    } 
    if (aSEL == @selector(setN:)) { 
     class_addMethod([self class], aSEL, (IMP) dynamicSetN, "[email protected]:f"); 
     return YES; 
    } 
    return [super resolveInstanceMethod:aSEL]; 
} 
@end 

int main(int argc, const char *argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    bird *aBird = [[bird alloc] init]; 
    aBird.n = 3; 
    printf("\n%f\n,%d", aBird.n, aBird.height); 
    [pool drain]; 
    return 0; 
} 
+0

請添加您從編譯器獲得的錯誤消息。 – 2012-01-10 18:51:42

回答

2

@ H2CO3對於您的二傳手是正確的。動態吸氣器具有相同的基本問題。您正嘗試撥打[self n],這在id上不存在。 這就是爲什麼它不會編譯。 (As @ H2CO3注意到,這會產生一個警告,而不是一個錯誤;你們都使用-Werror,對吧?)但更重要的是,即使這樣做,這將是一個無限循環。 self.n只是致電[self n],它將發回此功能。

如果您正在尋找示例,您可以下載iOS 6 Programming Pushing the Limits的第20章的代碼。查看Person項目Person.m。如果你感興趣的話,第28章會詳細解釋如何實現這種功能。

請注意,在ObjC中正確命名非常重要。你的班級應該是Bird,而不是bird。在嘗試諸如動態分發之類的高級功能之前,獲取命名基礎知識至關重要。

2

您的二傳手不能編譯,因爲你的self參數的類型是「ID」,這本身沒有名爲「n」的財產。你要投那麼直接取消對它的引用:

((bird *)self)->n = sname; 

你消氣似乎不錯,雖然,我不知道爲什麼它不能被編譯。

+0

getter自己調用並且在運行時不起作用。需要進行與setter相同的字段訪問才能獲得返回值。不過,我看不出爲什麼它不能編譯。 – 2012-01-10 18:51:23

+0

類型「id」在語法上沒有名爲「n」的屬性。編譯器不知道它實際上是否響應-n或-setN:方法(這是動態的價格) – 2012-01-10 19:57:53

+0

是否意味着(id)-dynamic類型綁定的使用與C函數中的靜態類型不同? objective-c方法中靜態類型和動態類型之間是否存在一些差異? – 2012-01-11 07:19:06

相關問題