2012-07-01 44 views
1

我面臨的問題是設備方向就地異步更新UIView。我已經在viewDidLoad中實現的設備取向如下目標c:以設備方向異步更新UIView

- (void)viewDidLoad{ 
[super viewDidLoad]; 
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil]; 
[self initialize];} 

在orientationChanged方法,我有以下代碼

-(void)orientationChanged { 
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; 

if(UIInterfaceOrientationIsLandscape(orientation)){ 
    UINib *nib = [UINib nibWithNibName:@"ConsoleViewControllerLandscape" bundle:nil]; 
    UIView *portraitView = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0]; 
    self.view = portraitView; 

    [self initialize]; 

} else { 
    UINib *nib = [UINib nibWithNibName:@"ConsoleViewController" bundle:nil]; 
    UIView *portraitView = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0]; 
    self.view = portraitView; 

    [self initialize]; 

} 

在初始化方法,我實際上異步地碼等

[self performSelectorOnMainThread:@selector(arrangeAsynchronously) withObject:nil waitUntilDone:NO]; 
- (void) arrangeAsynchronously{ 
    //Some complex calculation and finally 
[self.view addSubview:imageview]; 
} 

更新UI問題是方向改變imageViews沒有添加到主視圖。比方說,我從縱向視圖開始,然後我可以在縱向視圖中看到所有圖像視圖,如果它更改爲橫向視圖,則視圖爲空。再次,如果我切換到肖像,然後所有子視圖,即imageViews正確添加。問題是方向改變時,我正在加載一個新的nib文件,但代碼仍然指的是從舊的nob文件加載的舊視圖。我如何更改參考。只有在異步模式下才會出現此問題。

它與uiview沒有問題,而是在設備旋轉後計算子視圖位置。早些時候,我的代碼是

CGAffineTransform inverseTransform = CGAffineTransformInvert(self.view.transform); 
fixedPoint = CGPointApplyAffineTransform(fixedPoint,inverseTransform); 
fixedPoint = CGPointMake(fixedPoint.x+126, fixedPoint.y-109); 

,我把它改成

fixedPoint = CGPointMake(fixedPoint.x+126, fixedPoint.y-109); 

但是還是我無言以對爲什麼的AffineTransform不起作用waitUntilDone:NO和waitUntilDone工作:YES。

回答

0

您的策略有點問題。 self.view以某種方式呈現,並且僅僅因爲您製作了新的UIView,並不意味着它會在所呈現的窗口中被替換。

我建議您將容器視圖添加到您的主要UIView(您在此處替換的視圖),然後在更改設備方向時更改容器視圖的內容。

編輯

我的回答似乎有點不清楚,所以讓我嘗試解釋更詳細。 UIViewControllerUIViewUIWindow呈現。這意味着窗口對視圖有參考。當您更改UIViewControllerUIView(通過構建新的UIView)並不意味着它會反映在UIWindow中。


初步方案:

UIViewController->UIView1 < -UIWindow

之後您將構造一個新的UIView:

UIViewController->UIView2
的UIWindow - >UIView1


正如你可以在上面的圖中看到的,你沒有根的任何錯誤,但你現在有兩種觀點,並在UIViewController所做的更改不會在屏幕上體現。

但是,您可能會如此幸運,但它首次有效:如果您在重建UIView之前由UIWindow呈現一切仍然有效,但它仍然是一個糟糕的設計,可能很容易中斷(就像您看到的一樣在時間改變之後)。

這就是事情可能實際工作的情況:


初步方案:

* UIViewController->UIView1

構造一個新的UIView後:

* UIViewController->UIView2

窗口在屏幕上顯示的看法:

UIViewController->UIView2 < -UIWindow


基本上你不應該你的手柄扔掉到的UIViewControllerUIView後已呈現。

我希望這可以幫助您瞭解引用/指針的工作原理。

+0

現在很酷的編碼器。我試圖幫助你。讓我試着解釋一下我所看到的與你的設計有關的問題;每次手機傾斜時,您都可以在視圖控制器中查看自己重新構建的視圖。但是在某處你有一個UIWindow或另一個視圖控制器,它仍然有一個對第一個視圖的引用。這意味着即使你構建了一個新的視圖,你也不會得到它。基本上說:你不應該在呈現之後重建UIViewController的視圖。我希望這可以澄清一點,也請儘量保持友好和藹的語調。 – EsbenB

+0

感謝您的建議,我想解釋的是,當我使用[self performSelectorOnMainThread:@selector(arrangeAsynchronously)withObject:nil waitUntilDone:NO]更新視圖時會出現問題;但是當waitUntilDone:YES時,問題不會出現。這意味着,問題不是因爲View呈現,而是與線程有關。讓我知道它是否合理。 –

+0

執行選擇器中waitUntilDone YES/NO的區別在於代碼將被執行,而不是執行該操作的線程。請嘗試我建議的解決方案。如果這沒有幫助,我們可以討論下一步。 – EsbenB