Tag Archives: Xamarin.tvOS

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9814)

En informatique, les problèmes les plus simples sont parfois les plus bizarres à comprendre et c’est ce qui m’est arrivé il y a 2 jours sur un prototype Xamarin.iOS sur laquelle je travaille.

L’application est on ne peut plus classique puisqu’elle fait simplement des appels à des webservices pour afficher des données sous forme d’une liste.

Alors que tout fonctionne correctement au début, en passant les webservices de HTTP à HTTPS, l’erreur, dont la description est très parlante (NSURLSession/NSURLConnection HTTP load failed kCFStreamErrorDomainSSL, -9814), se produit de manière subite.

La première réaction a été de se dire que j’ai oublié de configurer ATS (App Transport Security) dans le fichier Info.plist de l’application. Après vérification, ce n’est pas le cas puisque la configuration autorise tous les appels comme indiqué ci-dessous.

<key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
  </dict>
</key>

Après recherche dans la documentation officielle Apple, le code 9814 signifie que le certificat SSL est expiré mais ce n’est pas le cas puisque celui-ci expire en 2019.

D’où peut donc bien venir cette erreur dans ce cas ?

Après plus d’une heure à tourner en rond, en cherchant sur StackOverflow et toutes les sources classiques d’aide pour un développeur, une illumination m’est apparue : “Vérifions quelle date est utilisée par mon périphérique actuellement”.

BINGO !!! Le périphérique qui n’a apparemment jamais réussi à se synchroniser avec une source de temps (ou défini manuellement dans les paramètres du système), utilise une date en Janvier 1970.

L’erreur ne signifie pas dans ce cas que le certificat est réellement expiré, mais qu’il n’a pas réussi à être validé dans la séquence normale de validation des communications HTTPS.

Je partage donc cette petite mésaventure qui vous évitera de perdre du temps, simplement parce que le périphérique utilisé n’était pas à l’heure. Après vérification, la même erreur s’applique sur tvOS si jamais vous travaillez sur cette plateforme.

React to changes of focus in your Xamarin.tvOS applications

The focus engine introduced in UIKit for tvOS 9.0 is one of the key concepts you should know if you want to develop applications for the Apple TV.

It allows you to know what is the control that is currently focused on the screen, and to be notified when the focus changes from a view to another view (e.g. from a textfield to a button, from a collection view cell to the next cell, etc…).

Today I have created my first and simple application that uses a UICollectionView with few cells as you can see on the screenshot below. I was proud of my work until I realized that when the application is running, there is no visual indication that gives a feedback to the user of which cell is currently selected (cell #0 or cell #1).

tvOS - CollectionView without focus

I then looked for solutions to surround the focused cell with a white border to give an instant feedback to the user. The focus engine gives you this capability through the DidUpdateFocus method.

This method exposes a context to retrieve which views are focused (the previous and the next), and an animation coordinator to change attributes of these views within an animation.

When you know this method, it is very simple to accomplish your goal. The example below shows you how to remove the border for the old focused view, and add a border for the new focused view.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Layer.BorderColor = UIColor.Clear.CGColor;
      previousCell.Layer.BorderWidth = 0;
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Layer.BorderColor = UIColor.White.CGColor;
      nextCell.Layer.BorderWidth = 5;
    }
  }, null);
}

The visual feedback is now more understandable for the user and he knows that the currently focused view is the cell #1.

tvOS - CollectionView with border when focused

It is good but if I want to have the same feature that is standard on the Apple TV (the cells sizes increase/decrease when they are focused/unfocused), what I need to do ?

If your cell is only composed with an UIImageView, you can select the option called “Adjusts image when focused” on the properties of this view in Xcode.

tvOS - ImageView adjusts image when focused

But when your cells are more complex like the sample below (each cell is composed with an UIImageView, a translucent UIView with a UILabel above), then you probably want to increase the size all the items inside the cell at the same time.

tvOS - CollectionView with scale when focused

No problem to achieve this goal with the same method that was previously mentioned. We just need to apply a transformation to the cell (CGAffineTransform.MakeScale(…)) when it receive the focus, and revert it (CGAffineTransform.MakeIdentity()) when the focus is lost.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Transform = CGAffineTransform.MakeIdentity();
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Transform = CGAffineTransform.MakeScale(1.25f, 1.25f);
    }
  }, null);
}

As we have seen in this article, it’s pretty easy to interact with the focus engine of tvOS to apply any modifications on views, depending on the focus state of each of them.