替换运行时从 XIB 加载的 UIImage 的内容

发布于 2024-09-13 16:31:51 字数 619 浏览 10 评论 0原文

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

例如:

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

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

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

关于如何拦截图像的加载有什么想法吗?

For a concept I'm developing, I need to load XIB files manually and by using class and instance method swizzling I have been able to intercept calls to imageCustomNamed, imageCustomWithContentsOfFile and imageCustomWithCGImage for the UIImage class and initCustomWithImage for UIImageView. What I want to to is detect the image name and replace it with some content rendered on the fly in place of the one set in IB at design time.

for example:

when XIB has an UIImageView object whose Image property is set to "About.png", I need to intercept the loading of that image and replace with another one depending on certain condition. It would be ok even to replace the image after the UIImageView object has loaded the image set at design time, but looks like the original name of the UIImage used to set the content of UIImageView is not stored anywhere.

I cannot use IBOutlets as I don't know the content of XIB file before hand; this is a class that should work on any XIB not just a particular one.

The custom methods are in fact being called in placed of the default ones, but looks like that when loading XIb the system uses imageCustomWithCGImage which accept a CGImageRef as argument; from it there is no way to know the origin (i.e: the image file name)

Any idea on how I can intercept the loading of images?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微暖i 2024-09-20 16:31:51

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

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

我不确定如果从其他包(例如框架)加载笔尖会发生什么。

In OS 3, at least, you can override UIImageNibPlaceholder's initWithCoder:. Replace it with something like this:

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

I'm not sure what happens if you load nibs from other bundles (e.g. frameworks).

柳絮泡泡 2024-09-20 16:31:51

也许您可以在 xib 文件中设置 UIImageView 的另一个属性,然后引用该属性?例如标签、标记...

Perhaps you can set another property of UIImageView in xib file, and then reference that property? For example label, or tag...

只是一片海 2024-09-20 16:31:51

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

但您可以重载其超类(UIImage)的方法。似乎 UIImageNibPlaceholder 没有实现“awakeAfterUsingCoder”,所以你可以安全地执行此操作,直到有一天 Apple 实现了。

#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

It's not a good idea to swizzle a private class(UIImageNibPlaceholder)'s method.

But you can overload its superclass(UIImage)'s method. Seems like UIImageNibPlaceholder did't implement 'awakeAfterUsingCoder', so you can safely do this until Apple did it one day.

#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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文