Tampaknya dengan Xcode 8, pada viewDidLoad
, semua subview viewcontroller memiliki ukuran yang sama yaitu 1000x1000. Hal yang aneh, tapi oke, viewDidLoad
belum pernah menjadi tempat yang lebih baik untuk mengukur tampilan dengan benar.
Tapi viewDidLayoutSubviews
apakah!
Dan pada proyek saya saat ini, saya mencoba mencetak ukuran tombol:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"%@", self.myButton);
}
Log menunjukkan ukuran (1000x1000) untuk myButton! Kemudian jika saya masuk klik tombol, misalnya, log menunjukkan ukuran normal.
Saya menggunakan autolayout.
Apakah ini bug?
ios
autolayout
ios10
xcode8
Martin
sumber
sumber
(0, 0, 1000, 1000)
inisialisasi terikat adalah cara baru Xcode instanciates views dari IB. Sebelum Xcode8, tampilan dibuat dengan ukuran yang dikonfigurasi di xib, kemudian diubah ukurannya sesuai layar setelahnya. Tetapi sekarang, tidak ada ukuran yang dikonfigurasi dalam dokumen IB karena ukurannya tergantung pada pilihan perangkat Anda (di bagian bawah layar). Jadi pertanyaan sebenarnya adalah: adakah tempat yang dapat diandalkan di mana ukuran akhir tampilan dapat diperiksa?Jawaban:
Sekarang, Interface Builder memungkinkan pengguna mengubah ukuran setiap pengontrol tampilan di storyboard secara dinamis, untuk mensimulasikan ukuran perangkat tertentu.
Sebelum fungsionalitas ini, pengguna harus mengatur secara manual setiap ukuran pengontrol tampilan. Jadi pengontrol tampilan disimpan dengan ukuran tertentu, yang digunakan
initWithCoder
untuk mengatur frame awal.Sekarang, tampaknya
initWithCoder
tidak menggunakan ukuran yang ditentukan di storyboard, dan menentukan ukuran 1000x1000 px untuk tampilan viewcontroller & semua subviewnya.Ini bukan masalah, karena tampilan harus selalu menggunakan salah satu dari solusi tata letak berikut:
autolayout, dan semua batasan akan mengatur tampilan Anda dengan benar
autoresizingMask, yang akan mengatur tata letak setiap tampilan yang tidak memiliki batasan apa pun yang dilampirkan ( catatan autolayout dan batasan margin sekarang kompatibel dalam tampilan yang sama \ o /! )
Tapi ini dia masalah untuk semua hal tata letak yang terkait dengan lapisan tampilan, seperti
cornerRadius
, karena tata letak otomatis maupun topeng otomatis tidak berlaku untuk properti lapisan.Untuk menjawab masalah ini, cara yang umum adalah menggunakan
viewDidLayoutSubviews
jika Anda berada di controller, ataulayoutSubview
jika Anda dalam tampilan. Pada titik ini (jangan lupa untuk memanggilsuper
metode relatifnya), Anda cukup yakin bahwa semua tata letak telah selesai!Cukup yakin? Hum ... tidak sepenuhnya, saya telah berkomentar, dan itulah mengapa saya menanyakan pertanyaan ini, dalam beberapa kasus tampilan masih memiliki ukuran 1000x1000 pada metode ini. Saya pikir tidak ada jawaban untuk pertanyaan saya sendiri. Untuk memberikan informasi yang maksimal tentangnya:
1- Itu terjadi hanya saat meletakkan sel! Dalam
UITableViewCell
&UICollectionViewCell
subkelas,layoutSubview
tidak akan dipanggil setelah tampilan ditata dengan benar.2- Seperti yang dikatakan @EugenDimboiu (tolong beri suara positif pada jawabannya jika berguna untuk Anda), menelepon
[myView layoutIfNeeded]
subview yang tidak ditata akan mengaturnya dengan benar tepat pada waktunya.3- Menurut saya, ini pasti bug. Saya telah mengirimkannya ke radar (id 28562874).
PS: Saya bukan penutur asli bahasa Inggris, jadi silakan mengedit posting saya jika tata bahasa saya harus diperbaiki;)
PS2: Jika ada solusi yang lebih baik, jangan ragu untuk menulis jawaban lain. Saya akan memindahkan jawaban yang diterima.
sumber
UIStackView
dalam aUICollectionViewCell
tidak mengembalikan tinggi yang benar selamaviewDidLayoutSubviews
. MeneleponlayoutIfNeeded
segera memperbaiki masalah.Apakah Anda menggunakan sudut membulat untuk tombol Anda? Coba telepon
layoutIfNeeded()
sebelumnya.sumber
Solusi: Bungkus semua yang ada
viewDidLayoutSubviews
di dalamnyaDispatchQueue.main.async
.sumber
-viewDidLoad
... solusi yang anehSaya tahu ini bukan pertanyaan persis Anda, tetapi saya mengalami masalah serupa di mana pada pembaruan beberapa pandangan saya kacau meskipun memiliki ukuran bingkai yang benar di viewDidLayoutSubviews. Menurut catatan Rilis iOS 10:
Pada dasarnya, Anda tidak bisa memanggil layoutIfNeeded pada objek turunan View jika Anda menggunakan translatesAutoresizingMaskIntoConstraints - sekarang memanggil layoutIfNeeded harus ada di superView, dan Anda masih bisa memanggilnya di viewDidLayoutSubviews.
sumber
Jika frame tidak benar dalam layoutSubViews (padahal sebenarnya tidak), Anda dapat mengirimkan sedikit kode asinkron pada thread utama. Ini memberi sistem waktu untuk melakukan tata letak. Ketika blok yang Anda kirim dijalankan, bingkai memiliki ukuran yang sesuai.
sumber
Ini memperbaiki masalah (sangat menjengkelkan) untuk saya:
Edit / Catatan: Ini untuk ViewController layar penuh.
sumber
[super viewDidLayoutSubviews];
metode ini karena banyak hal tata letak otomatis dilakukan oleh tampilan itu sendiriUIView
. Tetapi jika Anda harus melakukan perhitungan khusus pada bingkai tampilan tertentu, jawaban Eugen berfungsi: panggillayoutIfNeeded
. Saya merasa ini bukan solusi terbaik, tetapi saya masih belum menemukan yang lebih baik.Sebenarnya
viewDidLayoutSubviews
juga bukan tempat terbaik untuk mengatur bingkai pandangan Anda. Sejauh yang saya mengerti, mulai sekarang satu-satunya tempat yang harus dilakukan adalahlayoutSubviews
metode dalam kode tampilan aktual. Saya berharap saya tidak benar, seseorang tolong koreksi saya jika itu tidak benar!sumber
viewDidLayoutSubviews
cukup ambigu. Kalimat kedua dalam "diskusi" memiliki kontradiksi dengan kalimat terakhir. developer.apple.com/reference/uikit/uiviewcontroller/…Saya sudah melaporkan masalah ini ke Apple, masalah ini sudah ada sejak lama, ketika Anda menginisialisasi UIViewController dari Xib, tetapi saya menemukan solusi yang cukup bagus. Selain itu saya menemukan masalah itu dalam beberapa kasus ketika layoutIfNeeded di UICollectionView dan UITableView ketika sumber data tidak disetel di saat awal, dan diperlukan juga swizzle.
Pengiriman setelah perpanjangan:
Ekstensi Swizzle:
sumber
Masalah saya diselesaikan dengan mengubah penggunaan dari
untuk
Jadi, dari Did to Will
Sangat aneh
sumber
Solusi yang lebih baik untuk saya.
Menggunakan
sumber
Ganti layoutSublayers (dari layer: CALayer) alih-alih layoutSubviews di subview sel untuk memiliki bingkai yang benar
sumber
Jika Anda perlu melakukan sesuatu berdasarkan bingkai tampilan Anda - timpa layoutSubviews dan panggil layoutIfNeeded
Saya memiliki masalah dengan viewDidLayoutSubviews mengembalikan bingkai yang salah untuk tampilan saya, yang mana saya perlu menambahkan gradien. Dan hanya layoutIfNeeded yang melakukan hal yang benar :)
sumber
Sesuai pembaruan baru di ios ini sebenarnya adalah bug tetapi kami dapat mengurangi ini dengan menggunakan -
Jika Anda menggunakan xib dengan autolayout dalam proyek Anda, maka Anda hanya perlu memperbarui frame dalam pengaturan autolayout, cari gambar untuk ini.
sumber