Folha de ação de sobreposição de teclado no iOS 13.1 no CNContactViewController
12
Isso parece ser específico para o iOS 13.1, pois funciona como esperado no iOS 13.0 e versões anteriores para adicionar um contato no CNContactViewController, se eu 'Cancelar', a folha de ação está sobreposta pelo teclado. Nenhuma ação é executada e o teclado não está descartando.
Parabéns ao @GxocT pela excelente solução! Ajudei imensamente meus usuários.
Mas eu queria compartilhar meu código com base na solução @GxocT, esperando que ajude outras pessoas nesse cenário.
Eu precisava que meu CNContactViewControllerDelegatecontactViewController(_:didCompleteWith:)cancelamento fosse cancelado (além de concluído).
Além disso, meu código não estava em um UIViewControllermodo que não háself.navigationController
Eu também não gosto de usar força para desembrulhar quando posso ajudá-lo. Eu fui mordido no passado, então eu acorrentei if letna configuração
Aqui está o que eu fiz:
Estenda CNContactViewControllere coloque a função swizzle
lá.
No meu caso na função swizzle basta ligar para o CNContactViewControllerDelegatedelegado contactViewController(_:didCompleteWith:)com selfe self.contactobjeto do controlador de contato
No código de instalação, verifique se a chamada swizzleMethod
class_getInstanceMethodespecifica a CNContactViewController
classe em vez deself
E o código Swift:
classMyClass:CNContactViewControllerDelegate{overridefunc viewDidLoad(){super.viewDidLoad()self.changeImplementation()}func changeCancelImplementation(){let originalSelector =Selector(("editCancel:"))let swizzledSelector =#selector(CNContactViewController.cancelHack)iflet originalMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), originalSelector),let swizzledMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), swizzledSelector){
method_exchangeImplementations(originalMethod, swizzledMethod)}}func contactViewController(_ viewController:CNContactViewController, didCompleteWith contact:CNContact?){// dismiss the contacts controller as usual viewController.dismiss(animated:true, completion:nil)// do other stuff when your contact is canceled or saved...}}extensionCNContactViewController{@objc func cancelHack(){self.delegate?.contactViewController?(self, didCompleteWith:self.contact)}}
O teclado ainda aparece momentaneamente, mas cai logo após o controlador de contatos ser descartado.
Permite que a Apple conserte isso
forçar o desembrulhamento é usado para tornar o código compacto, é claro que você deve evitá-lo se possível e se pode levar a uma falha. btw eu não tenho certeza se ele está correto para passar self.contact para delegado, porque ele provavelmente não é criado se você cancelar o fluxo ps: mudou a minha aplicação para desembrulha força evitar: D
GxocT
@GxocT - concordou com os esforços da força. E nem sempre são terríveis, mas outros não são como você e podem sempre usá-los sem perceber o risco;). Eu gosto se deixar em vez de! quando não tenho 100% de certeza de que não será nulo. Sobre o self.contact - é verdade Eu não sei o que o código lib da Apple normalmente passa para o delegado internamente, mas self.contact tinha os dados de contato e o documento CNContactViewController diz que é "o contato sendo exibido", por isso parecia bem usar. Meu código na verdade não usa o contato passado no delegado de conclusão para que eu pudesse passar nulo na extensão.
Barrett
O conteúdo (incluindo exibições de texto e teclados) no CNContactViewController deve estar em um processo separado. Se você pode usar 'View Hierarchy' no Xcode para este controlador de exibição, poderá achar que o conteúdo não pode ser visto. Como resultado, não podemos controlar o teclado nem a exibição de texto.
WildCat 9/10/19
5
Não consegui encontrar uma maneira de descartar o teclado. Mas pelo menos você pode exibir o ViewController usando meu método.
Não sei por que, mas é impossível descartar o teclado no CNContactViewController. Tentei endEditing :, crie um novo UITextField firstResponder e assim por diante. Nada funcionou.
Tentei alterar a ação do botão "Cancelar". Você pode encontrar esse botão na pilha NavigationController, mas sua ação é alterada toda vez que você digita alguma coisa.
Finalmente, usei o método swizzling. Não consegui encontrar uma maneira de descartar o teclado como mencionei anteriormente, mas pelo menos você pode descartar o CNContactViewController quando o botão "Cancelar" for pressionado.
De fato, o usuário pode deslizar para baixo para descartar o teclado e depois tocar em Cancelar e ver a folha de ação. Portanto, esse problema é lamentável e definitivamente um bug (e eu arquivei um relatório de bug), mas não fatal (embora, com certeza, a solução alternativa não seja trivial para o usuário descobrir).
Obrigado @Gxoct por seu excelente trabalho. Acho que essa é uma pergunta e um post muito útil para quem está trabalhando CNContactViewController. Eu também tive esse problema (até agora), mas no objetivo c. Interpreto o código Swift acima no objetivo c.
-(void)viewDidLoad {[super viewDidLoad];Classclass=[CNContactViewControllerclass];
SEL originalSelector =@selector(editCancel:);
SEL swizzledSelector =@selector(dismiss);// we will gonna access this method & redirect the delegate via this method
Method originalMethod = class_getInstanceMethod(class, originalSelector);Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));if(didAddMethod){
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));}else{
method_exchangeImplementations(originalMethod, swizzledMethod);}}
Criando uma CNContactViewControllercategoria para acessar dispensar;
Não consegui encontrar uma maneira de descartar o teclado. Mas pelo menos você pode exibir o ViewController usando meu método.
PS: Você pode encontrar informações adicionais sobre o tópico do reddit: https://www.reddit.com/r/swift/comments/dc9n3a/bug_with_cnviewcontroller_ios_131/
fonte
De fato, o usuário pode deslizar para baixo para descartar o teclado e depois tocar em Cancelar e ver a folha de ação. Portanto, esse problema é lamentável e definitivamente um bug (e eu arquivei um relatório de bug), mas não fatal (embora, com certeza, a solução alternativa não seja trivial para o usuário descobrir).
fonte
Corrigido no iOS 13.4 testado no Xcode Simulator
fonte
Obrigado @Gxoct por seu excelente trabalho. Acho que essa é uma pergunta e um post muito útil para quem está trabalhando
CNContactViewController
. Eu também tive esse problema (até agora), mas no objetivo c. Interpreto o código Swift acima no objetivo c.Criando uma
CNContactViewController
categoria para acessar dispensar;Caras que não estão tão familiarizados com o Swizzling, você pode tentar este post por matt
fonte
Obrigado, @GxocT pela sua solução alternativa, no entanto, a solução postada aqui é diferente da que você postou no Reddit.
O do Reddit funciona para mim, este não, então eu quero republicá-lo aqui. A diferença está na linha com swizzledMethod, que deve ser:
Todo o código atualizado é:
fonte