【问题标题】:Saving high-resolution resources so that the app knows it can use them on retina devices保存高分辨率资源,以便应用知道它可以在视网膜设备上使用它们
【发布时间】:2013-02-04 18:02:00
【问题描述】:

我的应用程序尺寸很大,因为它是通用的并且专为 Retina 显示器而设计。我想允许用户从我的服务器下载 Retina 图像,而不是最初将它们包含在应用程序中。

我用下面的代码试过了。唯一的问题是图像存储在 Documents 文件夹中,应用程序不会将它们识别为 Retina 图像

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.test.com/img2@2x.png"]]];
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngFilePath = [NSString stringWithFormat:@"%@/img2@2x.png",docDir];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
[data1 writeToFile:pngFilePath atomically:YES];

我应该如何保存图像以允许应用使用它们?

【问题讨论】:

    标签: ios objective-c image retina-display file-management


    【解决方案1】:

    imageWithData: 方法将始终创建比例为 1.0(非视网膜)的图像。从捆绑包外的自定义位置创建视网膜感知 UIImage,您需要使用 initWithCGImage:scale:orientation: 方法:

    UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.test.com/img2@2x.png"]]];
    UIImage *retinaImage = [UIImage initWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];
    

    (而且,显然,您不应该同步下载图像...)。

    我需要在我上一个项目中做同样的事情(从文档目录加载与比例相关的图像),所以我在 UIImage 类别中编写了一个小方便方法:

    - (id)initWithContentsOfResolutionIndependentFile:(NSString *)path
    {
        if([[UIScreen mainScreen] scale] == 2.0) {
            NSString *path2x = [[path stringByDeletingLastPathComponent]
                                stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.%@",
                                                                [[path lastPathComponent] stringByDeletingPathExtension],
                                                                [path pathExtension]]];
    
            if([[NSFileManager defaultManager] fileExistsAtPath:path2x]) {
                return [self initWithCGImage:[[UIImage imageWithData:[NSData dataWithContentsOfFile:path2x]] CGImage] scale:2.0 orientation:UIImageOrientationUp];
            }
        }
    
        return [self initWithContentsOfFile:path];
    }
    

    用法:

    UIImage *myImage = [[UIImage alloc] initWithContentsOfResolutionIndependentFile:@"/path/to/image.png"];
    

    这将尝试在视网膜上从/path/to/image@2x.png 加载图像,否则使用/path/to/image.png

    【讨论】:

      【解决方案2】:

      它不起作用,因为 UI 图像的来源是 Bundle 而不是 NSDocumentDirectory 文件夹。要使用视网膜和非视网膜图像,您应该检测设备是否是视网膜并以编程方式从 NSDocumentDirectory 加载图像。

      您可以使用this 进行视网膜检测。

      【讨论】:

      • 我如何从 NSDocumentDirectory 中加载图像?
      • 使用您的代码,添加UIImage *image = [UIImage imageWithContentsOfFile:pngFilePath];,其中 pngFilePath 是图像路径。
      • @aLFaRSi 请查看我的答案以获取示例和更多 cmets。
      【解决方案3】:

      您可以使用[UIImage imageWithData: scale:] 并且能够跳过“@2x”命名约定:

      - (UIImage *)getRetinaSafeImage: (NSString *)fileName
      {
          // alternatively you can use NSURL instead of path
          NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
          NSData *myImageData = [NSData dataWithContentsOfFile: [NSString stringWithFormat:@"%@/%@",docDir, fileName]];
      
          if([[UIScreen mainScreen] scale] == 2.0)
              return [UIImage imageWithData:myImageData scale:2.0];
          else return [UIImage imageWithData:myImageData];
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        相关资源
        最近更新 更多