2012-03-02 16 views
36

जब मैं अपना व्यू कंट्रोलर landscape मोड में शुरू करता हूं (व्यूडिडलोड के बाद कहा जाता है), मैं फ्रेम प्रिंट करता हूं, यह मुझे पोर्ट्रेट मोड के लिए फ्रेम आकार दे रहा है।UIViewController अमान्य फ्रेम देता है?

क्या यह कोई सुझाव है?

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSLog(@"%@", NSStringFromCGRect(self.view.frame)); 
    // Result is (0, 0 , 768, 1024) 
} 
+1

और viewDidAppear के बारे में क्या? – Luke

+1

viewDidAppear ने ठीक काम किया – aryaxt

उत्तर

157

कुछ ऐसी चीजें हैं जिन्हें आप समझ में नहीं आते हैं।

सबसे पहले, सिस्टम आपको अपने निब को लोड करने के तुरंत बाद viewDidLoad भेजता है। इसने अभी तक दृश्य पदानुक्रम में दृश्य भी नहीं जोड़ा है। तो इसने डिवाइस के घूर्णन के आधार पर आपके दृश्य का आकार बदल नहीं लिया है।

दूसरा, एक दृश्य का फ्रेम इसके पर्यवेक्षण के समन्वय स्थान में है। यदि यह आपका मूल दृश्य है, तो इसका पर्यवेक्षण UIWindow होगा (एक बार सिस्टम वास्तव में दृश्य पदानुक्रम में आपका दृश्य जोड़ता है)। UIWindow इसके सबव्यूव के परिवर्तन को सेट करके रोटेशन को संभालता है। इसका मतलब यह है कि दृश्य का फ्रेम जरूरी नहीं होगा जो आप उम्मीद करते हैं।

यहाँ पोर्ट्रेट ओरिएंटेशन में दृश्य पदानुक्रम है:

(lldb) po [[UIApp keyWindow] recursiveDescription] 
(id) $1 = 0x09532dc0 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>> 
    | <UIView: 0x9634ee0; frame = (0 20; 768 1004); autoresize = W+H; layer = <CALayer: 0x9633b50>> 

और यहाँ परिदृश्य-बाएँ अभिविन्यास में दृश्य पदानुक्रम है: लैंडस्केप ओरिएंटेशन में, फ्रेम आकार है

(lldb) po [[UIApp keyWindow] recursiveDescription] 
(id) $2 = 0x09635e70 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>> 
    | <UIView: 0x9634ee0; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x9633b50>> 

सूचना है कि 748 x 1024 , 1024 x 748.

यदि आप अपना मूल दृश्य है, तो क्या आप शायद देखना चाहते हैं, दृश्य है बी ounds:

(lldb) p (CGRect)[0x9634ee0 bounds] 
(CGRect) $3 = { 
    (CGPoint) origin = { 
    (CGFloat) x = 0 
    (CGFloat) y = 0 
    } 
    (CGSize) size = { 
    (CGFloat) width = 1024 
    (CGFloat) height = 748 
    } 
} 

संभवतः आप जानना चाहते हैं कि दृश्य का परिवर्तन, फ्रेम और सीमाएं अपडेट हो जाती हैं। इंटरफ़ेस एक लैंडस्केप ओरिएंटेशन में है, तो जब आपके विचार नियंत्रक अपने लोड होगा, तो आप इस क्रम में संदेश प्राप्त नहीं होंगे:

{{0, 0}, {768, 1004}} viewDidLoad 
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation: 
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation: 
{{0, 0}, {768, 1004}} viewWillAppear: 
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation: 
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation: 
{{0, 0}, {768, 1004}} willRotateToInterfaceOrientation:duration: 
{{0, 0}, {1024, 748}} viewWillLayoutSubviews 
{{0, 0}, {1024, 748}} layoutSubviews 
{{0, 0}, {1024, 748}} viewDidLayoutSubviews 
{{0, 0}, {1024, 748}} willAnimateRotationToInterfaceOrientation:duration: 
{{0, 0}, {1024, 748}} shouldAutorotateToInterfaceOrientation: 
{{0, 0}, {1024, 748}} viewDidAppear: 

आप देख सकते हैं कि अपने दृश्य के सीमा बदलने आप से पहले willRotateToInterfaceOrientation:duration: और प्राप्त के बाद आप viewWillLayoutSubviews प्राप्त करें।

viewWillLayoutSubviews और viewDidLayoutSubviews विधियां आईओएस 5.0 के लिए नई हैं।

layoutSubviews संदेश दृश्य नियंत्रक नहीं, दृश्य को भेजा गया है, इसलिए यदि आप इसका उपयोग करना चाहते हैं तो आपको एक कस्टम UIView सबक्लास बनाना होगा।

+0

धन्यवाद महान जानकारी – aryaxt

+1

यह एक महान स्पष्टीकरण है। – schellsan

+1

मैंने सुना है कि सबसे अच्छी व्याख्याओं में से एक। धन्यवाद – Jon

2

यहां एक साफ समाधान है।

मुझे एक ही समस्या का सामना करना पड़ रहा था और मैं अपने पूरे ऐप में frame का उपयोग करने पर जोर देता हूं। मैं रूट व्यू कंट्रोलर के लिए अपवाद नहीं बनाना चाहता हूं। मैंने देखा कि रूट व्यू कंट्रोलर का frame चित्र आयाम प्रदर्शित कर रहा था, लेकिन सभी सबव्यूज़ में सही परिदृश्य आयाम था।

चूंकि यह केवल रूट व्यू कंट्रोलर है जो अलग-अलग व्यवहार करता है, हम रूट व्यू कंट्रोलर के रूप में एक मानक, खाली दृश्य नियंत्रक सेट कर सकते हैं और उस पर हमारे कस्टम व्यू कंट्रोलर को जोड़ सकते हैं। (नीचे कोड।)

फिर आप अपने कस्टम व्यू कंट्रोलर में frame का उपयोग कर सकते हैं।

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    // Override point for customization after application launch. 

    self.window.rootViewController = [[UIViewController alloc] init]; 

    [self.window makeKeyAndVisible]; 

    self.viewController = [[ViewController alloc] initWithNibName:nil bundle:nil]; 
    [self.window.rootViewController addChildViewController:self.viewController]; 
    [self.window.rootViewController.view addSubview:self.viewController.view]; 

    return YES; 
} 
संबंधित मुद्दे