iPhone SDK: apa perbedaan antara loadView dan viewDidLoad?

136

Saat bekerja dengan tampilan dan pengontrol tampilan di aplikasi iPhone, adakah yang bisa menjelaskan perbedaan antara loadView dan viewDidLoad?

Konteks pribadi saya, adalah bahwa saya membangun semua pandangan saya dari kode, saya tidak dan tidak akan menggunakan Interface Builder, jika itu membuat perbedaan.

Saya sering menemukan bahwa ketika saya menambahkan kode init ke loadView, saya berakhir dengan pelacakan tumpukan tak terbatas, jadi saya biasanya melakukan semua bangunan tampilan anak saya di viewDidLoad ... tetapi bagi saya tidak jelas kapan masing-masing dieksekusi, dan apa tempat yang lebih tepat untuk meletakkan kode init. Apa yang akan sempurna, adalah diagram sederhana dari panggilan inisialisasi.

Terima kasih!

ryan.scott
sumber

Jawaban:

200

Saya dapat menebak apa yang mungkin menjadi masalah di sini, karena saya telah melakukannya:

Saya sering menemukan bahwa ketika saya menambahkan kode init ke loadView, saya berakhir dengan pelacakan tumpukan yang tak terbatas

Jangan membaca self.view di -loadView. Hanya setel , jangan mengerti .

Pengakses properti self.view memanggil -loadView jika tampilan saat ini tidak dimuat. Ada rekursi tak terbatas Anda.

Cara biasa untuk membangun tampilan secara terprogram dalam -loadView, seperti yang ditunjukkan dalam contoh pra-Interface-Builder Apple, lebih seperti ini:

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

Dan saya tidak menyalahkan Anda karena tidak menggunakan IB. Saya terjebak dengan metode ini untuk semua Instapaper dan menemukan diri saya jauh lebih nyaman dengannya daripada berurusan dengan kerumitan IB, kebiasaan antarmuka, dan perilaku di balik layar yang tidak terduga.

Marco
sumber
ahhhh, terima kasih atas penjelasannya, akhirnya! Saya telah menghindar dari ungkapan mengalokasikan variabel sementara, lalu menyetel ke self.view, lalu melepaskan ... sepertinya canggung, tidak perlu. Sekarang saya bisa mengerti mengapa keputusan itu membawa saya ke jalan yang sekarang saya temukan.
ryan.scott
Saya memiliki kode seperti itu dan tidak ada rekursi. Mengapa? -(void) loadView { // Frame for Hypnosis view CGRect frame = [[UIScreen mainScreen] bounds]; // Create a Hipnosis view v = [[HypnosisView alloc] initWithFrame:frame]; self.view = v;
pengguna2054339
45

loadViewadalah metode UIViewControlleryang benar-benar akan memuat tampilan dan menetapkannya ke viewproperti. Ini juga merupakan lokasi yang UIViewControllerakan diganti oleh subclass jika Anda ingin menyiapkan viewproperti secara terprogram.

viewDidLoadadalah metode yang dipanggil setelah tampilan dimuat. Ini disebut setelah loadView dipanggil. Ini adalah tempat di mana Anda dapat mengganti dan menyisipkan kode yang melakukan penyiapan awal lebih lanjut dari tampilan setelah dimuat.

NilObject
sumber
14
viewDidLoad()

digunakan saat Anda memuat tampilan dari NIB dan ingin melakukan penyesuaian apa pun setelah peluncuran

LoadView()

digunakan saat Anda ingin membuat tampilan secara terprogram (tanpa menggunakan Interface Builder)

ashokdy
sumber
Ini mungkin memiliki beberapa masalah, saya telah menguji ketika pengontrol tampilan saya tidak terkait dengan file NIB, viewDidLoad masih dipanggil
ruandao
11

Hanya menambahkan beberapa contoh kode untuk menunjukkan apa yang dikatakan 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];
}
alamodey
sumber
4
jadi, di antara Anda berdua, apakah akurat untuk mengatakan bahwa loadView adalah tempat saya harus melakukan alokasi / init dari self.view pengontrol saya, dan tampilan anak harus ditangani di viewDidLoad (atau yang lebih baru)?
ryan.scott
2

Untuk mencegah pengulangan tak terbatas terjadi saat Anda membaca self.view, panggil implementasi super kelas saat Anda memuat tampilan. Penerapan super akan mengalokasikan UIView baru untuk Anda.

- (void) loadView {
[super loadview];

// init code here...

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

}
futureelite7
sumber
6
Saya bersumpah bahwa dokumentasi Apple mengatakan Anda tidak boleh menelepon [super loadView];. Itu bertentangan dalam contoh, tetapi saya pikir dokumen mengatakannya dengan benar (saya telah menemukan banyak bug dalam contoh dari waktu ke waktu). [super loadView]diperlukan untuk UITableViewController dll. Namun! Semua pengaturan pasca-pemuatan (misalnya menambahkan subview ekstra) harus dilakukan di viewDidLoad.
Ivan Vučica
Saya telah menelepon [super loadView] tanpa efek samping sejauh ini. Mungkin benar jika Anda berniat untuk mengatur pandangan-diri terhadap sesuatu yang Anda buat sendiri.
futureelite7
Jika Anda memanggil [super loadView] di dalam loadView maka ini akan mencoba untuk memuat tampilan dari ujung jika tersedia dengan nama default. Jadi Anda perlu berhati-hati.
Ian1971
Dan jika Anda memanggil [super loadView], Anda menginisialisasi self.view dalam metode super loadView
Alex Nazarsky
1

Cara termudah untuk menggunakan loadView adalah membuat beberapa jenis pengontrol tampilan dasar, seperti MyBaseViewController yang merupakan subkelas dari UIViewController. Dalam metode loadView, buat tampilan dengan cara ini:

-(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];
}

Dan ketika Anda perlu membuat beberapa pengontrol tampilan, Anda cukup menggunakan subkelas MyBaseViewController dan di pengontrol loadView Anda cukup memanggil [super loadView] seperti ini

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

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

loadView()dipanggil saat pengontrol Anda diminta untuk membuatnya self.view. Anda bisa melakukannya sendiri seperti

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

Atau kelas UIController induk pengontrol Anda sudah memiliki nama metode -loadView()yang menginisialisasi self.view Anda ke tampilan kosong. Kemudian Anda bisa menelepon

[super loadView];

Saya sangat merekomendasikan pendekatan kedua karena mendorong warisan. Hanya jika pengontrol tampilan Anda tidak secara langsung diwarisi dari UIViewController.

Dulguun Otgon
sumber
0

Definisi yang diberikan oleh Apple pada viewDidLoad menyebutkan bahwa itu dipanggil setelah tampilan pengontrol dimuat ke dalam memori. Sederhananya, ini adalah metode pertama yang akan dimuat.

Anda mungkin berpikir dalam kondisi apa metode ini akan digunakan sepenuhnya? Jawabannya adalah, pada dasarnya apa pun yang Anda inginkan agar aplikasi dimuat terlebih dahulu. Misalnya, Anda mungkin menginginkan warna latar belakang yang berbeda, daripada putih, Anda mungkin dapat memilih biru.

Gulsan Borbhuiya
sumber