【问题标题】:Using NSSet/allTargets to get the xib so-called "File owner"?使用 NSSet/allTargets 获取 xib 所谓的“文件所有者”?
【发布时间】: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

标签: ios objective-c uiview uicontrol


【解决方案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!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多