iPhone SDK: loadView และ viewDidLoad แตกต่างกันอย่างไร


136

เมื่อทำงานกับมุมมองและตัวควบคุมมุมมองในแอพ iPhone ทุกคนสามารถอธิบายความแตกต่างระหว่าง loadView และ viewDidLoad ได้หรือไม่

บริบทส่วนบุคคลของฉันคือฉันสร้างมุมมองทั้งหมดของฉันจากรหัสฉันไม่และจะไม่ใช้ตัวสร้างส่วนต่อประสานที่ควรสร้างความแตกต่างใด ๆ

ฉันพบว่าบ่อยครั้งที่ฉันเพิ่มรหัสเริ่มต้นลงใน loadView ฉันจะจบด้วยการติดตามสแต็กที่ไม่สิ้นสุดดังนั้นโดยทั่วไปฉันจะสร้างสิ่งที่เด็กดูทั้งหมดใน viewDidLoad ... แต่มันก็ไม่ชัดเจนสำหรับฉันเมื่อถูกประมวลผลและ ตำแหน่งที่เหมาะสมในการใส่รหัส init คืออะไร สิ่งที่จะสมบูรณ์แบบเป็นแผนภาพง่าย ๆ ของการเริ่มต้นการโทร

ขอบคุณ!

คำตอบ:


200

ฉันสามารถเดาได้ว่าอะไรคือปัญหาที่นี่เพราะฉันได้ทำไปแล้ว:

ฉันพบว่าบ่อยครั้งที่ฉันเพิ่มรหัสเริ่มต้นใน loadView ฉันสิ้นสุดด้วยการติดตามสแต็กที่ไม่สิ้นสุด

อย่าอ่าน self.view ใน -loadView เพียงตั้งได้ไม่ได้รับมัน

การเข้าถึงคุณสมบัติ self.view เรียก -loadView หากไม่ได้โหลดมุมมองในปัจจุบัน มีการสอบถามซ้ำแบบไม่สิ้นสุดของคุณ

วิธีปกติในการสร้างมุมมองโดยทางโปรแกรมใน -loadView ดังแสดงในตัวอย่าง pre-Interface-Builder ของ Apple เป็นดังนี้:

UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];

และฉันไม่โทษคุณที่ไม่ได้ใช้ IB ฉันใช้วิธีนี้สำหรับ Instapaper ทั้งหมดและพบว่าตัวเองรู้สึกสะดวกสบายมากกว่าการจัดการกับความซับซ้อนของ IB, อินเตอร์เฟสอินเตอร์เฟสและพฤติกรรมเบื้องหลังที่ไม่คาดคิด


ขอบคุณสำหรับคำอธิบายในที่สุด! ฉันเบือนหน้าหนีจากสำนวนที่จัดสรรตัวแปรชั่วคราวแล้วตั้งค่าเป็น self.view แล้วปล่อย ... ดูเหมือนว่าจะอึดอัดไม่จำเป็น ตอนนี้ฉันสามารถเข้าใจได้แล้วว่าทำไมการตัดสินใจนั้นจึงนำฉันไปสู่เส้นทางที่ฉันพบตัวเอง
ryan.scott

ฉันมีรหัสดังกล่าวและไม่มีการเรียกซ้ำ ทำไม? -(void) loadView { // Frame for Hypnosis view CGRect frame = [[UIScreen mainScreen] bounds]; // Create a Hipnosis view v = [[HypnosisView alloc] initWithFrame:frame]; self.view = v;
user2054339

44

loadViewเป็นวิธีการUIViewControllerที่จะโหลดมุมมองและกำหนดให้กับviewคุณสมบัติจริง นี่เป็นตำแหน่งที่ subclass ของUIViewControllerจะแทนที่ถ้าคุณต้องการตั้งค่าviewคุณสมบัติโดยทางโปรแกรม

viewDidLoadเป็นวิธีการที่เรียกว่าเมื่อโหลดมุมมองแล้ว สิ่งนี้เรียกว่าหลังจาก loadView ถูกเรียกใช้ เป็นสถานที่ที่คุณสามารถแทนที่และใส่รหัสที่ตั้งค่าเริ่มต้นเพิ่มเติมของมุมมองเมื่อมันถูกโหลดแล้ว


14
viewDidLoad()

จะใช้เมื่อคุณโหลดมุมมองของคุณจาก NIB และต้องการดำเนินการปรับแต่งใด ๆ หลังจากเปิดตัว

LoadView()

จะใช้เมื่อคุณต้องการสร้างมุมมองของคุณโดยทางโปรแกรม (โดยไม่ต้องใช้ Interface Builder)


นี่อาจมีปัญหาบางอย่างฉันมีการทดสอบเมื่อตัวควบคุมมุมมองของฉันไม่เชื่อมโยงกับไฟล์ NIB, viewDidLoad ยังคงถูกเรียกใช้
ruandao

11

เพียงเพิ่มตัวอย่างโค้ดเพื่อสาธิตสิ่งที่ NilObject กล่าว

- (void)loadView
{
    // create and configure the table view
    myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped];   
    myTableView.delegate = self;
    myTableView.dataSource = self;
    myTableView.scrollEnabled = NO;
    self.view = myTableView;

    self.view.autoresizesSubviews = YES;
}

