Keyboard iPad tidak akan diberhentikan jika gaya presentasi modal ViewController adalah UIModalPresentationFormSheet

214

catatan:

Lihat jawaban yang diterima (bukan yang terpilih teratas) untuk solusi pada iOS 4.3.

Pertanyaan ini adalah tentang perilaku yang ditemukan di keyboard iPad, di mana ia menolak untuk diberhentikan jika ditampilkan dalam dialog modal dengan pengontrol navigasi.

Pada dasarnya, jika saya menghadirkan pengontrol navigasi dengan baris berikut seperti di bawah ini:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Keyboard menolak untuk diberhentikan. Jika saya mengomentari baris ini, keyboard akan hilang dengan baik.

...

Saya punya dua textFields, nama pengguna, dan kata sandi; nama pengguna memiliki tombol Berikutnya dan kata sandi memiliki tombol Selesai. Keyboard tidak akan hilang jika saya menyajikan ini di pengontrol navigasi modal.

BEKERJA

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
[self.view addSubview:b.view];

TIDAK BEKERJA

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
[[UINavigationController alloc]
 initWithRootViewController:b];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

Jika saya menghapus bagian pengontrol navigasi dan menyajikan 'b' sebagai pengontrol tampilan modal dengan sendirinya, itu berfungsi. Apakah pengontrol navigasi masalahnya?

BEKERJA

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:b animated:YES];
[b release];

BEKERJA

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc]
         initWithRootViewController:b];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];
Kalle
sumber
Pertanyaan SO berikut ini tampaknya memiliki masalah yang sama, tetapi tidak ada jawaban: stackoverflow.com/questions/3019709/…
Kalle
+1 Terima kasih atas penjelasan Anda yang luar biasa. Tetapi di mana saya harus meletakkan metode itu? Tampaknya tidak berfungsi di mana saya membuat kode untuk menghadirkan pengontrol model ...
Lorenzo B
1
Itu harus di kelas pengontrol tampilan modal itu sendiri.
Kalle
Terima kasih. Saya melihat. Saya memutuskan memasukkannya ke dalam kategori untuk UINavigationControllerkelas. Bersulang.
Lorenzo B
Saya sangat berhutang budi kepada Anda untuk pertanyaan ini. Saya terkejut yang resignFirstRespondermengeksekusi tetapi keyboard masih ditampilkan. Skenario saya (presentationFormSheet dengan navigasi contrllr) persis sama dengan milik Anda. Terima kasih banyak!!
sErVerdevIL

Jawaban:

115

Di pengontrol tampilan yang disajikan secara sederhana, cukup timpa disablesAutomaticKeyboardDismissaluntuk kembali NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}
Sebastian H
sumber
Yap, sejak 4.3 sepertinya ini masalahnya. Akan memperbarui pertanyaan. Terima kasih!
Kalle
2
Ini perlu ditambahkan ke pengontrol navigasi
pottedmeat
1
Ya, berfungsi saat Anda menimpanya di NavigationController. Itulah satu-satunya hal yang benar-benar berhasil untuk saya.
James Laurenstin
Penolong! Mengapa Apple melakukan hal-hal seperti ini? Tentunya itu seharusnya default untuk TIDAK & memungkinkan kita untuk mengubahnya jika kita benar-benar ingin
SomaMan
Tidak bekerja pada kelas turunan UIViewController, menonaktifkan AutomatisKeyboardDismissal tidak pernah dipanggil
Jorge Arimany
172

Ini telah diklasifikasikan sebagai "karya sebagaimana dimaksud" oleh para insinyur Apple. Saya mengajukan bug untuk ini beberapa waktu lalu. Alasan mereka adalah bahwa pengguna sering memasukkan data dalam bentuk modal sehingga mereka berusaha untuk "membantu" dan menjaga keyboard tetap terlihat di mana biasanya berbagai transisi dalam tampilan modal dapat menyebabkan keyboard ditampilkan / disembunyikan berulang kali.

sunting: inilah tanggapan seorang insinyur Apple di forum pengembang:

Apakah pandangan Anda kebetulan disajikan dengan gaya UIModalPresentationFormSheet? Untuk menghindari animasi masuk dan keluar yang sering, keyboard kadang-kadang akan tetap di layar bahkan ketika tidak ada responden pertama. Ini bukan bug.

Ini memberi banyak masalah pada orang (termasuk saya sendiri) tetapi saat ini sepertinya tidak ada cara untuk mengatasinya.

MEMPERBARUI:

