Iphone 访问OCUnit测试目标内的UIImage

Iphone 访问OCUnit测试目标内的UIImage,iphone,objective-c,ipad,unit-testing,ocunit,Iphone,Objective C,Ipad,Unit Testing,Ocunit,我目前正在为一款iPad应用程序编写一个图像处理测试。我在单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用[UIImage ImageName:@“photo1.jpg”访问它时,没有返回任何图像。如果我将主资源文件夹中的文件名更改为1,则会返回一个图像 有办法访问单元测试目标内的Resources文件夹吗?找到了此问题的答案,看起来您无法使用[UIImage ImageName:],您可以这样访问图像: NSBundle *bundle = [NSBundle bundleFo

我目前正在为一款iPad应用程序编写一个图像处理测试。我在单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用[UIImage ImageName:@“photo1.jpg”访问它时,没有返回任何图像。如果我将主资源文件夹中的文件名更改为1,则会返回一个图像


有办法访问单元测试目标内的Resources文件夹吗?

找到了此问题的答案,看起来您无法使用[UIImage ImageName:],您可以这样访问图像:

NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *imagePath = [bundle pathForResource:@"photo1" ofType:@"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];

您可以使用以下类别(但仅将其添加到测试目标!)。它将使UIImage ImageName:方法在测试目标中自动工作:

.h文件

/**
 * UIImage imageNamed: method does not work in unit test
 * This category provides workaround that works just like imageNamed method from UIImage class.
 * Works only for png files. If you need other extension, use imageNamed:extension: method.
 * NOTE: Do not load this category or use methods defined in it in targets other than unit tests
 * as it will replace original imageNamed: method from UIImage class!
 */
@interface UIImage (ImageNamedForTests)

/**
 * Returns image with the specified name and extension.
 * @param imageName Name of the image file. Should not contain extension.
 * NOTE: You do not have to specify '@2x' in the filename for retina files - it is done automatically.
 * @param extension Extension for the image file. Should not contain dot.
 * @return UIImage instance or nil if the image with specified name and extension can not be found.
 */
+ (UIImage *)imageNamed:(NSString *)imageName extension:(NSString *)extension;


@end
.m文件

#import "UIImage+ImageNamedForTests.h"
#import <objc/runtime.h>

@implementation UIImage (ImageNamedForTests)

+ (void)load {
    [self swizzleClassMethod];
}

+ (void)swizzleClassMethod {
    SEL originalSelector = @selector(imageNamed:);
    SEL newSelector = @selector(swizzled_imageNamed:);
    Method origMethod = class_getClassMethod([UIImage class], originalSelector);
    Method newMethod = class_getClassMethod([UIImage class], newSelector);
    Class class = object_getClass([UIImage class]);
    if (class_addMethod(class, originalSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
        class_replaceMethod(class, newSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, newMethod);
    }
}

+ (UIImage *)swizzled_imageNamed:(NSString *)imageName {
    return [self imageNamed:imageName extension:@"png"];
}

+ (UIImage *)imageNamed:(NSString *)imageName extension:(NSString *)extension {
    NSBundle *bundle = [NSBundle bundleForClass:[SomeClassFromUnitTestTarget class]];//Any class from test bundle can be used. NOTE: Do not use UIImage, as it is from different bundle
    NSString *imagePath = [bundle pathForResource:imageName ofType:extension];
    return [UIImage imageWithContentsOfFile:imagePath];
}
#导入“UIImage+ImageNamedForTests.h”
#进口
@实现UIImage(ImageNamedForTests)
+(空)荷载{
[自选方法];
}
+(void)swizzleClassMethod{
SEL originalSelector=@选择器(ImageName:);
SEL newSelector=@选择器(swizzled_ImageName:);
Method OrigmMethod=class_getClassMethod([UIImage class],originalSelector);
方法newMethod=class_getClassMethod([UIImage class],newSelector);
Class Class=object_getClass([UIImage Class]);
if(class_addMethod(class,originalSelector,method_getImplementation(newMethod),method_getTypeEncoding(newMethod))){
类_replaceMethod(类、新闻选择器、方法_getImplementation(origMethod)、方法_getTypeEncoding(origMethod));
}否则{
方法交换实施(原始方法,新方法);
}
}
+(UIImage*)swizzled_imageName:(NSString*)imageName{
返回[self-imageName:imageName扩展名:@“png”];
}
+(UIImage*)imageName:(NSString*)imageName扩展名:(NSString*)扩展名{
NSBundle*bundle=[NSBundle bundleForClass:[SomeClassFromUnitTestTarget类]];//可以使用测试捆绑包中的任何类。注意:不要使用UIImage,因为它来自不同的捆绑包
NSString*imagePath=[bundle pathForResource:imageName of Type:extension];
返回[UIImage imageWithContentsOfFile:imagePath];
}

为这一点做了一个方便的分类

image = [UIImage testImageNamed:@"image.png"];
就像:

@interface BundleLocator : NSObject
@end

@interface UIImage (Test)
+(UIImage*)testImageNamed:(NSString*) imageName;
@end

@implementation BundleLocator
@end

@implementation UIImage (Test)
+(UIImage*)testImageNamed:(NSString*) imageName
{
    NSBundle *bundle = [NSBundle bundleForClass:[BundleLocator class]];
    NSString *imagePath = [bundle pathForResource:imageName.stringByDeletingPathExtension ofType:imageName.pathExtension];
    return [UIImage imageWithContentsOfFile:imagePath];
}
@end

从iOS 8开始,我们就有了:
-imagename:inBundle:compatibleWithTraitCollection:
UIImage上的failable init

迅速:

let bundle = NSBundle(forClass: self.dynamicType)
let image:UIImage? = UIImage(named: "imageFileName",
                          inBundle:bundle,
     compatibleWithTraitCollection:nil)
在Objective-C中

NSBundle* bundle = [NSBundle bundleForClass:[self class]];
UIImage* image = [UIImage imageNamed:@"imageFileName.extension"
                             inBundle:bundle
        compatibleWithTraitCollection:nil];

这个答案应该在最上面。我已经为UIImage创建了一个新的初始化器来完成它已经完成的工作。我现在觉得有点傻。