2010-02-11 21 views
26

Ich habe eine UITabBar-basierte Anwendung, die gut funktioniert. Unter bestimmten Umständen zeige ich stattdessen einen anderen UIViewController. Was mich jetzt stört ist, dass ich den Rahmen für die Testspitze (und nur die Testspitze!) Richtig anzeigen muss. (Sonst befindet sich die Ansicht unterhalb der Statusleiste).Offset auf UIWindow addSubview

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{ 
    if (condition) { 

     UIViewController *vc = [[UIViewController alloc] initWithNibName:@"Test" bundle:nil]; 

     // FIXME this should NOT be required 
     CGRect r = vc.view.frame; 
     r.origin.y += 20; 
     vc.view.frame = r; 

     [window addSubview:vc.view]; 
     [window makeKeyAndVisible]; 
     return; 
    } 

    [window addSubview:tabViewController.view]; 
    [window makeKeyAndVisible]; 
} 

Also stimmt etwas mit der Testspitze nicht? Kann nicht sein. Die Testspitze funktioniert wie gewünscht in einem sauberen neuen Projekt. Und eine neue saubere Feder zeigt die gleichen Symptome. Also stimmt etwas mit der MainWindow-Feder nicht, oder? Aber der UITabBarController zeigt gut an.

Ich bin ein wenig verwirrt und keine Ideen mehr hier. Irgendwelche Vorschläge, wie man das aufspürt?

Antwort

76

die Stammansicht zu Ihrem UIWindow Hinzufügen kann kompliziert sein, da das Fenster immer die Statusleiste unterlappt. Der Rahmen Ihrer Root-Ansicht muss daher auf [[UIScreen mainScreen] applicationFrame] zurückgesetzt werden, um zu verhindern, dass er auch die Statusleiste unterschneidet. Normalerweise müssen wir uns darüber keine Gedanken machen, weil UIViewController den Frame für uns modifiziert ... außer wenn es nicht der Fall ist. Hier ist der Deal:

  • Wenn Sie Ihren View-Controller und seine Ansicht in der gleichen NIB erstellen, und Sie Nest der Ansicht unterhalb der Ansicht Controller, es wird nach Ansicht des Rahmens automatisch anpassen.
  • Wenn Sie Ihre View-Controller und seine Ansicht in der gleichen NIB erstellen, aber Sie die Ansicht auf die Ansicht Steuerung durch den Ansicht Ausgang des Controllers verbinden, anstatt sie nisten, die Steuerung nicht justiert die Ansichtsrahmen automatisch.
  • Wenn Sie Ihren View-Controller in einem NIB erstellen, und Sie es zu einer in einem frei stehenden NIB definierte Ansicht verbinden, indem der View-Controller des „NIB-Namen“ Eigenschaft in IB Einstellung, es wird justiert die Frames Ansicht automatisch, aber nur wenn haben Sie auch "Größe Ansicht von NIB" überprüft.
  • Wenn Sie Ihren View-Controller erstellen, indem Sie -initWithNibName: bundle :, aufrufen, wird den Rahmen der Ansicht automatisch anpassen.
  • UITabBarController erwartet, dass seine Ansicht als Stammansicht des Fensters hinzugefügt wird, und passt daher den Rahmen seiner eigenen Ansicht immer so an, dass er dem Anwendungsrahmen automatisch entspricht. (Als Ergebnis erhalten Sie eine seltsame 20 Pixel Lücke bemerken, wenn Sie jemals eine UITabBarController Ansicht als Subview etwas anderes als das Fenster hinzufügen.)

Ich denke, Apple-dachte, dass -initWithNibName: Bundle: nicht wird normalerweise verwendet, um die Grundansicht des Fensters zu erstellen, sodass der Rahmen in Ihrem Fall nicht angepasst wird.Die Größe manuell anzupassen, wie Sie es getan haben, ist in Ordnung, und ist in der Tat in der View Controller Programming Guide for iPhone OS empfohlen, aber Sie sollten wirklich [[UIScreen mainScreen] applicationFrame] verwenden, da die Statusleiste nicht immer 20 Pixel groß ist (z. B. ist es größer, wenn Sie an einem Telefonanruf sind .)

+3

Ich würde zweimal upvote, wenn ich könnte :) –

+1

die endgültige Antwort auf eine der ärgerlichsten häufigsten Kuriositäten in der iOS-Entwicklung. 5 Sterne, 10/10, würde wieder spielen –

+0

nicht vollständig lesen Sie Ihre Antwort, aber ich bin sehr glücklich mit Keyword [[UIScreen mainScreen] applicationFrame] –

0

Ich gehe davon aus, dass Ihre UITabBarController eine IB-Steckdose ist, so dass, wenn applicationDidFinishLaunching: aufgerufen wird, ist es bereits initialisiert. Versuchen Sie Folgendes: nur nach dem View-Controller instanziiert wird, tun:

[vc setWantsFullScreenLayout:YES]; 
+0

Nach dem Aufruf verschwinden die 20 Pixel am unteren Bildschirmrand (die weiß waren und nicht die Hintergrundfarbe der Ansicht) und der gesamte Bereich wird abgedeckt. Aber die UI-Steuerelemente sind immer noch 20 Pixel zu nah an der Spitze. Ich denke, das passt die Größe von 320x460 auf 320x480. Der Ursprung ist immer noch falsch. Und nach all dem wäre auch nur ein Workaround. Ich möchte den Grund dafür finden. – tcurdt

0

Gerade zweite, was oben gesagt wurde: der Code Hier ist das ich zu verwenden hatte:

#define MAIN_SCREEN_OFFSET_PIXELS  20 

- (void) pushDownViewOnMainScreen { 
    CGRect r = [[UIScreen mainScreen] applicationFrame]; 
    r.origin.y -= MAIN_SCREEN_OFFSET_PIXELS; 

    self.view.frame = r; 
} 


- (void) viewDidLoad { 
    [self pushDownViewOnMainScreen]; 

    // ... 
} 
4

Dies ist viel einfacher und auch (iOS 4.0 und höher)

MyRootViewController *vc = [[MyRootViewController alloc] init];  
[window setRootViewController:vc]; 
[vc release]; 

arbeitet - setRootViewContro ller fügt dem Fenster automatisch die Ansicht des Controllers hinzu, sodass Sie sich keine Gedanken darüber machen müssen. Die Eigenschaft ist (nicht atomisch, beibehalten), so dass sie freigegeben wird, nachdem sie dem Fenster zugewiesen wurde, und übergibt das Besitzrecht des Objekts an das UIWindow und wird freigegeben (und demzufolge freigegeben), wenn das Fenster freigegeben wird. Sie könnten natürlich eine Instanzvariable erstellen und einen Verweis darauf behalten und in -dealloc veröffentlichen, wenn Sie damit in den anderen App-Delegiertenmethoden arbeiten möchten. Ich bevorzuge die oben genannte Methode, da es sich automatisch um die Bereinigung kümmert.

Falls Sie es nicht wissen, können Sie View-Controller auch sofort freigeben, nachdem Sie ihre Ansichten einer anderen Ansicht als Unteransicht hinzugefügt oder eine Modal-View-Controller-Ansicht präsentiert haben. Immer wenn eine Ansicht entfernt oder aus dem View-Stack entfernt wird, werden ihre entsprechenden Controller ebenfalls freigegeben.

Sie müssen nicht initWithNibName verwenden, nur ... alloc] init]; Wird besorgt.

+0

Sie müssen initWithNibName verwenden, wenn Sie von einer Feder laden, obwohl , ofc ... – fnf