UIImage imageNamed扩展名

tho*_*ert 1 uiimage ios

我最近在我的应用程序中发现了一个相当大的性能问题,这是由于在[UIImage imagenamed:]中找不到图像.

我想知道是否有"插入式"解决方案以某种方式记录这种"错误"?我开始编写UIImage类的扩展,如下所示:

@implementation UIImage (Debug)
#ifdef DEBUG
+ (UIImage*) imageNamed:(NSString*) name{
    UIImage* img = [UIImage imageNamed:name];

    if(!img){
        NSLog(@"Error: referencing non-exiting image: %@", name);
    }

    return img;
}
#endif
@end
Run Code Online (Sandbox Code Playgroud)

但这导致无限循环,因为[UIImage imageNamed:name]当然会导致再次调用扩展方法...

有什么建议?

谢谢托马斯

Ali*_*are 6

永远不应该使用类别来覆盖现有方法.这将导致意外结果(使用的实现将取决于运行时加载二进制映像/模块的顺序).

相反,您可以使用objc运行时的可能性来交换一个选择器与另一个选择器的实现(有时称为方法调配).但如果你真的不知道其含义,我会劝阻你这样做.(如果要调用原始文件以避免调用循环,请调用交换方法,在父类中实现方法时管理用例,而不是子项,以及更多细微之处)


但是,如果您只想调试并在未找到UIImage时收到警报,请使用符号断点!(断点不限于放在给定的代码行上!)

断点是更强大的比你能想象(我建议你看WWDC'11约"在Xcode掌握调试"视频会话),尤其是你可以放置一个断点不会在您的特定代码行,但在特定的方法调用(在你的情况下是方法-imageNamed:),并为断点添加一个条件,这样它只会在特定条件下被击中(返回的图像为零?).您甚至可以要求断点记录一些信息(或播放声音或其他)和/或继续执行而不是停止代码执行.


Dar*_*ust 6

你想要做什么是所谓的混写:你交换两种方法让你自己的方法现在被称为代替,你可以访问原来的名下方法方法.起初看起来有点令人困惑,但这是它的工作原理:

#import <objc/runtime.h>    

@implementation UIImage(Debug)

// Executed once on startup, before anything at UIImage is called.
+ (void)load
{
    Class c = (id)self;

    // Use class_getInstanceMethod for "normal" methods
    Method m1 = class_getClassMethod(c, @selector(imageNamed:));
    Method m2 = class_getClassMethod(c, @selector(swizzle_imageNamed:));

    // Swap the two methods.
    method_exchangeImplementations(m1, m2);
}

+ (id)swizzle_imageNamed:(NSString *)name
{
    // Do your stuff here. By the time this is called, this method
    // is actually called "imageNamed:" and the original method
    // is now "swizzle_imageNamed:".

    doStuff();
    // Call original method
    id foo = [self swizzle_imageNamed:name];
    doMoreStuff();
    return something;
}

@end
Run Code Online (Sandbox Code Playgroud)

  • @AliSoftware:谢谢,你对'+ load`是正确的.我找到了一个答案,提出了另一个好的解决方案:[__ attribute__((constructor))](http://stackoverflow.com/questions/4668887/objective-c-is-it-safe-to-overwrite-nsobject-initialize/4671741 #4671741). (2认同)