更改使用 loadNibNamed 实例化的类

Posted

技术标签:

【中文标题】更改使用 loadNibNamed 实例化的类【英文标题】:Change classes instantiated with loadNibNamed 【发布时间】:2010-05-04 09:31:42 【问题描述】:

我正在尝试使用 iPhone SDK 更改使用 nib 创建的对象的类别。

这样做的原因是;直到运行时我才知道我希望 nib 对象是什么类(尽管它们将具有相同的基于 UIView 的超类),并且我不想为每种可能性创建不同的 nib - 因为 .nib 将是除了一个对象的类之外,每个对象都相同。

我已经成功了,使用了几种方法,但要么有一些连锁反应,要么不确定我使用的方法有多安全:

方法一:在超类上覆盖alloc,并为我需要的类设置一个c变量:

+ (id) alloc 
 if (theClassIWant) 
  id object = [theClassIWant allocWithZone:NSDefaultMallocZone()]; 
  theClassIWant = nil;
  return object;
 
 return [BaseClass allocWithZone:NSDefaultMallocZone()];

这很好用,我认为是“合理”安全的,但如果有一个具有正确类的 nib 作为 Nib 中的类标识,或者我自己分配一个子类(不设置“theClassIWant”) - 一个对象基类已创建。我也不太喜欢覆盖 alloc 的想法...

方法2:在initWithCoder中使用object_setClass(self,theClassIWant)(在超类调用initWithCoder之前):

- (id) initWithCoder:(NSCoder *)aDecoder 
 if (theClassIWant) 

  // the framework doesn't like this:
  //[self release];  
  //self = [theClassIWant alloc];

  // whoa now! 
  object_setClass(self,theClassIWant);

  theClassIWant = nil;
  return [self initWithCoder:aDecoder];
 

 if (self = [super initWithCoder:aDecoder]) 
           ...

这也很有效,但并不是所有的子类都必须与超类的大小相同,所以这可能非常不安全!为了解决这个问题,我尝试在 initWithCoder 中释放并重新分配正确的类型,但我从框架中得到以下错误:

"此编码器要求从 initWithCoder 返回替换的对象:"

不太明白这意味着什么!我正在替换 initWithCoder 中的一个对象...

欢迎任何关于这些方法有效性的cmet,或改进或替代的建议!

【问题讨论】:

实际上我已经改进了方法 1,如果未设置“theClassIWant”,则使用“self”作为类。我意识到 self 可以在类方法中使用。即返回 [self allocWithZone:NSDefaultMallocZone()]; +1 表示无所畏惧地滥用语言。 【参考方案1】:

虽然我很想知道您是否可以使用您的方法实现这一目标,但您可能需要考虑使用 custom placeholder objects。

【讨论】:

嗨,我在这些方法中使用自定义占位符对象(因为超类是在笔尖中设置的自定义占位符对象)。问题是我无法在任何地方在运行时设置类。看来您可以用 loadNibNamed:owner:options: 中的 options 参数替换代理对象,但这对我的基于视图的对象没有帮助......或者我错过了什么?

以上是关于更改使用 loadNibNamed 实例化的类的主要内容,如果未能解决你的问题,请参考以下文章

用户创建的类对象实例化的未声明标识符

在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型

Java:Effective java学习笔记之 通过私有构造器强化不可实例化的能力

在 Python 中,如何在重新加载后更改实例化对象?

如何强制 Java 在实例化时重新加载类?

在 Swift 中使用 MagicalRecord 实例化的向下转型 CoreData 实体