【问题标题】:IBOutlet is nil after initWithCoder is called调用 initWithCoder 后 IBOutlet 为零
【发布时间】:2014-03-30 06:15:01
【问题描述】:

简单的问题,我使用情节提要在 UIViewController 中定义了一个名为 bigImageView 的 UIImageView, 它在那个 UIViewController 的 h 文件中声明如下:

 @property (retain, nonatomic) IBOutlet UIImageView *bigImageView;

在我的appDelegate 上,我按如下方式初始化 UIViewController:

imageViewController = [storyboard instantiateViewControllerWithIdentifier:@"chosenImageController"];

这会在我的 UIViewController m 文件上调用 initWithCoder:

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Custom initialization
    }
    return self;
}

这个函数只被调用一次,所以没有双重初始化。 但是,后来,当我检查我的 bigImageView 指针时,它仍然是 nil。

init 不应该为它分配内存吗? 我认为这就是为什么当我尝试将此 UIImageview 设置为保存 UIImage 时它不显示图像 谢谢

【问题讨论】:

  • 何时调用此 VC 的 viewDidLoad 或 viewWillApear 方法?
  • @Tander,我从另一个 UIViewController 获得了这个 UIViewController,其中我有一个按钮调用调用 [self.navigationController pushViewController:imageViewController animated:YES];

标签: objective-c xcode uiimageview initwithcoder


【解决方案1】:

一切都按照它的意思工作。首先 nib/storyboard 中的每个对象都会调用 alloc/init,然后建立所有连接,然后调用 viewDidLoad

您需要等待- (void)viewDidLoad 在您的控制器上被调用,然后应该设置bigImageView。如果未设置,则说明您在情节提要中做错了。

init 方法不负责分配任何内存。所有内存都由alloc 方法分配,该方法总是在init 之前调用。 Alloc 将用nil/NULL/0 值填充所有实例变量,然后 init 为每个实例变量分配初始值(通常基于 NSCoder 对象的内容,但应由您决定应该做什么)。

然而,对于 IB 网点,它们是在初始化后由 nib 加载过程设置的。

编辑:

// ViewControllerA.m:
imageViewController = [storyboard instantiateViewControllerWithIdentifier:@"chosenImageController"];
imageViewController.image = imageToShow;

// ViewControllerB.h
@property (retain) NSImage *image;
@property (retain, nonatomic) IBOutlet UIImageView *bigImageView;

// ViewControllerB.m
- (void)viewDidLoad
{
  self.bigImageView.image = self.image;

  [super viewDidLoad];
}

【讨论】:

  • 我有一个 viewcontrollerA 出现在它之前,然后在 viewcontrollerA 上我选择了一个图像,这反过来又应该在我显示我的第二个 imageViewController 之前使用委托设置图像。
  • @Alon_T 我已经更新了我的答案,向您展示如何将图像提供给下一个视图控制器。请注意,所有这些代码都将在 GPU 执行任何操作之前执行。
【解决方案2】:

您不需要定义 initWithCoder,因为其中没有自定义逻辑。我会删除那个样板代码。

这是我要检查的内容:

  1. 在故事板中,确保视图控制器的类设置正确。
  2. 通过在您的@property 附近寻找一个圆圈,确保插座在情节提要中正确连接。它应该是一个实心圆圈,而不是一个圆圈的轮廓。
  3. 确保仅在调用 viewDidLoad 后才读取该值。 Apple 的唯一保证是在此方法调用之后设置插座。

更新:听起来您想在加载视图之前访问图像视图。没有办法做到这一点。一种技巧是调用viewController.view,这将强制加载视图,但您不应该这样做的原因有很多。

更好的方法是在视图控制器上实现属性,这些属性适用于未加载视图和加载视图时。您可以看到一个优雅的解决方案示例in this question。注意如果视图被加载,photographerLabel 将通过didSet 方法设置。另一方面,如果视图未加载,它将通过viewDidLoad 方法设置。有关该代码的 Objective-C 版本或更多详细信息,请参阅该问题中的链接视频。

【讨论】:

  • initWithCoder 是为了调试而定义的
  • 如果类名不正确,调试器将无法到达那里;)
  • 我看到了 viewDidLoad。但只有在实际显示该控制器时才会调用它。我希望能够在显示该控制器之前处理那里的值(例如设置预显示的图像)
  • @Alon_T:在 viewWillAppear 和 viewDidAppear 之前调用 viewDidLoad。您应该可以在那里进行所有自定义。
  • @Alon_T viewDidLoad 在所有内容加载之后但在任何屏幕绘制指令发送到 GPU 之前调用。因此,您可以在其中执行操作,而用户不会看到 viewDidLoad 之前的状态。
猜你喜欢
  • 2017-06-08
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多