認識されないセレクタ例外をスローする代わりに、メッセージ転送を使用して、実装されていない getter メソッドが 0 を返すようにしたいと考えています。お気に入り
MyClass *r = [[MyClass alloc] init];
NSNumber *n = (NSNumber *)r;
NSLog(@"%d", [n integerValue]); // output 0
NSLog(@"%f", [n doubleValue]); // output 0.00000
NSLog(@"%@", [n stringValue]); // output (null)
だから私はこの例を書いた:
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSNumber *n = (NSNumber *)self;
NSLog(@"%d", [n integerValue]);
NSLog(@"%f", [n doubleValue]);
NSLog(@"%@", [n stringValue]);
return YES;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *ms = [super methodSignatureForSelector:aSelector];
if(ms)
return ms;
// Q = uint64_t, so it should also works for double which is also 64bit
return [NSMethodSignature signatureWithObjCTypes:"Q@:"];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
uint64_t ZERO64 = 0;
[anInvocation setReturnValue:&ZERO64];
}
実機での出力結果は 0, 0.00000, (null) ですが、エミュレータでは 0, NaN, (null) です。
そのため、double 型は期待どおりに動作しません。私の最初の考えは、NSMethodSignature を "d@:" (d は double) に変更することです。
出力結果はデバイスとシミュレータの両方で正しいですが、シミュレータでのみ奇妙なことが起こっています。このコードを実行すると、ある種の CALayer 例外で 6 番目のループでクラッシュします。
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
for(NSInteger i = 0; i < 100; i++) {
NSInteger t = [(NSNumber *)self integerValue];
UIViewController *view = [[UIViewController alloc] init];
// it always crash on the 6th loop on this line**
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:view];
}
return YES;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *ms = [super methodSignatureForSelector:aSelector];
if(ms)
return ms;
// we change to return double
return [NSMethodSignature signatureWithObjCTypes:"d@:"];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
uint64_t ZERO64 = 0;
[anInvocation setReturnValue:&ZERO64];
}
最初の例でエミュレーターで NaN が返される理由と、2 番目の例で何が起こったのかという 2 つの質問に興味があります。