[Résolu] Swift 3 : Orientation forcée compliquée

busterTheobusterTheo Membre
novembre 2016 modifié dans API UIKit #1

Bonjour à  tous.


Je met du texte bold pour vous faire gagner du temps dans ce post certainement trop long.


 


Je reviens donc vers vous, car mon appli était presque prête à  être publiée sur l'ApStore,


mais évidemment, comme rien n'est simple, il faut maintenant que l'appli fonctionne aussi sur iPad 12,9 pouces, et aussi en ios10.


 


Voici la question (et plus bas, les informations nécessaires à  la compréhension) :


 


Comment forcer le landscape sans avoir de crash ?


 


Explications :


J'ai donc fait la mise à  jour de Xcode (Version 8.1 (8B62)), et tout passé en swift 3, suite à  de nombreuses lectures sur le web. Je suis en iOS 9.3 minimum.


 


J'ai fait la conversion swift 3,


recalé le storyBoard avec la nouvelle méthode de Xcode (device, orientation, vary for traits),


modifié plusieurs dimensions qui étaient fixes (car c'était prévu au départ pour 1024x768) en relatif par rapport au MainScreenSize dans le code.


 


C'est du sport, tout ça.


Après pleins de vérifs et de contrôles, j'ai du faire quand même des adaptations un peu bizarres.


 


Bref, je viens ici surtout pour un problème un peu grave que plusieurs personnes sur le web ont également relevé.


Et je ne suis pas parvenu à  le régler.


 


En gros, il s'agit de l'orientation. Je dois être en landscape toujours, jamais de portrait.


Vous connaissez, j'en suis sûr ce message d'Apple : 



 


 


"Supported orientations has no common orientation with the application"

Donc, obligé de mettre portrait dans le build sinon ça crash.


 


Et donc, sur le simulator, je vérifie sur 9 pouces et 13 pouces.


Et lorsque je change de device, ça arrive en portrait. Je rotate donc, et relance l'appli et c'est ok.


 


Sur mon ipad2 (vrai device), ça marche nickel partout sauf quand je vais chercher une image dans l'album, il arrive toujours en portrait. 


 


Puis, les méthodes suivantes ne fonctionnent plus :



override var supportedInterfaceOrientations : UIInterfaceOrientationMask {//not working
return .landscapeLeft
}

override var shouldAutorotate: Bool {//not working
return false
}

J'ai également éplucher ce lien d'Apple.


 


Et, bof... Plein d'essais non concluants.


 


Voilà , j'espère ne pas avoir été insupportablement long, mais c'est un peu hard d'expliquer tout ça succinctement...


 


Merci d'avance pour une éventuelle suggestion...


Réponses

  • CéroceCéroce Membre, Modérateur
    novembre 2016 modifié #2

    Donc, obligé de mettre portrait dans le build sinon ça crash.

    Qu'entends-tu par là ? Tu veux dire que tu as fixé l'orientation dans le panneau "General" de Xcode? (Sache que ça modifie en fait Info.plist).
    Si ton application doit fonctionner uniquement en Landscape, il faut évidemment mettre cette valeur à  Landscape uniquement. Je précise, parce que tu sembles dire le contraire plus haut.
  • Merci pour ta réponse.


     


    Avant cette dernière mise à  jour, pas de portrait dans le panneau général de Xcode.


     


    Après, obligé, sinon crash. Et message Apple.


     


    Dans mon info.plist, j'ai les 3 orientations pour iPad : portrait, landscapeLeft et right.


  • CéroceCéroce Membre, Modérateur
    novembre 2016 modifié #4
    Commence par mettre en landscape uniquement.
    Le message qui s'affiche

    "Supported orientations has no common orientation with the application"

    indique justement qu'il y a une incohérence avec ce réglage.

    Je viens de faire l'essai, et il n'y a RIEN d'autre à  faire. Il ne faut implémenter supportedInterfaceOrientations() que si justement ça diffère du cas général.

    Par contre, je viens de lire dans la doc de UIImagePickerController que, sur iPad, celui-ci doit nécessairement être présenté dans un Popover quand on affiche la Photo Library; sinon, exception.
  • Joanna CarterJoanna Carter Membre, Modérateur

    Pourquoi tu as mis seulement .landscapeLeft ? Qu'est-ce qui se passerai avec un gaucher ?


  • ah merci à  vous, je ré-essaie tout ça...


  • Bon, en fait j'ai un peu tout mélangé (ça sent la tête dans l'guidon, comme d'hab.).


     


    C'est justement en cherchant sur le web pour avoir un UIImagePickerController en paysage... J'ai vu qu'il fallait cocher portrait puis etc...


    Bref, d'la m... Je suis d'accord.


     


    En tout cas, effectivement plus de problème d'orientation (pour l'appli) en 9 et en 13 pouces.


    Et sans implémenter supportedInterfaceOrientations.


     


    Par contre, le UIImagePickerController est effectivement en portrait, et ça, c'est impossible dans cette appli.


     


    Je l'avais auparavant, avant cette mise à  jour,  en mode paysage. avec les deux méthodes supportedInterfaceOrientations.


    Concernant la doc Apple qui dit en portrait, cela marchait quand même en paysage et ne marche plus.


     


    Voici mon ancien code et mon nouveau.


    Ancien code:



    func imageAlbum() {
    self.dismissViewControllerAnimated(true, completion: nil)

    let picker = UIImagePickerController()
    picker.delegate = self

    picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
    picker.mediaTypes = UIImagePickerController.availableMediaTypesForSourceType(picker.sourceType)!
    picker.allowsEditing = false

    let popover = UIPopoverController(contentViewController: picker)
    popover.dismissPopoverAnimated(true)
    popover.presentPopoverFromRect(imageViewPickee.frame, inView: imageViewPickee.superview!, permittedArrowDirections : UIPopoverArrowDirection.Any, animated: true)
    }

    Nouveau code :



    func imageAlbum(_ recognizer: UITapGestureRecognizer) {
    self.dismiss(animated: true, completion: nil)

    let picker = UIImagePickerController()
    picker.delegate = self

    picker.sourceType = .photoLibrary
    picker.allowsEditing = false

    picker.popoverPresentationController?.sourceView = recognizer.view
    picker.popoverPresentationController?.permittedArrowDirections = .any
    picker.popoverPresentationController?.sourceRect = (recognizer.view?.bounds)!

    present(picker, animated: true, completion: nil)
    }

    Une idée pour un picker en mode paysage, ou bien on est obligé de se plier à  cette contrainte Apple ?


     


    Merci d'avance...


  • busterTheobusterTheo Membre
    novembre 2016 modifié #8

    Bon, ben bonjour les dégâts


     


    En 13 pouces, si je cherche une photo dans l'album, ça crash.


     


    Et je ne comprend rien au message d'Apple.


     



     


    objc[13660]: Class PLBuildVersion is implemented in both /Applications/Xcode_81.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/


    SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11f205998) and /Applications/Xcode_81.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/


    SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x11fb40d38). One of the two will be used. Which one is undefined.


    2016-11-14 20:06:29.614378 GuideEsthetique[13660:7271843] [Warning] <_UIPopoverBackgroundVisualEffectView 0x7fa7c8f5b600> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.


    2016-11-14 20:06:30.154 GuideEsthetique[13660:7271843] *** Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and [PUUIAlbumListViewController shouldAutorotate] is returning YES'


    *** First throw call stack:


    (


    0   CoreFoundation                      0x000000010449734b __exceptionPreprocess + 171


    1   libobjc.A.dylib                     0x0000000103adb21e objc_exception_throw + 48


    2   CoreFoundation                      0x0000000104500265 +[NSException raise:format:] + 197


    3   UIKit                               0x00000001055989da -[UIViewController __supportedInterfaceOrientations] + 866


    4   UIKit                               0x0000000105598f63 -[UIViewController __withSupportedInterfaceOrientation:apply:] + 45


    5   UIKit                               0x00000001055997ab -[UIViewController setInterfaceOrientation:] + 145


    6   UIKit                               0x00000001055820c9 -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 1437


    7   UIKit                               0x0000000105496620 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1590


    8   UIKit                               0x000000010549631d -[UIView(Internal) _didMoveFromWindow:toWindow:] + 819


    9   UIKit                               0x000000010549631d -[UIView(Internal) _didMoveFromWindow:toWindow:] + 819


    10  UIKit                               0x000000010549631d -[UIView(Internal) _didMoveFromWindow:toWindow:] + 819


    11  UIKit                               0x00000001054896b4 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 151


    12  UIKit                               0x00000001054895a2 -[UIView(Hierarchy) _postMovedFromSuperview:] + 857


    13  UIKit                               0x00000001054992eb -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1982


    14  UIKit                               0x00000001054877a1 -[UIView(Hierarchy) addSubview:] + 838


    15  UIKit                               0x0000000105552961 -[UITransitionView transition:fromView:toView:removeFromView:] + 1953


    16  UIKit                               0x0000000105f51767 -[UIViewControllerBuiltinTransitionViewAnimator animateTransition:] + 1963


    17  UIKit                               0x0000000105558cbc __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 2915


    18  UIKit                               0x00000001053e52eb _runAfterCACommitDeferredBlocks + 320


    19  UIKit                               0x00000001053d1f6f _cleanUpAfterCAFlushAndRunDeferredBlocks + 566


    20  UIKit                               0x00000001054033da _afterCACommitHandler + 176


    21  CoreFoundation                      0x000000010443be17 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23


    22  CoreFoundation                      0x000000010443bd87 __CFRunLoopDoObservers + 391


    23  CoreFoundation                      0x0000000104420b9e __CFRunLoopRun + 1198


    24  CoreFoundation                      0x0000000104420494 CFRunLoopRunSpecific + 420


    25  GraphicsServices                    0x000000010acfea6f GSEventRunModal + 161


    26  UIKit                               0x00000001053d8964 UIApplicationMain + 159


    27  GuideEsthetique                     0x00000001022b948f main + 111


    28  libdyld.dylib                       0x000000010864768d start + 1


    )


    libc++abi.dylib: terminating with uncaught exception of type NSException


    (lldb)



     


     


    J'ai par ailleurs du code qui s'est inscrit dans plusieurs de mes controllers (le coup du fileprivate) :


    Mais pas dans celui qui m'a fait planter.


     


    Et sur les écrans où il est ajouté, si je le met en commentaire ou pas, cela ne semble pas poser de problème...


     


    Voici le code :



    // FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
    // Consider refactoring the code to use the non-optional operators.
    fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs, rhs) {
    case let (l?, r?):
    return l < r
    case (nil, _?):
    return true
    default:
    return false
    }
    }

    // FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
    // Consider refactoring the code to use the non-optional operators.
    fileprivate func >= <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs, rhs) {
    case let (l?, r?):
    return l >= r
    default:
    return !(lhs < rhs)
    }
    }

    // FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
    // Consider refactoring the code to use the non-optional operators.
    fileprivate func <= <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs, rhs) {
    case let (l?, r?):
    return l <= r
    default:
    return !(rhs < lhs)
    }
    }

    J'ai lu également plein de trucs sur ce truc, mais je n'y comprend rien.


     


    Merci d'avance


  • Le dossier en question :


    bugPLBuildVersion.png


  • J'avais fait ça, suite à  la mise à  jour :


    Voir ce lien qui l'explique, puis je met une copie de mon info.plist plus loin.


     


     


    infoPlist.png

  • busterTheobusterTheo Membre
    novembre 2016 modifié #11

    Et par contre, si je remet portrait dans le panneau Xcode général et donc il se met automatiquement dans le plist,


    eh bien ça ne crash plus, mais j'ai les pas d'orientation appli et un picker vertical... Pfff


     


    J'ai l'impression de me transformer en jongleur débutant à  10 mètres du sol.


  • A part ça, j'avais cette fonction en ios8 qui permettait d'avoir le picker en paysage, et qui marche plus en ios9 minimum



    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.currentContext
    }

    Et comme je suis têtu, je cherche quand même à  avoir mon picker en paysage.


    Mais je n'y arrive pas, car ça commence à  faire appel à  des notions qui me dépassent.


     


    Voici les liens que je visite et dont j'essaie les propositions :


    Extension picker


     


    Supported orientation


     


     


     


    Merci de votre aide...

  • busterTheobusterTheo Membre
    novembre 2016 modifié #13

    Bon, je continue à  me parler à  moi-même :


     


    J'ai enfin trouvé la solution.


    Pour ceux que ça intéresse,


    Elle est là 


     


    En swift 3, on peut quand même détecter quand on tourne l'iPad.


    Et après, on fait ce que l'on veut...


    Avec ça :



    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
    print("Landscape")
    } else {
    print("Portrait")
    }
    }

    Voilà , surcharger la méthode "viewWillTransition".


     


    Ils sont bons aussi sur stackoverflow.


     


    Bon, je met "Résolu".


     


    Merci à  ceux qui ont tenté de m'aider.


     


    Je reste convaincu, que ke n'ai pas été très clair sur ce coup là , et que j'ai un peu surchargé ce post de multiples infos un peu soulantes. Désolé.


     


      :p   :-*  :p


Connectez-vous ou Inscrivez-vous pour répondre.