使用 NSSet/allTargets 获取 xib 所谓的“文件所有者”?
Posted
技术标签:
【中文标题】使用 NSSet/allTargets 获取 xib 所谓的“文件所有者”?【英文标题】:Using NSSet/allTargets to get the xib so-called "File owner"? 【发布时间】:2013-12-05 08:42:55 【问题描述】:查看这张图片,您可以看到从 nib 加载的 UIView 有一个“文件所有者”
在 xib 中注意,Apple 已将某些内容标记为“文件所有者”。
所以,打开 Xcode,打开任意 xib,查看 Placeholders,然后直接查看下方,即可看到:
“文件所有者”。
在这个特定示例中,“xib-file-owner”恰好是类 LoginScreen。
因此,在运行时,对于由此 xib 创建的特定事物,“was-xib-file-owner”(创造一个短语)实际上是:
它将是:LoginScreen 类的某个特定实例。
现在在运行时。显然,在 UIView 中,每个 UIButton 都可以简单地调用
[self.someButton sendActionsForControlEvents:UIControlEventTouchUpInside ];
你确实可以“去”,准确地说:
您转到:LoginScreen 类的实例。
注意 - 当然,UIButton 可以指向任何地方。我问的是我们知道 UIButton 确实指向 UIButton 的“was-xib-file-owner”的情况。
事实上,allTargets
方法确实会返回该目标(在本例中是 LoginScreen 类的一些实例)作为它返回的 N 个目标的一部分,实际上是选择器(s) 等。
我还不够好,无法为 allTargets、NSSet 等编写代码。
谁能告诉我如何使用 allTargets 和一些计算机代码提取 LoginScreen 类的实例?即在 xib 中看到的“was-xib-file-owner”的运行实例?干杯。
稍后:
奇怪的是,这个问题的答案基本上和一般来说是:
[self.allTargets anyObject]
因为,如果从 xib 创建,将只有一个,而且,这正是上面粗体描述的内容。重复一遍:当然,UIButton 可以指向任何地方。我问的是我们知道 UIButton 确实指向 UIButton 的“was-xib-file-owner”的情况。
在那种(“正常”)情况下,答案确实非常简单——[self.allTargets anyObject]。
【问题讨论】:
为什么需要按钮的所有者? 您是指所有者还是容器? 有 N 个目标和 1 个超级视图... 0 个所有者 记录一下: giora:这是一个奇怪的问题,请注意苹果方法 sendActionsForControlEvents,例如,“需要”知道这一点。 anoop/daij:我的意思是“was-xib-file-owner”。当然,运行时没有“文件所有者”,所以我的意思是“was-xib-file-owner”。我已经编辑一遍又一遍地在问题中说明这一点,因为它可能会在未来帮助某人!干杯男人,真棒QA 【参考方案1】:在运行时视图不知道文件所有者(如 IB 中所示)。有关文件所有者的信息不存在。你可以做的最接近的是检查目标的类:
if([self respondsToSelector:@selector(allTargets)])
NSSet *owners = self.allTargets;
for(id owner in owners)
if([owner isKindOfClass:[UIViewController class]])
NSLog(@"owner: %@", owner);
或者只是假设目标是所有者
if([self respondsToSelector:@selector(allTargets)])
id owner = [self.allTargets anyObject];
NSLog(@"owner: %@", owner);
【讨论】:
再次:没有所有者,因为 Anoop 在他的回答中说:“文件的所有者只不过是一个代理,它在运行时获取类。” 不,运行时没有文件所有者...该信息不存在。 Danke .. 这个问题的实际答案基本上是:[self.allTargets anyObject],这很有趣! :) 你知道,我很好奇你为什么要检查 respondsToSelector ..? (如果是 UIButton,您可以调用 allTargets;问题是关于 UIButton。)您只是小心谨慎,还是有什么我不知道的?干杯! 小心点:防御性编程【参考方案2】:实际上按钮没有“所有者”。
UIButton 是特定视图的子视图,在 IB 中,您将按钮拖动到某个视图中,然后该按钮成为该视图的子视图。要检索按钮的超级视图,请调用 [myButton superview];
然后可以将 Button 引用为某个类的属性或 iVar,但它是另一回事。
【讨论】:
不,我的意思是从库中将一个按钮拖到视图中。当您说“所有者”时,您指的是 IB 中显示的文件所有者?因此,它通常是 VC,也可以是视图。使用 NSSet,您可以使用 anyObject 方法访问一个随机对象,但我不确定这就是您要查找的内容。 @JoeBlow 没有这样的所有者【参考方案3】:您有一个UIButton
,它为某些控制事件附加了目标(通常是UIControlEventTouchUpInside
)。
您可以按如下方式获取UIButton
的目标
NSSet *targets = [myButton allTargets];
for( NSObject *target in targets )
//Do something with target
//Maybe it's a view:
if( [target isKindOfClass:[UIView class]] )
//Do something to view specific target
需要注意两点:
目标不是UIButton
的“所有者”,也不需要是 UIView(如果我正确理解您的问题)。目标可以是任何对象,一般会从NSObject
派生。
Interface Builder 中的“文件所有者”只是“拥有”笔尖的UIViewController
(通常)的一个术语——它可能是也可能不是按钮的目标!
如果您确定您的按钮将您的文件所有者作为目标,那么您可以通过以下方式检查它(尽管我不建议这样编码):
//Assuming your File Owner is "LoginScreen" as in your picture
NSSet *targets = [myButton allTargets];
for( NSObject *target in targets )
//Is the target our File Owner class type?
if( [target isKindOfClass:[LoginScreen class]] )
LoginScreen *login = (LoginScreen *)target
//Do something with `login`
更好的方法是递归检查 UIButton 的 nextResponder,直到您点击管理视图控制器。我还没有测试过以下代码,但它遵循文档:
UIResponder *responder = [myButton nextResponder];
while( [responder isKindOfClass:[UIViewController class]] == NO &&
responder != nil )
responder = [responder nextResponder];
//If your button is "owned" in the responder chain
// by a UIViewController, then `responder` will be it
// otherwise `responder` will be nil
if( responder )
//Do something
但是,我不知道您为什么需要这样做。也许有更简单的解决方案来解决您的问题?
【讨论】:
Simeon,在您的代码示例二第 7 行中:** isKindOfClass:[LoginScreen class]** 我有两个难题:(A)您假设我的程序员知道它是 LoginScreen 类;没有更通用的解决方案吗? (即,我在问“对于 UIButton,如何确定 xib 上 FileOwner 的类是什么......”)。并且(B)可以匹配 LoginScreen 的“任何”实例(我相信?),我想找到实际的 LoginScreen(很可能是 UIViewController),它确实是那个 xib 的 FileOwner。有什么想法吗?! :) 更通用的解决方案可能是检查isKindOfClass:[UIViewController class]
,因为它会找到作为目标附加到按钮的任何视图控制器。我的解决方案的后半部分(使用nextResponder
)将找到按钮的最近的视图控制器“父级” - 但是,它可能会或可能不会作为目标附加。
也许最好的答案是,如果您的程序员知道 UIButton 是 UIButton 的常见类型,那么确实 all 目标确实是实例-- the-FileOwnerClass:然后,只需在 Simeon 的代码的第 9 行取第一项(不管是哪一项).. 确实这就是答案。 (事实上,目标确实是通过加载 xib 并使用“FileOwner”这是由 xib-loader 理解/知道的创建的,这对于 UIView/UIButton 本身来说是完全未知的。)控件上没有标志'哦,这个目标恰好是从 xib/FileOwner 加载的。
simeon,虽然您是第一个了解并确实详细解释了情况的人,但由于他给出了结论性代码(我现在使用它!),因此单击“赏金”给 daij 似乎是合适的。的确,他事先已经在努力解决这个问题。我希望你们俩都没事。 (不能随心所欲地点击尽可能多的“赏金”,这是愚蠢的。)再次非常感谢你,Simeon!以上是关于使用 NSSet/allTargets 获取 xib 所谓的“文件所有者”?的主要内容,如果未能解决你的问题,请参考以下文章