为什么我的 IBOutlet 在 ARC 下被释放?

6

问题

在我有机会使用它之前,IBOutlet 就被释放了。

希望实现的功能

我想从我的应用程序委托中访问导航控制器,以便我可以重新加载表视图。

我的设置

我有:

  • 一个 Main.xib,它在目标设置中设置为我的主要界面
  • 将导航控制器作为 app 委托的 ivar 的 IBOutlet
  • 此 IBOutlet 钩接到 Main.xib 中正确的导航控制器
  • 应用程序委托在 xib 中被实例化,但未设置为文件所有者

我正在使用 ARC、Xcode 4.3.2 和 iOS5.1

我尝试过的

  • 更改部署目标
  • 在导航控制器、应用程序委托的 dealloc 上设置断点,但它们从未被调用
  • 阅读我能找到的有关 ARC 和 IBOutlet 的所有内容 - 没有任何东西似乎与我所做的相矛盾
  • 创建一个只包含所需最小类的全新项目 - 我看到完全相同的问题

代码

KPAppDelegate.h

@interface KPAppDelegate : UIResponder <UIApplicationDelegate> {
    IBOutlet  KPBrowseExpensesNavigationController *nc;
}

@property (strong) IBOutlet KPBrowseExpensesNavigationController *nc;

KPAppDelegate.m

@implementation KPAppDelegate

@synthesize nc;

-(void)setNc:(KPBrowseExpensesNavigationController *)nc_ {
    nc = nc_; // This gets called on view load and nc gets set.
}

...snip...

// This is called about 5 seconds after app startup
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
        // By the time we get here, nc is nil.
        UITableViewController *tvc = [[nc viewControllers] objectAtIndex:0];
        [[tvc tableView] reloadData];
}

@end

更新

我肯定在这里做了什么非常愚蠢的事情。即使是一个非常简单的项目仍然会出现这个问题。请参见下面的链接。

下载一个展示该问题的简单测试项目。


1
非常非常好的问题示例。 - James Webster
4个回答

2

您的 Interface Builder 中的输出口是否设置为 KPBrowseExpensesNavigationController 类型?如果没有,它将无法在您的 nib 和 ViewController 之间建立连接。

您应该在 Identity Inspector 中将其自定义类设置为 KPBrowseExpensesNavigationController。


仍然无法工作。插座/ivar 仍然为空。请参见我上面的更新,其中包含一个超级简单的项目,显示了这个问题。 - John Gallagher

2
在 Window nib 中,将 FilesOwner 类设置为 UIApplication,然后从 Outlets 指向 AppDelegate 对象的委托。这就是您项目示例中的问题所在。

您,先生,真是太聪明了。我确实想到过这一点,但由于委托似乎已经被执行,所以我认为这不会是问题。要是我5小时前就试过该怎么好……! 再次感谢。 - John Gallagher
没问题,通过一个项目来理解比在这里看一些代码更容易。所以你用一个项目的例子来解释是非常好的 :) - Adrian Ancuta

1

我不确定为什么您将其声明为属性和非属性。我应该这样做:

@interface KPAppDelegate : UIResponder <UIApplicationDelegate> 

@property (nonatomic, strong) IBOutlet KPBrowseExpensesNavigationController *nc;

在您的实施中:

@implementation KPAppDelegate

@synthesize nc = _nc; // So you don't accidentally use nc

...snip...

// This is called about 5 seconds after app startup
-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
        // By the time we get here, nc is nil.
        UITableViewController *tvc = [[**self.nc** viewControllers] objectAtIndex:0];
        [[tvc tableView] reloadData];
}

@end

希望这能有所帮助!

谢谢,但它仍然是nil。:( 我显然误解了@property,所以感谢您澄清这一点。 - John Gallagher

1

我没有看到你在哪里分配你的导航控制器。仅仅声明属性不会给它赋任何值,所以它会是nil。在你的应用程序委托的-didFinishLaunchingWithOptions方法中设置你的alloc/init语句。其他一切看起来都很好。

KPBrowseExpensesNavigationController *nc = [[KPBrowseExpensesNavigationController alloc] init];

如果您有自定义的init,也可以使用它,但请确保在尝试使用它之前进行设置。


控制器在nib文件中被初始化。但还是谢谢你的建议! - John Gallagher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接