Iphone 为什么我的对象不能通过segue正确传递?

Iphone 为什么我的对象不能通过segue正确传递?,iphone,objective-c,ios,xcode,ipad,Iphone,Objective C,Ios,Xcode,Ipad,假设我有两个控制器,BarViewController和FooViewController FooViewController有一个名为imageView的UIImageView的出口: @property (nonatomic, weak) UIImageView *imageView; // code in BarViewController - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

假设我有两个控制器,BarViewController和FooViewController

FooViewController有一个名为imageView的UIImageView的出口:

@property (nonatomic, weak) UIImageView *imageView;
// code in BarViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"BarToFooSegue"]){
        NSURL *photoUrl = @"http://www.randurl.com/someImage"; // assume valid url
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];

        [segue.destinationViewController setMyImage:image];
}
BarViewController有一个UIButton按钮的出口。 BarViewController有一个从该按钮到FooViewController的序列,称为BartoFosegue(在故事板中完成)

当我运行以下代码,并在FooViewController.imageView.image上调用NSLog时,结果是nil,并且我的图像不会显示。为什么会这样

// code in BarViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"BarToFooSegue"]){
        NSURL *photoUrl = @"http://www.randurl.com/someImage"; // assume valid url
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

        [segue.destinationViewController setImageView:imageView];
    }
}
我已尝试将FooViewController.imageView设置为“强”而不是“弱”,但问题仍然存在:

@property (nonatomic, strong) UIImageView *imageView;
运行我的调试器时,我注意到FooViewController中的imageView在PrepareForsgue:中被正确更新,但随后几行被重新更新为新分配的imageView,其中@property image设置为nil。我不确定控制流的哪个部分导致了这种情况,因为它发生在用汇编语言编写的行中

我通过向FooViewController添加UIImage属性使代码正常工作:

@property (nonatomic, strong) UIImage *myImage;
- (void)viewWillAppear:(BOOL)animated{
    [self.imageView setImage:self.myImage];
}
并将BarViewController中的prepareForSegue:更改为传递图像而不是imageView:

@property (nonatomic, weak) UIImageView *imageView;
// code in BarViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"BarToFooSegue"]){
        NSURL *photoUrl = @"http://www.randurl.com/someImage"; // assume valid url
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];

        [segue.destinationViewController setMyImage:image];
}
和修改视图将显示:在FooViewController中:

@property (nonatomic, strong) UIImage *myImage;
- (void)viewWillAppear:(BOOL)animated{
    [self.imageView setImage:self.myImage];
}

prepareForSegue
中,尚未定义出口——它们为零。您正在向nil发送一条消息,这很好,因此不会给您错误,但在这种情况下,它可能会导致意外行为。您可以通过创建一个临时UIImage属性来解决此问题,并在ViewDiLoad或ViewWillDisplay中将图像视图设置为该图像。

调用
[segue.destinationViewController视图]设置图像之前,这将导致加载视图层次结构,然后设置插座。

如果必须直接设置imageView.image,我同意@ikuragames answer。但通常,我会将ViewController的视图层次结构保持为私有

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"BarToFooSegue"]){
        NSURL *photoUrl = @"http://www.randurl.com/someImage"; 
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];

   
        FooViewController *vc = [segue destinationViewController];
        vc.myImage = image;   
 }
}

我不认为将UIImage属性添加到Foo中是丑陋的。我认为它实际上比@ikuragames正确的解决方案更漂亮。

对不起,你是说[segue.destinationViewController setImageView:imageView];因为segue.destinationViewController为nil,所以什么也不做?在FooViewController中创建临时UIImage属性感觉是多余的。肯定有更整洁的解决方案吗?目标视图控制器不是零,但imageView是。您可以通过在prepareForSegue中记录图像视图来测试它,它将返回nil。不,不幸的是,事情就是这样发生的。在iOS 6中,这是固定的,但是如果你需要为iOS 5构建,你必须这样做。这与我解决这个问题的方法是相同的代码。我主要感兴趣的是为什么会出现这个问题,如果有更好的解决方法,这真的是一个很好的解决方案吗?如果内存不足,可以随时卸载视图控制器的视图,并在必要时重新加载。因此,在
viewdiload
中设置
imageView
似乎是一个更可靠的解决方案。我相信,如果仔细使用,这是一个实用的解决方案。与任何模式一样,滥用和误用当然是可能的。这种情况似乎是,imageView是一个容器,用于一些目的地并不真正关心的装饰,因此添加一个属性来临时存储UIImage,然后在viewDidLoad中设置它似乎过于复杂,语义值很小。视图将要加载,因为您正在准备一个segue-强制它稍早加载可以避免编写粘合代码。OP设计中更有趣的问题是,从prepareForSegue中的URL加载将阻止主线程。我不希望目标视图控制器需要从网络加载,但我可以看到在prepareForSegue中启动了一个异步NSURLConnection,并在完成块中设置了映像。在这种情况下,您需要确保在执行完成时已加载视图,强制加载视图将是一种方法@scott说iOS6在prepareForSegue之前加载视图-我还没有测试过,但这是有意义的。