0

我正在玩调酒,但不太明白这一点。我的 alloc swizzle 看起来像这样:

@interface UIAlertView (Custom)
+ (id)allocCustom;
@end

@implementation UIAlertView (Custom)    
+ (void)load
{
    Method original;
    Method mock;
    original = class_getClassMethod(self, @selector(alloc));
    mock = class_getClassMethod(self, @selector(allocCustom));
    method_exchangeImplementations(mock, original);
}

+ (id)allocCustom
{
    NSLog(@"Custom!");
    return [self allocCustom];
}    
@end

如果我在重复调用的 NSLog 语句处暂停,在调用堆栈中我会看到:

* thread #1: tid = 0x2c388a, 0x00003a2f My App`+[UIAlertView(self=0x03825c74, _cmd=0x0327e663) allocCustom] + 31 at MYClass.m:62, queue = 'com.apple.main-thread, stop reason = breakpoint 4.1
    frame #0: 0x00003a2f My App`+[UIAlertView(self=0x03825c74, _cmd=0x0327e663) allocCustom] + 31 at iBFGClientAppDelegate.m:62
    frame #1: 0x036c7b42 CoreFoundation`+[NSTimeZone timeZoneWithName:] + 34
    frame #2: 0x036c7a52 CoreFoundation`+[NSTimeZone systemTimeZone] + 626
    frame #3: 0x036c7767 CoreFoundation`+[NSTimeZone defaultTimeZone] + 71
    frame #4: 0x036e82cd CoreFoundation`CFTimeZoneCopyDefault + 45
    frame #5: 0x036f8b90 CoreFoundation`CFCalendarCreateWithIdentifier + 544
    frame #6: 0x03705f2c CoreFoundation`__CFLogCString + 124
    frame #7: 0x03705e6e CoreFoundation`_CFLogvEx + 270
    frame #8: 0x01581fbc Foundation`NSLogv + 137
    frame #9: 0x01581f28 Foundation`NSLog + 27
    frame #10: 0x00003a3a My App`+[UIAlertView(self=0x03825c74, _cmd=0x0327e663) allocCustom] + 42 at MYClass.m:62
    frame #11: 0x036c7b42 CoreFoundation`+[NSTimeZone timeZoneWithName:] + 34
    frame #12: 0x036c7a52 CoreFoundation`+[NSTimeZone systemTimeZone] + 626
    frame #13: 0x036c7767 CoreFoundation`+[NSTimeZone defaultTimeZone] + 71
    frame #14: 0x036e82cd CoreFoundation`CFTimeZoneCopyDefault + 45
    frame #15: 0x036f8b90 CoreFoundation`CFCalendarCreateWithIdentifier + 544
    frame #16: 0x03705f2c CoreFoundation`__CFLogCString + 124
    frame #17: 0x03705e6e CoreFoundation`_CFLogvEx + 270
    frame #18: 0x01581fbc Foundation`NSLogv + 137
    frame #19: 0x01581f28 Foundation`NSLog + 27
    frame #20: 0x00003a3a My App`+[UIAlertView(self=0x01800f3c, _cmd=0x0327e663) allocCustom] + 42 at MYClass.m:62
    frame #21: 0x023fb8ae UIKit`UIApplicationMain + 60
    frame #22: 0x0000293b My App`main(argc=1, argv=0xbfffedac) + 75 at main.m:18

似乎 timeZoneWithName: 正在回调我的自定义 alloc 方法。显然,当 alloc 没有被混合时没有递归,但我很困惑这里发生了什么。

4

2 回答 2

2

您的问题很可能发生,因为您正在使用 method 调配一个方法,这是一个方法allocCustomon 。根据我的发现,您可以成功地 swizzle的 alloc 方法,但似乎您不能从子类中做到这一点。您可以通过将以下内容添加到您的类别来查看证明情况的证据:UIAlertViewallocNSObjectNSObjectUIAlertView

+ (id)alloc
{
    return [super alloc];
}

通过这样做,它现在可以正常工作。但是由于alloc是一个方法NSObject并且显然不会被覆盖UIAlertView,你可以删除你的方法调配,并将你的代码添加到你的覆盖alloc方法中:

+ (id)alloc
{
    NSLog(@"Custom!");
    return [super alloc];
}

现在这样做可能有点危险,以防 Apple 在未来更改其实施并且由于某种原因allocUIAlertView. 在这种情况下,我认为您的实现会覆盖他们的实现,尽管我认为确切的行为在技术上是未定义的。

于 2014-02-14T19:19:38.047 回答
0

我不是方法调配方面的专家,但我猜因为你allocCustom是一个类方法,self实际上是指类本身。你真正想要的是这样的

+(id) allocCustom {

 id obj = calloc(class_getInstanceSize(self), 1);
 obj->isa = self;
 obj->retainCount = 1;
 return obj;
}

此链接可能对您有用:https ://www.mikeash.com/pyblog/friday-qa-2013-01-25-lets-build-nsobject.html

于 2014-02-14T19:05:54.013 回答