Feuille d'action de superposition de clavier dans iOS 13.1 sur CNContactViewController
12
Cela semble être spécifique à iOS 13.1, car cela fonctionne comme prévu sur iOS 13.0 et les versions antérieures pour ajouter un contact dans CNContactViewController, si je `` Annuler '', la feuille d'action se chevauche par clavier. Aucune action n'est effectuée et le clavier ne se ferme pas.
Félicitations à @GxocT pour l'excellente solution de contournement! J'ai énormément aidé mes utilisateurs.
Mais je voulais partager mon code basé sur la solution @GxocT en espérant qu'il aiderait les autres dans ce scénario.
J'avais besoin que mon CNContactViewControllerDelegatecontactViewController(_:didCompleteWith:)appel soit annulé (ainsi que fait).
De plus, mon code n'était pas dans un UIViewControllerdonc il n'y a pasself.navigationController
Je n'aime pas non plus utiliser les déballages de force quand je peux l'aider. J'ai été mordu dans le passé donc j'ai enchaîné les if lets dans la configuration
Voici ce que j'ai fait:
Étendez CNContactViewControlleret placez la fonction swizzle à l'intérieur
.
Dans mon cas, dans la fonction swizzle, il suffit d'appeler le CNContactViewControllerDelegatedélégué contactViewController(_:didCompleteWith:)avec selfet l' self.contactobjet du contrôleur de contact
Dans le code d'installation, assurez-vous que l'appel swizzleMethod
class_getInstanceMethodspécifie la CNContactViewController
classe au lieu deself
Et le code 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)}}
Le clavier s'affiche toujours momentanément, mais disparaît juste après que le contrôleur de contacts a quitté.
Espérons qu'Apple corrige ce problème
les déballages forcés sont utilisés pour rendre le code compact bien sûr, vous devez les éviter si possible et si cela peut conduire à un crash. btw je ne sais pas s'il est correct de passer self.contact à déléguer, car il n'est probablement pas créé si vous annulez le flux ps: a changé mon implémentation pour éviter les
déballages forcés
@GxocT - a accepté les urwraps de force. Et ils ne sont pas toujours terribles mais d'autres ne vous ressemblent pas et peuvent toujours les utiliser sans se rendre compte du risque;). J'aime si on laisse au lieu de! quand je ne suis pas sûr à 100%, ce ne sera pas nul. À propos de self.contact - c'est vrai, je ne sais pas ce que le code lib d'Apple transmet normalement au délégué en interne, mais self.contact avait les données de contact et le document CNContactViewController dit que c'est "le contact affiché", donc il semblait correct à utiliser. Mon code n'utilise pas réellement le contact passé dans le délégué d'achèvement afin que je puisse simplement passer zéro dans l'extension.
Barrett
Le contenu (y compris les vues de texte et les claviers) de CNContactViewController doit faire l'objet d'un processus distinct. Si vous pouvez utiliser «Afficher la hiérarchie» dans Xcode pour ce contrôleur de vue, il se peut que le contenu ne soit pas visible. Par conséquent, nous ne pouvons pas contrôler le clavier ni la vue texte.
WildCat
5
Je n'ai pas trouvé de moyen de rejeter le clavier. Mais au moins, vous pouvez faire apparaître ViewController en utilisant ma méthode.
Je ne sais pas pourquoi mais il est impossible de supprimer le clavier dans CNContactViewController. J'ai essayé endEditing:, faire un nouveau premier répondeur UITextField et ainsi de suite. Rien n'a fonctionné.
J'ai essayé de modifier l'action du bouton "Annuler". Vous pouvez trouver ce bouton dans la pile NavigationController, mais son action est modifiée à chaque fois que vous tapez quelque chose.
Enfin, j'ai utilisé la méthode swizzling. Je n'ai pas pu trouver un moyen de fermer le clavier comme je l'ai mentionné plus tôt, mais au moins vous pouvez fermer CNContactViewController lorsque vous appuyez sur le bouton "Annuler".
L'utilisateur peut en fait glisser vers le bas pour fermer le clavier, puis appuyez sur Annuler et voir la feuille d'action. Ce problème est donc regrettable et certainement un bogue (et j'ai déposé un rapport de bogue) mais pas fatal (bien que, pour être sûr, la solution de contournement ne soit pas triviale pour l'utilisateur à découvrir).
Merci @Gxoct pour son excellent travail. Je pense que c'est une question et un message très utiles pour ceux qui travaillent avec CNContactViewController. J'ai aussi eu ce problème (jusqu'à présent) mais dans l'objectif c. J'interprète le code Swift ci-dessus dans l'objectif 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);}}
Création d'une CNContactViewControllercatégorie pour accéder à licencier;
Merci, @GxocT pour votre solution de contournement, cependant, la solution publiée ici est différente de celle que vous avez publiée sur Reddit.
Celui sur Reddit fonctionne pour moi, celui-ci ne fonctionne pas, donc je veux le republier ici. La différence est sur la ligne avec swizzledMethod qui devrait être:
let swizzledMethod = class_getInstanceMethod(object_getClass(self), swizzledSelector){
L'ensemble du code mis à jour est:
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(self), 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)}}
Je n'ai pas trouvé de moyen de rejeter le clavier. Mais au moins, vous pouvez faire apparaître ViewController en utilisant ma méthode.
PS: Vous pouvez trouver des informations supplémentaires sur le sujet reddit: https://www.reddit.com/r/swift/comments/dc9n3a/bug_with_cnviewcontroller_ios_131/
la source
L'utilisateur peut en fait glisser vers le bas pour fermer le clavier, puis appuyez sur Annuler et voir la feuille d'action. Ce problème est donc regrettable et certainement un bogue (et j'ai déposé un rapport de bogue) mais pas fatal (bien que, pour être sûr, la solution de contournement ne soit pas triviale pour l'utilisateur à découvrir).
la source
Corrigé dans iOS 13.4 Testé dans Xcode Simulator
la source
Merci @Gxoct pour son excellent travail. Je pense que c'est une question et un message très utiles pour ceux qui travaillent avec
CNContactViewController
. J'ai aussi eu ce problème (jusqu'à présent) mais dans l'objectif c. J'interprète le code Swift ci-dessus dans l'objectif c.Création d'une
CNContactViewController
catégorie pour accéder à licencier;Les gars qui ne sont pas si familiers avec Swizzling, vous pouvez essayer ce post par matt
la source
Merci, @GxocT pour votre solution de contournement, cependant, la solution publiée ici est différente de celle que vous avez publiée sur Reddit.
Celui sur Reddit fonctionne pour moi, celui-ci ne fonctionne pas, donc je veux le republier ici. La différence est sur la ligne avec swizzledMethod qui devrait être:
L'ensemble du code mis à jour est:
la source