2012-09-17 159 views
4

說我有2個控制器,BarViewController和FooViewController。爲什麼我的對象沒有通過segue正確傳遞?

FooViewController具有出口到一個UIImageView稱爲ImageView的:

@property (nonatomic, weak) UIImageView *imageView; 

BarViewController具有出口到一個UIButton按鈕。 BarViewController具有此按鈕FooViewController一個SEGUE,叫BarToFooSegue(在故事板完成)。

當我運行下面的代碼,並調用的NSLog上FooViewController.imageView.image,結果是零,我的形象將不會顯示。爲什麼會這樣?

// 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的是內部prepareForSegue正確更新:但然後在幾行後重新更新爲一些新分配的imageView,並將@property圖像設置爲nil。我不確定控制流程的哪一部分會導致這種情況,因爲它發生在用匯編語言編寫的行中。

我得到了我的代碼中加入一個UIImage屬性FooViewController工作:

@property (nonatomic, strong) UIImage *myImage; 

和改變prepareForSegue:在BarViewController傳遞圖像,而不是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]; 
} 

和修改viewWillAppear中:在FooViewController中:

- (void)viewWillAppear:(BOOL)animated{ 
    [self.imageView setImage:self.myImage]; 
} 

回答

6

呼叫[segue.destinationViewController view];您設定的圖像之前,這將導致加載視圖層次,然後你的網點將被設置。

+1

+1。並投下它(無效)並寫出一個好評。 :-) – danh

+1

這真的是一個很好的解決方案嗎?如果內存不足,視圖控制器的視圖可隨時卸載,並在需要時再次重新加載。因此,在'viewDidLoad'中設置'imageView'似乎是更強大的解決方案。 –

+0

我認爲這是一個慎重使用的實用解決方案。與任何模式一樣,當然可以濫用和濫用。情況似乎是imageView是一個目的地並不關心的裝飾的容器,所以添加一個屬性來臨時存儲UIImage,然後在viewDidLoad中設置它看起來像是一個過於複雜的小語義值。該視圖會加載,因爲你正在準備一個segue - 迫使它稍早加載,避免了必須編寫膠水代碼。 – ikuramedia

2

prepareForSegue網點尚未定義 - 它們是零。你發送消息給nil,這是完全正確的,因此不會給你一個錯誤,但在這種情況下,它可能會導致意外的行爲。你可以通過創建一個臨時的UIImage屬性來解決它,並在viewDidLoad或viewWillAppear中將圖像視圖設置爲該圖像。

+0

對不起,你是說[segue.destinationViewController setImageView:ImageView的]。沒有做什麼,因爲segue.destinationViewController是零? – Popcorn

+0

在FooViewController中創建一個臨時的UIImage屬性讓人覺得多餘。當然,必須有一個更好的解決方案? – Popcorn

+0

目標視圖控制器不是零,但imageView是。您可以通過在prepareForSegue中記錄圖像視圖來測試它,它將返回nil。不,不幸的是,這是如何完成的。在iOS 6中這是固定的,但如果你需要爲iOS 5構建,你必須這樣做。 –

-1
- (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; 
} 
} 
+0

這與我對此問題的解決方案的代碼相同。我主要對這個問題發生的原因感興趣,並且如果有更好的方法來解決它 – Popcorn

1

我同意@ikuragames回答,如果你必須直接設置imageView.image。但通常情況下,我將ViewController的視圖層次結構保留爲私有的。

我不認爲它是醜陋到UIImage的屬性添加到富。我認爲它比@ikuragames正確的解決方案更漂亮。

相關問題