- (void)viewDidLoad 
{
  self.title = @"Create group";

  // Right menu bar button is to Save
  UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
  self.navigationItem.rightBarButtonItem = saveButtonItem;
  [saveButtonItem release];
}

4
ดังนั้นระหว่างคุณสองคนมันถูกต้องหรือไม่ที่จะบอกว่า loadView เป็นตำแหน่งที่ฉันควรทำ alloc / init ของ self.view ของคอนโทรลเลอร์และมุมมองลูกควรจัดการใน viewDidLoad (หรือใหม่กว่า)?
ryan.scott

2

เพื่อป้องกันการวนซ้ำไม่สิ้นสุดเกิดขึ้นเมื่อคุณอ่าน self.view ให้เรียกใช้การดำเนินการระดับสูงของคลาสเมื่อคุณโหลดมุมมอง การนำ Super มาใช้จะจัดสรร UIView ใหม่ให้คุณ

- (void) loadView {
[super loadview];

// init code here...

[self.view addSubView:mySubview1]; //etc..

}

6
[super loadView];ฉันจะสาบานเอกสารแอปเปิ้ลบอกว่าคุณไม่ควรเรียก นั่นเป็นความขัดแย้งในตัวอย่าง แต่ฉันคิดว่าเอกสารพูดอย่างถูกต้อง (ฉันพบข้อบกพร่องจำนวนมากในตัวอย่างเมื่อเวลาผ่านไป) [super loadView]เป็นสิ่งจำเป็นสำหรับ UITableViewController และอื่น ๆ แต่! การตั้งค่าหลังการโหลดใด ๆ (เช่นการเพิ่มการดูย่อยพิเศษ) ควรทำใน viewDidLoad
Ivan Vučica

ฉันเรียก [super loadView] โดยไม่มีผลข้างเคียงใด ๆ มันอาจเป็นจริงถ้าคุณตั้งใจตั้ง self.view กับสิ่งที่คุณทำเอง
futureelite7

หากคุณเรียกใช้ [super loadView] ภายใน loadView มันจะพยายามโหลดมุมมองจากปลายปากกาหากมีพร้อมกับชื่อเริ่มต้น ดังนั้นคุณต้องระวัง
Ian1971

และถ้าคุณเรียกใช้ [super loadView] คุณเริ่มต้น self.view ด้วยวิธี super loadView
Alex Nazarsky

1

วิธีที่ง่ายที่สุดในการใช้ loadView คือการสร้างคอนโทรลเลอร์มุมมองบางประเภทเช่น MyBaseViewController ซึ่งเป็นคลาสย่อยของ UIViewController ในมันเป็นวิธี loadView สร้างมุมมองด้วยวิธีนี้:

-(void) loadView {
    if ([self viewFromNib]) {
        self.view = [self viewFromNib];
    } else {
        self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    }
    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
    self.view.backgroundColor = [UIColor whiteColor];
}

และเมื่อคุณต้องการสร้างตัวควบคุมมุมมองคุณเพียงแค่ใช้คลาสย่อยของ MyBaseViewController และในตัวควบคุม loadView คุณก็เรียก [super loadView] เช่นนี้

//sucblass loadView
-(void) loadView {
    [super loadView];

    //rest of code like this..
    UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
    [self.view addSubview:myLabel];
    [myLabel release];
}

1

loadView()self.viewจะถูกเรียกเมื่อการควบคุมของคุณถามว่าจะสร้างมัน คุณสามารถทำได้ด้วยตัวเองเช่น

self.view = [UIView alloc] init...];

หรือคลาส UIController ของคอนโทรลเลอร์ของคุณมีชื่อเมธอด-loadView()ที่กำหนดค่าเริ่มต้น self.view ของคุณให้เป็นมุมมองว่าง จากนั้นคุณสามารถโทร

[super loadView];

ฉันขอแนะนำแนวทางที่สองเพราะมันส่งเสริมมรดก เฉพาะในกรณีที่ตัวควบคุมมุมมองของคุณไม่ได้รับการสืบทอดโดยตรงจาก UIViewController


0

นิยามที่กำหนดโดย Apple ใน viewDidLoad กล่าวถึงว่าถูกเรียกหลังจากมุมมองของคอนโทรลเลอร์ถูกโหลดลงในหน่วยความจำ ในการใส่คำศัพท์ง่ายๆมันเป็นวิธีแรกที่จะโหลด

คุณอาจกำลังคิดว่าวิธีนี้ใช้อย่างเต็มที่ในสภาพใด คำตอบคือโดยพื้นฐานแล้วอะไรก็ตามที่คุณต้องการให้แอปโหลดก่อน ตัวอย่างเช่นคุณอาจต้องการสีพื้นหลังที่แตกต่างกันแทนที่จะเป็นสีขาวคุณอาจเลือกสีน้ำเงิน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.