目标 C - [self.view viewWithTag] 返回 null

ObjectiveC - [self.view viewWithTag] returning null

我完全被难住了,已经研究了好几天了。可能是我遗漏的非常简单的东西。

我有一个 ViewController,其中包含一个名为 GameView 的自定义 UIView,以及一个名为 buttonBox 的 UIView,其中包含一个 "next level" 按钮。我想要实现的是当关卡在 GameView 中完成时,它会在我的 ViewController 中触发一个显示按钮框的函数,以便用户可以单击 "next level" 按钮。它根本行不通。

我尝试了 3 种方法,都没有用:

ViewController的相关代码如下:

@interface PlayViewController : UIViewController
@property GameView *gv;
@property (strong, nonatomic) IBOutlet UIView *buttonBox;
-(void) showButtonBox;
@end

@implementation PlayViewController
@synthesize buttonBox;
...
- (IBAction)showButtonBox {
    UIView *uiv = (UIView*) [self.view viewWithTag:999];
    dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Showing box function");
        NSLog(@"%@", uiv);
        uiv.hidden = NO;
    });
}
@end

我的自定义视图:

@implementation GameView
...
   dispatch_async(bgQueue, ^{
        _loopRunning = true;
        //NSLog(@"Calling main loop...");
        while ([self loopRunning])
        {
             ...
             PlayViewController * pvc = [[PlayViewController alloc]init];
             [pvc showButtonBox];
             ...
         }
@end

问题是,变量 uiv 在 NSLog 中返回 null,这显然是 hidden 不起作用的原因,但我不知道为什么。当我使用 IBOutlet.

时它也不起作用

此外,NSLog 的当前输出如下:

2015-11-24 00:18:38.612 ib[12579:1264539] Showing box function
2015-11-24 00:18:38.612 ib[12579:1264539] (null)

提前致谢。

正确答案:

问题是我使用 StoryBuilder 来构建我的 UI,但是通过使用 alloc init 方法创建了一个新的视图控制器(从未显示)而不是正确引用视图控制器正在显示。这是通过将正在显示的视图控制器传递给 viewDidLoad 函数中的视图来实现的,见下文:

@implementation PlayViewController
@synthesize buttonBox;
@synthesize gv;

- (void)viewDidLoad
{
    [super viewDidLoad];
    gv = [self.view viewWithTag:777];
    [gv setPlayViewController:self];
}
...

伙计,这很简单。一起来看看:

@implementation GameView
...
   dispatch_async(bgQueue, ^{
        _loopRunning = true;
        //NSLog(@"Calling main loop...");
        while ([self loopRunning])
        {
             ...
             PlayViewController * pvc = [[PlayViewController alloc]init];
             [pvc showButtonBox];
             ...
         }
@end

这里有问题:

dispatch_async(bgQueue, ^{

我假设,bgQueue 代表 "background queue",这意味着这不是由主线程(UI 线程)提供的。 话虽如此,期望

是相当天真的

[pvc showButtonBox];

才能正常工作。只需将此代码移至主线程即可。例如,您可以将上述代码行包装到主队列中的 dispatch_async 中。如果您的 outlets and/or 标签没问题,那应该可以解决您的问题。干杯。

[[PlayViewController alloc]init];

这将创建 PlayViewController 的新实例。您在哪里定义了您的渠道和观点?

  • 在情节提要中?你不能使用这个初始化器 - 故事板中的任何东西都不会被拾取,你必须使用 segue 或 initializeViewControllerWithIdentifier:
  • 在 xib 文件中?是叫PlayViewController.xib吗?如果不是,它不会被初始化器拾取。视图控制器的普通 alloc/init 只会找到 documentation of the nibName property 中描述的 nib 文件。
  • 你真的想要 alloc / init 吗?您真的想制作一个 视图控制器,还是已经在屏幕上了?

从您的评论来看,选项 3 似乎是正确的答案。 PlayViewController 已经在屏幕上,alloc/init 正在创建它的一个新实例,它永远不会被放在屏幕上,无论故事板或笔尖如何,它都不会加载任何视图。

您需要获取对 PlayViewController 现有 实例的引用。在不知道您的应用程序结构的情况下,很难说出它是如何完成的——它是否呈现游戏视图?游戏视图是视图控制器视图的子视图吗?您可能需要在创建游戏视图时在 viewDidLoad 处传递对游戏视图的引用(弱),或者在情节提要中设置出口。