Saya memiliki UITableView dengan daftar item. Memilih item akan mendorong viewController yang kemudian melanjutkan untuk melakukan hal berikut. dari metode viewDidLoad Saya menjalankan URLRequest untuk data yang diperlukan oleh salah satu subview saya - subclass UIView dengan drawRect diganti. Saat data datang dari cloud, saya mulai membangun hierarki tampilan saya. subclass yang dimaksud akan melewati data dan metode drawRectnya sekarang memiliki semua yang diperlukan untuk merender.
Tapi.
Karena saya tidak menyebut drawRect secara eksplisit - Cocoa-Touch yang menanganinya - saya tidak punya cara untuk memberi tahu Cocoa-Touch bahwa saya benar-benar ingin subclass UIView ini dirender. Kapan? Sekarang akan bagus!
Saya sudah mencoba [myView setNeedsDisplay]. Ini terkadang berhasil. Sangat jerawatan.
Saya telah bergumul dengan ini selama berjam-jam. Bisakah seseorang yang memberi saya pendekatan yang kokoh dan terjamin untuk memaksa render ulang UIView.
Berikut ini cuplikan kode yang memasukkan data ke tampilan:
// Create the subview
self.chromosomeBlockView = [[[ChromosomeBlockView alloc] initWithFrame:frame] autorelease];
// Set some properties
self.chromosomeBlockView.sequenceString = self.sequenceString;
self.chromosomeBlockView.nucleotideBases = self.nucleotideLettersDictionary;
// Insert the view in the view hierarchy
[self.containerView addSubview:self.chromosomeBlockView];
[self.containerView bringSubviewToFront:self.chromosomeBlockView];
// A vain attempt to convince Cocoa-Touch that this view is worthy of being displayed ;-)
[self.chromosomeBlockView setNeedsDisplay];
Cheers, Doug
sumber
setNeedsDisplay
panggilan sebenarnya dan panggilandrawRect:
. Sementara keandalan panggilan ada di sini, saya tidak akan menyebutnya sebagai solusi "paling kuat" — solusi gambar yang kuat harus, secara teori, melakukan semua gambar segera sebelum kembali ke kode klien yang menuntut pengundian.Saya punya masalah dengan penundaan yang besar antara memanggil setNeedsDisplay dan drawRect: (5 detik). Ternyata saya memanggil setNeedsDisplay di utas yang berbeda dari utas utama. Setelah memindahkan panggilan ini ke utas utama, penundaan itu hilang.
Semoga ini bisa membantu.
sumber
Cara yang dijamin uang kembali, diperkuat-beton-kokoh untuk memaksa tampilan menggambar secara sinkron (sebelum kembali ke kode panggilan) adalah dengan mengonfigurasi
CALayer
interaksi denganUIView
subkelas Anda .Di subkelas UIView Anda, buat
displayNow()
metode yang memberi tahu layer untuk " set course for display " lalu " make it so ":Cepat
Objective-C
Juga terapkan
draw(_: CALayer, in: CGContext)
metode yang akan memanggil metode gambar pribadi / internal Anda (yang berfungsi karena setiapUIView
adalah aCALayerDelegate
) :Cepat
Objective-C
Dan buat
internalDraw(_: CGRect)
metode kustom Anda , bersama dengan fail-safedraw(_: CGRect)
:Cepat
Objective-C
Dan sekarang panggil saja
myView.displayNow()
kapan pun Anda benar-benar membutuhkannya untuk menggambar (seperti dariCADisplayLink
panggilan balik) .displayNow()
Metode kami akan memberi tahuCALayer
kepadadisplayIfNeeded()
, yang akan secara sinkron memanggil kembali ke kamidraw(_:,in:)
dan melakukan penggambaraninternalDraw(_:)
, memperbarui visual dengan apa yang ditarik ke dalam konteks sebelum melanjutkan.Pendekatan ini mirip dengan @ RobNapier di atas, tetapi memiliki keuntungan memanggil
displayIfNeeded()
selainsetNeedsDisplay()
, yang membuatnya sinkron.Hal ini dimungkinkan karena
CALayer
s mengekspos lebih banyak fungsionalitas menggambar daripadaUIView
yang dilakukannya— lapisan adalah level yang lebih rendah daripada tampilan dan dirancang secara eksplisit untuk tujuan gambar yang sangat dapat dikonfigurasi dalam tata letak, dan (seperti banyak hal di Cocoa) dirancang untuk digunakan secara fleksibel ( sebagai kelas induk, atau sebagai delegator, atau sebagai jembatan ke sistem gambar lain, atau hanya sendiri). PenggunaanCALayerDelegate
protokol yang tepat memungkinkan semua ini.Informasi lebih lanjut tentang konfigurasi
CALayer
s dapat ditemukan di bagian Menyiapkan Objek Lapisan dari Panduan Pemrograman Animasi Inti .sumber
drawRect:
secara eksplisit mengatakan "Anda tidak boleh memanggil metode ini secara langsung sendiri." Juga, CALayerdisplay
secara eksplisit mengatakan "Jangan panggil metode ini secara langsung." Jika Anda ingin menggambarcontents
langsung pada lapisan secara serempak, Anda tidak perlu melanggar aturan ini. Anda bisa menggambar ke lapisancontents
kapan saja Anda mau (bahkan pada utas latar belakang). Cukup tambahkan sublayer ke tampilan untuk itu. Tapi itu berbeda dengan menampilkannya di layar, yang perlu menunggu hingga waktu pengomposisian yang tepat.contents
("Jika objek lapisan terikat ke objek tampilan, Anda harus menghindari menyetel konten properti ini secara langsung. Interaksi antara tampilan dan lapisan biasanya menghasilkan dalam tampilan yang menggantikan konten properti ini selama pembaruan berikutnya. ") Saya tidak secara khusus merekomendasikan pendekatan ini; gambar yang terlalu dini merusak kinerja dan kualitas gambar. Tetapi jika Anda membutuhkannya karena suatu alasan, makacontents
bagaimana mendapatkannya.drawRect:
secara langsung. Tidak perlu mendemonstrasikan teknik ini, dan telah diperbaiki.contents
teknik yang Anda sarankan… terdengar memikat. Saya mencoba sesuatu seperti itu pada awalnya tetapi tidak bisa membuatnya berfungsi, dan menemukan solusi di atas menjadi kode yang jauh lebih sedikit tanpa alasan untuk tidak sama berkinerja. Namun, jika Anda memiliki solusi yang berfungsi untukcontents
pendekatan tersebut, saya akan tertarik untuk membacanya (tidak ada alasan mengapa Anda tidak dapat memiliki dua jawaban untuk pertanyaan ini, bukan?)display
. Ini hanya metode publik khusus dalam subkelas UIView, seperti yang dilakukan di GLKView (subkelas UIView lain, dan satu-satunya metode yang ditulis Apple yang saya ketahui yang menuntut fungsionalitas DRAW NOW! ).Saya memiliki masalah yang sama, dan semua solusi dari SO atau Google tidak berhasil untuk saya. Biasanya,
setNeedsDisplay
berhasil, tetapi ketika tidak ...Saya telah mencoba memanggil
setNeedsDisplay
tampilan dengan segala cara yang mungkin dari setiap kemungkinan utas dan barang - masih tidak berhasil. Kami tahu, seperti yang dikatakan Rob, ituTapi untuk beberapa alasan kali ini tidak akan menarik. Dan satu-satunya solusi yang saya temukan adalah memanggilnya secara manual setelah beberapa waktu, untuk membiarkan apa pun yang menghalangi undian berlalu, seperti ini:
Ini adalah solusi yang bagus jika Anda tidak benar-benar membutuhkan tampilan untuk menggambar ulang. Sebaliknya, jika Anda melakukan beberapa hal (tindakan) bergerak, biasanya tidak ada masalah hanya dengan menelepon
setNeedsDisplay
.Saya berharap ini akan membantu seseorang yang tersesat di sana, seperti saya dulu.
sumber
Saya tahu ini mungkin perubahan besar atau bahkan tidak cocok untuk proyek Anda, tetapi apakah Anda mempertimbangkan untuk tidak melakukan push sampai Anda sudah memiliki datanya ? Dengan begitu, Anda hanya perlu menggambar tampilan sekali dan pengalaman pengguna juga akan lebih baik - dorongan akan berpindah saat sudah dimuat.
Cara Anda melakukan ini adalah dengan
UITableView
didSelectRowAtIndexPath
meminta data secara asinkron. Setelah Anda menerima respons, Anda secara manual melakukan segue dan meneruskan data ke viewController AndaprepareForSegue
. Sementara itu, Anda mungkin ingin menampilkan beberapa indikator aktivitas, untuk indikator pemuatan sederhana, periksa https://github.com/jdg/MBProgressHUDsumber