【问题标题】:Replacing the content of UIImage(s) loaded from XIB at runtime替换运行时从 XIB 加载的 UIImage(s) 的内容
【发布时间】:2011-03-27 06:51:28
【问题描述】:

对于我正在开发的一个概念,我需要手动加载 XIB 文件,并通过使用类和实例方法调配,我已经能够拦截对 UIImage 类的 imageCustomNamed、imageCustomWithContentsOfFile 和 imageCustomWithCGImage 的调用以及 UIImageView 的 initCustomWithImage 调用。我想要的是检测图像名称并将其替换为动态呈现的一些内容,以代替设计时在 IB 中设置的内容。

例如:

当 XIB 有一个 UIImageView 对象,其 Image 属性设置为“About.png”时,我需要拦截该图像的加载并根据特定条件替换为另一个图像。 UIImageView 对象在设计时加载了图像集后,即使替换图像也可以,但看起来用于设置 UIImageView 内容的 UIImage 的原始名称没有存储在任何地方。

我无法使用 IBOutlets,因为我事先不知道 XIB 文件的内容;这是一个适用于任何 XIB 的类,而不仅仅是特定的。

自定义方法实际上被调用来代替默认方法,但看起来在加载 XIb 时,系统使用了接受 CGImageRef 作为参数的 imageCustomWithCGImage;从中无法知道来源(即:图像文件名)

知道如何拦截图像的加载吗?

【问题讨论】:

    标签: iphone objective-c uiimageview uiimage swizzling


    【解决方案1】:

    至少在 OS 3 中,您可以覆盖 UIImageNibPlaceholder 的 initWithCoder:。将其替换为以下内容:

    -(id)hack_UIImageNibPlaceholder_initWithCoder:(NSCoder*)coder
    {
      NSString * name = [coder decodeObjectForKey:@"UIResourceName"];
      [self release];
      return [[UIImage imageNamed:name] retain];
    }
    

    我不确定如果您从其他捆绑包(例如框架)加载 nib 会发生什么。

    【讨论】:

    • 我想过,但这是私人物品的一部分,所以这是不行的
    • 都是“私人物品”。无法保证您可以替换 +[UIImage imageNamed:] 并期望在操作系统更新后仍然可以正常工作。有时这是唯一的方法。
    • 您认为这会通过审核吗?替换 +[UIImage imageNamed:] 不会,但这是私有 api,尽管您没有替换任何下划线前缀方法
    • @nbransby 从我在线阅读的内容来看,自动私有 API 检测仅进行基本的静态分析,因此您可以使用 NSClassFromString()/NSSelectorFromString() 来解决问题。有些人添加了额外的混淆(例如 rot13),但我会避免它:Apple 可能不介意“负责任的私有 API 使用”,但这会越界。或者,不要使用笔尖。
    【解决方案2】:

    也许您可以在 xib 文件中设置 UIImageView 的另一个属性,然后引用该属性?比如标签,或者标签……

    【讨论】:

      【解决方案3】:

      混合私有类(UIImageNibPlaceholder) 的方法不是一个好主意。

      但是你可以重载它的超类(UIImage)的方法。好像 UIImageNibPlaceholder 没有实现 'awakeAfterUsingCoder',所以你可以安全地做到这一点,直到有一天苹果做到了。

      #import "UIImage+xib.h"
      
      @implementation UIImage (xib)
      
      - (id)awakeAfterUsingCoder:(NSCoder *)coder{
        NSString* imageName = [coder decodeObjectForKey:@"UIResourceName"];
        if(imageName){
           return [UIImage imageNamed:imageName];
        }
        return self;
      }
      
      @end
      

      【讨论】:

        猜你喜欢
        • 2015-10-30
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 2015-04-28
        • 2012-07-29
        • 2012-02-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多