Saya mendapatkan beberapa perilaku aneh dengan presentViewController:animated:completion
. Apa yang saya buat pada dasarnya adalah permainan menebak.
Saya memiliki UIViewController
(frequencyViewController) yang berisi UITableView
(frequencyTableView). Ketika pengguna mengetuk baris di questionTableView yang berisi jawaban yang benar, tampilan (correctViewController) harus dibuat dan tampilannya harus meluncur ke atas dari bawah layar, sebagai tampilan modal. Ini memberi tahu pengguna bahwa mereka memiliki jawaban yang benar dan menyetel ulang frequencyViewController di belakangnya untuk pertanyaan berikutnya. correctViewController diberhentikan dengan menekan tombol untuk menampilkan pertanyaan berikutnya.
Ini semua bekerja dengan benar setiap saat, dan tampilan correctViewController muncul secara instan selama presentViewController:animated:completion
itu animated:NO
.
Jika saya set animated:YES
, correctViewController diinisialisasi dan melakukan panggilan ke viewDidLoad
. Namun viewWillAppear
,, viewDidAppear
dan blok penyelesaian dari presentViewController:animated:completion
tidak dipanggil. Aplikasi hanya ada di sana dan masih menampilkan frequencyViewController sampai saya membuat ketukan kedua. Sekarang, viewWillAppear, viewDidAppear dan blok penyelesaian dipanggil.
Saya menyelidiki lebih lanjut, dan bukan hanya ketukan lain yang akan menyebabkannya berlanjut. Tampaknya jika saya memiringkan atau mengguncang iPhone saya, ini juga dapat menyebabkannya memicu viewWillLoad dll. Ini seperti menunggu masukan pengguna lain sebelum maju. Ini terjadi pada iPhone asli dan di simulator, yang saya buktikan dengan mengirimkan perintah goyang ke simulator.
Saya benar-benar bingung apa yang harus saya lakukan tentang ini ... Saya sangat menghargai bantuan yang dapat diberikan siapa pun.
Terima kasih
Ini kode saya. Ini sangat sederhana ...
Ini adalah kode di questionViewController yang bertindak sebagai delegasi ke questionTableView
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
{
// If guess was wrong, then mark the selection as incorrect
NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
[cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];
}
else
{
// If guess was correct, show correct view
NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
self.correctViewController = [[HFBCorrectViewController alloc] init];
self.correctViewController.delegate = self;
[self presentViewController:self.correctViewController animated:YES completion:^(void){
NSLog(@"Completed Presenting correctViewController");
[self setUpViewForNextQuestion];
}];
}
}
Ini adalah keseluruhan dari correctViewController
@implementation HFBCorrectViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
NSLog(@"[HFBCorrectViewController initWithNibName:bundle:]");
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(@"[HFBCorrectViewController viewDidLoad]");
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"[HFBCorrectViewController viewDidAppear]");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)close:(id)sender
{
NSLog(@"[HFBCorrectViewController close:sender:]");
[self.delegate didDismissCorrectViewController];
}
@end
Edit:
Saya menemukan pertanyaan ini sebelumnya: UITableView dan presentViewController membutuhkan 2 klik untuk ditampilkan
Dan jika saya mengubah didSelectRow
kode saya menjadi ini, itu bekerja sangat lama dengan animasi ... Tapi itu berantakan dan tidak masuk akal mengapa itu tidak berhasil di tempat pertama. Jadi saya tidak menganggap itu sebagai jawaban ...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row != [self.frequencyModel currentFrequencyIndex])
{
// If guess was wrong, then mark the selection as incorrect
NSLog(@"Incorrect Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
UITableViewCell *cell = [self.frequencyTableView cellForRowAtIndexPath:indexPath];
[cell setBackgroundColor:[UIColor colorWithRed:240/255.0f green:110/255.0f blue:103/255.0f alpha:1.0f]];
// [cell setAccessoryType:(UITableViewCellAccessoryType)]
}
else
{
// If guess was correct, show correct view
NSLog(@"Correct Guess: %@", [self.frequencyModel frequencyLabelAtIndex:(int)indexPath.row]);
////////////////////////////
// BELOW HERE ARE THE CHANGES
[self performSelector:@selector(showCorrectViewController:) withObject:nil afterDelay:0];
}
}
-(void)showCorrectViewController:(id)sender
{
self.correctViewController = [[HFBCorrectViewController alloc] init];
self.correctViewController.delegate = self;
self.correctViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:self.correctViewController animated:YES completion:^(void){
NSLog(@"Completed Presenting correctViewController");
[self setUpViewForNextQuestion];
}];
}
sumber
presentViewController:
seharusnya memicu dimulai dengan penundaan besar. Ini tampaknya menjadi bug di iOS 7 dan juga dibahas di Forum Pengembang Apple.Jawaban:
Saya mengalami masalah yang sama hari ini. Saya menggali topik dan tampaknya itu terkait dengan runloop utama yang tertidur.
Sebenarnya ini adalah bug yang sangat halus, karena jika Anda memiliki sedikit animasi umpan balik, pengatur waktu, dll. Dalam kode Anda, masalah ini tidak akan muncul karena runloop akan tetap hidup oleh sumber-sumber ini. Saya telah menemukan masalah ini dengan menggunakan
UITableViewCell
yang telahselectionStyle
disetel keUITableViewCellSelectionStyleNone
, sehingga tidak ada animasi pemilihan yang memicu runloop setelah penangan pemilihan baris dijalankan.Untuk memperbaikinya (hingga Apple melakukan sesuatu), Anda dapat memicu runloop utama dengan beberapa cara:
Solusi yang paling tidak mengganggu adalah memanggil
CFRunLoopWakeUp
:Atau Anda dapat memasukkan blok kosong ke antrean utama:
Ini lucu, tetapi jika Anda menggoyangkan perangkat, itu juga akan memicu putaran utama (itu harus memproses peristiwa gerakan). Hal yang sama dengan keran, tetapi itu termasuk dalam pertanyaan asli :) Selain itu, jika sistem memperbarui bilah status (misalnya pembaruan jam, kekuatan sinyal WiFi berubah, dll.), Itu juga akan mengaktifkan loop utama dan menampilkan tampilan pengontrol.
Bagi siapa pun yang tertarik, saya menulis proyek demonstrasi minimal dari masalah ini untuk memverifikasi hipotesis runloop: https://github.com/tzahola/present-bug
Saya juga telah melaporkan bug tersebut ke Apple.
sumber
Lihat ini: https://devforums.apple.com/thread/201431 Jika Anda tidak ingin membaca semuanya - solusi untuk beberapa orang (termasuk saya) adalah membuat
presentViewController
panggilan secara eksplisit di utas utama:Swift 4.2:
Objective-C:
Mungkin iOS7 mengacaukan utasnya
didSelectRowAtIndexPath
.sumber
Saya melewati itu di Swift 3.0 dengan menggunakan kode berikut:
sumber
present
melalui panggilan balik penutupan.Memanggil
[viewController view]
pengontrol tampilan yang disajikan melakukan trik untuk saya.sumber
Saya akan penasaran untuk melihat apa yang
[self setUpViewForNextQuestion];
dilakukannya.Anda dapat mencoba menelepon
[self.correctViewController.view setNeedsDisplay];
di akhir blok penyelesaian Anda dipresentViewController
.sumber
Correct Guess: 1 kHz 18:04:57.173 Frequency[641:60b] [HFBCorrectViewController initWithNibName:bundle:] 18:04:57.177 Frequency[641:60b] [HFBCorrectViewController viewDidLoad]
Sekarang tidak ada yang terjadi hingga: Ketuk 218:05:00.515 Frequency[641:60b] [HFBCorrectViewController viewDidAppear] 18:05:00.516 Frequency[641:60b] Completed Presenting correctViewController 18:05:00.517 Frequency[641:60b] [HFBFrequencyViewController setUpViewForNextQuestion]
Saya telah menulis ekstensi (kategori) dengan metode swizzling untuk UIViewController yang memecahkan masalah. Terima kasih kepada AX dan NSHipster untuk petunjuk implementasi ( swift / objektif-c ).
Cepat
Objective-C
sumber
Periksa apakah sel Anda di papan cerita memiliki Seleksi = tidak ada
Jika demikian, ubah menjadi biru atau abu-abu dan itu akan berfungsi
sumber
XCode Vesion: 9.4.1, Swift 4.1
Dalam kasus saya ini terjadi, ketika saya mengetuk sel dan berpindah ke tampilan lain. Saya men-debug lebih dalam dan tampaknya itu terjadi di dalam
viewDidAppear
karena berisi kode berikutkemudian saya menambahkan segmen kode di atas di dalam
prepare(for segue: UIStoryboardSegue, sender: Any?)
dan bekerja dengan sempurna.Dalam pengalaman saya, solusi saya adalah, Jika kita berharap untuk melakukan perubahan baru (mis. Memuat ulang tabel, batal memilih sel yang dipilih, dll.) Untuk tampilan tabel ketika kembali lagi dari tampilan kedua, kemudian gunakan delegasi daripada
viewDidAppear
dan gunakan di atastableView.deselectRow
kode di segmen sebelum memindahkan pengontrol tampilan keduasumber