Di iOS 4.3 dan yang lebih baru, Anda sekarang dapat menerapkan `-disableAutomaticKeyboardDismissal 'pada pengontrol tampilan Anda untuk mengembalikan TIDAK:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Ini memperbaiki masalah.

Mike Weller
sumber
7
jeda Wow, oke. Terima kasih banyak untuk kepala. Sial Apple .. :(
Kalle
Apakah Anda mengirimkan laporan bug ke Apple? Saya telah melakukannya di bawah ID # 8384423. Saya juga telah mengirimkan contoh aplikasi untuk mereproduksi perilaku.
Shaggy Frog
3
Pada iOS 4.3 sekarang ada metode disableAutomaticKeyboardDismissal yang memperbaiki masalah ini.
Kalle
5
saya mencoba metode disablesAutomaticKeyboardDismissal, tetapi masih tidak menyelesaikan masalah, bagaimana cara mengatasinya?
R. Dewi
3
@ Tip: Anda perlu membuat UINavigationControllersubclass yang menimpa disablesAutomaticKeyboardDismissaluntuk kembali NOdan menggunakan ini sebagai pengontrol navigasi saat Anda menyajikan lembar formulir modal. Lihat jawaban dari @ miha-hribar di bawah ini.
Pascal
149

Hati-hati jika Anda menampilkan modal dengan a UINavigationController. Anda kemudian harus mengatur disablesAutomaticKeyboardDismissalpada pengontrol navigasi dan bukan pada pengontrol tampilan. Anda dapat dengan mudah melakukan ini dengan kategori.

File: UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

File: UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

Jangan lupa untuk mengimpor kategori dalam file tempat Anda menggunakan UINavigationController.

Miha Hribar
sumber
19
1, akhirnya saya melihat bagian yang hilang informasi untuk masalah ini disorot: bahwa salah satu kebutuhan untuk menimpa disablesAutomaticKeyboardDismissaldari UINavigationController, bukan controller tampilan sendiri, untuk memperbaiki masalah ini.
DarkDust
Bagus! Apa yang saya butuhkan. Terima kasih.
Justin
Sempurna. Tidak jelas dari dokumen resmi tetapi masuk akal karena UINavigationController berada di rantai responden. Jawaban yang sangat bagus. Terima kasih!
imnk
1
Saya menyajikan dialog modal dari UISplitViewController. Saya sudah mencoba kode di atas, tetapi mengganti UISplitViewController untuk UINavigationController, tetapi masih tidak berfungsi. Haruskah metode ini juga berfungsi pada UISplitViewController?
Snips
6
Ini bukan ide yang baik untuk menerapkan metode duplikat dalam suatu kategori. Anda tidak pernah dapat memastikan implementasi mana yang akan dipanggil, jadi paling baik Anda dapat mengharapkan perilaku yang tidak konsisten. Lebih baik untuk mewarisi dari UINavigationController dan mengganti metode di kelas kustom Anda.
sean woodward
51

Saya memecahkan ini dengan menggunakan UIModalPresentationPageSheetgaya presentasi dan mengubah ukurannya segera setelah saya mempresentasikannya. Seperti itu:

viewController.modalPresentationStyle = UIModalPresentationPageSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin;    
viewController.view.superview.frame = CGRectMake(
    viewController.view.superview.frame.origin.x,
    viewController.view.superview.frame.origin.y,
    540.0f,
    529.0f
);
viewController.view.superview.center = self.view.center;
[viewController release];
azdev
sumber
Hmmm ... ini tidak tepat ... mengubah ukuran menyebabkan modal untuk melukis lucu ... itu seperti menekan konten ke bawah agar sesuai dengan kotak ukuran baru atau sesuatu ... semuanya terlihat lucu. :(
toofah
Ada juga masalah rotasi dengan yang ini ... jika Anda memutar saat modal ini naik, ia akan menyusut / tumbuh seolah-olah itu adalah tampilan halaman penuh
toofah
2
toofah, saya mengedit kode untuk menangani masalah menyusut / berkembang ketika berputar; hanya masalah memberikan superview margin atas dan bawah yang fleksibel. Saya tidak yakin saya melihat perilaku lainnya.
azdev
1
ini hanya berfungsi selama Anda tidak mendorong tampilan lain di atas yang satu ini. Karena ketika Anda menutup tampilan yang didorong di atas tampilan yang disajikan UIModalPresentationPageSheet, itu kembali ke ukuran aslinya.
V1ru8
Itu berhasil. Namun kata dalam tampilan terlihat sedikit kabur. Saya tidak tahu kenapa.
jeswang
1

Jika Anda mengaktifkan tampilan modal yang berbeda, Anda bisa menghilangkan papan ketik. Itu tidak cantik dan tidak bernyawa turun, tetapi Anda bisa membuatnya pergi.

Akan lebih bagus jika ada perbaikan, tetapi untuk sekarang ini berfungsi. Anda dapat memasukkannya dalam kategori aktif UIViewControllerdan memanggilnya saat Anda ingin keyboard hilang:

@interface _TempUIVC : UIViewController
@end

@implementation _TempUIVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
@end

@implementation UIViewController (Helpers)

- (void)_dismissModalViewController {
    [self dismissModalViewControllerAnimated:NO];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [self release];
}

- (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated {
    [self retain];
    _TempUIVC *tuivc = [[_TempUIVC alloc] init];
    tuivc.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentModalViewController:tuivc animated:animated];
    if (animated) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil];
    } else
        [self _dismissModalViewController];
    [tuivc release];
}

@end

Hati-hati dengan ini meskipun Anda melihatDidAppear / viewDidDisappear dan semua metode dipanggil. Seperti yang saya katakan, itu tidak cantik, tetapi bekerja.

-Adam

Adam
sumber
1

Anda juga bisa menyiasatinya dalam aplikasi universal dengan hanya memeriksa idiom dan jika itu iPad, jangan muncul keyboard secara otomatis sama sekali dan biarkan pengguna mengetuk apa pun yang ingin mereka edit.

Mungkin bukan solusi terbaik tetapi sangat mudah dan tidak memerlukan hack mewah yang akan pecah dengan rilis iOS besar berikutnya :)

Maciej Swic
sumber
1

Masukkan kode ini di viewWillDisappear Anda: metode pengontrol saat ini adalah cara lain untuk memperbaikinya:

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];
Cerita
sumber
1

Saya menemukan itu disablesAutomaticKeyboardDismissaldan menambahkan disablesAutomaticKeyboardDismissalfungsi tidak berfungsi untuk saya UITextFielddalam dialog modal.

Keyboard pada layar tidak akan hilang.

Solusi saya adalah untuk menonaktifkan semua kontrol input teks dalam dialog saya, kemudian mengaktifkan kembali yang relevan sepersekian detik kemudian.

Sepertinya saat iOS melihat bahwa tidak ada UITextFieldkontrol diaktifkan, maka tidak menyingkirkan keyboard.

Mike Gledhill
sumber
0

Saya yakin Anda telah melihat ini, tetapi Anda yakin bahwa kelas controller Anda terhubung dengan benar sebagai delegasi UITextField, kan?

Neal L
sumber
Saya mengaturnya sendiri secara manual, dan metode delegasi dipanggil, jadi ya.
Kalle
0

mungkin jangan mengembalikan TIDAK, tapi YA. Jadi itu bisa hilang.

Dan Anda memiliki textFieldShouldEndEditingYA yang kembali juga?

Dan mengapa kamu menembak [nextResponder becomeFirstResponder]?! maaf saya mengerti sekarang

Saya juga memiliki sejumlah UITextViews yang semuanya memiliki properti "yang dapat diedit" disetel ke FALSE.

Bolehkah kita berasumsi bahwa tidak satu pun dari mereka yang memiliki tagnilai secondField.tag+1? Jika demikian, Anda memberi tahu mereka untuk menjadi responden pertama, alih-alih mengundurkan diri sebagai responden pertama. Mungkin menaruh beberapa NSLog () di struktur if.

mvds
sumber
1
TIDAK = jangan masukkan baris baru, dari apa yang bisa saya katakan. Dan mengaturnya ke YA tidak memperbaikinya.
Kalle
1
UITextField, menjadi satu baris menurut definisi, tidak banyak berpengaruh pada baris baru, saya pikir. Jadi ini lebih lanjut tentang memproses penekanan tombol Return / Done, sebagaimana dinyatakan dalam dokumen.
mvds
Apakah Anda sangat yakin Anda mengaitkan semuanya dengan cara yang benar? Sudahkah Anda memasukkan NSLog("tf %x / method ...",textField);semua fungsi delegasi?
mvds
Nah, fungsi delegasi dipanggil dengan tepat, dan itu tidak akan terjadi jika delegasi tidak diatur dengan tepat. Dan NSLog memberikan EXC_BAD_ACCESS. Juga memperingatkan saya tentang hal itu menjadi tipe XCode yang tidak kompatibel.
Kalle
Doh. Maaf, seharusnya sudah melihatnya sendiri. Saya telah memperbarui jawaban di atas dengan hasil NSLogs ini karena pemformatan akan mendapatkan sendiri dalam komunikasi ..
Kalle
0

Bagi mereka yang memiliki masalah dengan UINavigationController, lihat jawaban saya untuk pertanyaan serupa di sini: https://stackoverflow.com/a/10507689/321785

Sunting: Saya menganggap ini sebagai peningkatan pada solusi Miha Hribar (karena keputusan sedang diambil di mana seharusnya), dan berlawanan dengan komentar Pascal mengenai kategori pada UIViewController

Chris Trahey
sumber
0

mungkin bukan solusi yang sempurna, tetapi bekerja
[self.view endEditing: YES];
dari mana pun tombol atau gerakan Anda diterapkan untuk menyajikan modal

Tanuj Jagoori
sumber
0
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
fivewood
sumber