UIImage imageNamed扩展名

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

我想知道是否有一个“插入”的解决scheme,以这种“错误”logging在某种方式? 我开始写一个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 

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

有什么build议么?

谢谢Thomas

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

相反,您可以使用objc运行时的可能性将一个select器的实现与另一个select器交换(有时称为方法调整 )。 但是如果你不了解其中的含义,我会劝阻你这样做 。 (如果要调用原始函数以避免调用循环,请调用交换方法,在父类中实现该方法但在子类中实现时pipe理该用例,以及更多微妙之处)


但是,如果你只想debugging,并没有findUIImage时提醒使用符号断点 ! (断点不限于放在给定的代码行上 !)

断点比你想象的更强大(我鼓励你观看关于“掌握Xcode中的debugging”的WWDC'11video会话),尤其是你可以在你的代码中放置一个不在特定行上的断点 ,而是在一个特定的方法调用 (在你的情况下,方法-imageNamed: ,并添加一个条件的断点,所以它只会在一定的条件下(返回图像无?)。 你甚至可以要求断点logging一些信息 (或播放声音或其他),或者继续执行,而不是停止执行代码。

你想要做的就是调用swizzling :你交换两个方法,所以你现在调用你自己的方法,而你可以在你的方法的名字下访问原来 方法。 起初似乎有点混淆,但这是它的工作原理:

 #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