513 votes

Pourquoi créer « Implicitement Unwrapped Optionals » ?

Pourquoi souhaitez-vous créer un "Implicitly Unwrapped Optionals" contre la création d'un variable ou une constante. Si vous savez que cela peut être avec succès déballé alors pourquoi créer une option en premier lieu? Par exemple, pourquoi est-ce:

let someString:String! = "this is the string";

va être plus utile vs:

let someString:String = "this is the string";

Si "options indiquent qu'une constante ou une variable est autorisé à avoir "aucune valeur"." Mais "parfois, c'est clairement de la structure du programme qu'une option aura toujours une valeur, après que la valeur est d'abord définir" Quel est le point d'en faire une option en premier lieu? Si vous connaissez une option est toujours d'avoir une valeur... N'est-ce pas.... pas une option?

464voto

drewag Points 12938

Avant que je puisse décrire les cas d'utilisation pour Implicitement Déballé Options, vous devriez déjà comprendre ce que les Options et Implicitement Déballé Options sont en Swift. Si vous ne le faites pas, je vous recommande d'abord de lire mon article sur les options

Quand Utiliser Un Implicitement Déballé En Option

Il y a quatre raisons principales que l'on pourrait créer un Implicitement Déballé en Option. Tous ont à voir avec la définition d'une variable qui ne sera jamais accessible en nil parce que sinon, la Swift compilateur va toujours vous forcer explicitement déballer une Option.

1. Une Constante Qui Ne Peut Être Défini Lors De L'Initialisation

Chaque membre de la constante doit avoir une valeur par le temps de l'initialisation est terminée. Parfois, une constante ne peut pas être initialisé à sa valeur correcte lors de l'initialisation, mais il peut encore être garanti d'avoir une valeur avant d'être consulté.

En utilisant une variable Optionnelle permet de contourner ce problème, car l'Option est automatiquement initialisé avec nil et la valeur qu'elle peut éventuellement contenir sera toujours immuable. Cependant, il peut être une douleur à être constamment à déballer une variable que vous savez pour sûr, n'est pas nul. Implicitement Déballé Options de réaliser les mêmes prestations en Option avec l'avantage supplémentaire que l'on n'a pas explicitement déballer partout.

Un grand exemple de ceci est quand un membre de la variable ne peut pas être initialisé dans une sous-classe UIView jusqu'à ce que le point de vue est chargé:

class MyView : UIView {
    @IBOutlet var button : UIButton!
    var buttonOriginalWidth : CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

Ici, vous ne pouvez pas calculer la largeur d'origine de la touche jusqu'à ce que le point de vue des charges, mais vous savez qu' viewDidLoad sera appelée avant toute autre méthode sur la vue (autres que l'initialisation). Au lieu de forcer la valeur à être explicitement déballé inutilement partout dans votre classe, vous pouvez le déclarer comme un Implicitement Déballé en Option.

2. L'interaction avec un Objectif-C API

Chaque référence à un objet en Objective-C est un pointeur, ce qui signifie qu'il peut être nil. Ce qui signifie que chaque interaction avec un Objectif-C de l'API de Swift devez utiliser une option où il y a une référence à un objet. Vous pouvez utiliser une normale en Option dans chacun de ces cas, mais si vous savez certainement que la référence ne sera pas nil, vous pouvez vous épargner de déballage de code en la déclarant comme Implicitement Déballé en Option.

Un bon exemple de ceci est une UITableViewDataSource:

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? { return nil }

Ici, vous savez que la méthode ne sera jamais appelé sans tableView ou indexPath. Ce serait une perte de temps de le vérifier pour nil. Si c'était purement Swift API, un ne serait pas la déclarer comme une Option.

3. Lorsque Votre Application Ne peut pas Récupérer à Partir d'une Variable nil

Ce doit être extrêmement rare, mais si votre application peut littéralement pas de continuer à exécuter si une variable est - nil lors de l'accès, ce serait une perte de temps pour la peine de le tester pour nil. Normalement, si vous avez une condition qui doit absolument être vrai pour votre application de fonctionner, vous pouvez utiliser un assert. Un Implicitement Déballé en Option a une assertion sans intégré à.

4. NSObject Initialiseurs

Apple a au moins un cas étrange du Implicitement Déballé Options. Techniquement, tous les initialiseurs de classes qui héritent de NSObject retour Implicitement Déballé Options. C'est parce que l'initialisation en Objective-C peut renvoyer nil. Cela signifie que, dans certains cas, c'est que vous voulez toujours être en mesure de tester le résultat de l'initialisation de nil. Un parfait exemple de cela est avec UIImage si l'image n'existe pas:

var image : UIImage? = UIImage(named: "NonExistentImage")
if image != nil {
    println("image exists")
}
else {
    println("image does not exist")
}

Si vous pensez qu'il ya une chance que votre image n'existe pas et vous pouvez facilement traiter ce scénario, vous pouvez déclarer la variable qui reflète l'initialisation explicitement comme une Option de sorte que vous pouvez vérifier pour nil. Vous pouvez également utiliser un Implicitement Déballé en Option ici, mais depuis que vous êtes planification pour le vérifier de toute façon, il est préférable d'utiliser un normal en Option.

Quand Ne Pas Utiliser Un Implicitement Déballé En Option

1. Paresseusement Membre Calculé Variables

Parfois, vous avez un membre de la variable ne doit jamais être nul, mais il ne peut pas être réglé à la valeur correcte lors de l'initialisation. Une solution consiste à utiliser un Implicitement Déballé en Option, mais une meilleure solution est d'utiliser un paresseux variable:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

Maintenant, le membre de la variable contents n'est pas initialisé jusqu'à ce que la première fois qu'il est accessible. Cela donne à la classe une chance d'obtenir dans le bon état avant le calcul de la valeur initiale.

Remarque: Cela peut sembler contredire #1 à partir de ci-dessus. Cependant, il est important de faire la distinction. L' buttonOriginalWidth ci-dessus doit être défini lors de viewDidLoad pour empêcher quiconque de changer les boutons largeur de l'avant de la propriété est accessible.

2. Partout Ailleurs

Pour la plupart, Implicitement Déballé Options doit être évitée car si elle est utilisée à tort, l'ensemble de votre application crash quand il est accessible à tout nil. Si vous êtes toujours pas sûr de savoir si une variable peut être nul, toujours par défaut à l'aide d'un normal en Option. Déballage d'une variable qui n'est jamais nil certainement ne fait pas mal, très bien.

132voto

Catfish_Man Points 15439

Prenons le cas d’un objet qui peut-être avoir des propriétés nulle alors qu’elle est en cours de construction et configuré, mais il est immuable et non-nil par la suite (NSImage est souvent traitée de cette façon, bien que dans son cas, il est toujours utile de se transformer parfois). Optionals implicitement désencapsulé nettoieriez son code une bonne affaire, avec des pertes relativement faibles de sécurité (tant que celui de garantie tenue, il serait prudent).

(Edit) Pour être clair cependant : optionals réguliers sont presque toujours préférables.

56voto

n8gray Points 2923

Implicitement déballé options sont utiles pour la présentation d'une propriété non-facultatif quand vraiment il doit être facultative sous les couvertures. Cela est souvent nécessaire pour "attacher le noeud" entre deux objets que chacun besoin d'une référence à l'autre. Cela est logique, quand ni la référence est en fait facultatif, mais l'un d'eux doit être nul, tandis que la paire est en cours d'initialisation.

Par exemple:

// These classes are buddies that never go anywhere without each other
class B {
    var name : String
    weak var myBuddyA : A!
    init(name : String) {
        self.name = name
    }
}

class A {
    var name : String
    var myBuddyB : B
    init(name : String) {
        self.name = name
        myBuddyB = B(name:"\(name)'s buddy B")
        myBuddyB.myBuddyA = self
    }
}

var a = A(name:"Big A")
println(a.myBuddyB.name)   // prints "Big A's buddy B"

Tout B instance doit toujours valide myBuddyA référence, de sorte que nous ne voulons pas faire de l'utilisateur traiter comme facultatif, mais nous en avons besoin pour être en option, de sorte que nous pouvons construire une B , avant d'avoir un A à consulter.

TOUTEFOIS! Ce type de mutuelle de référence exigence est souvent une indication de couplage et de mauvaise conception. Si vous vous trouvez en s'appuyant sur implicitement déballé options que vous devriez probablement envisager de refactoring pour éliminer la croix-dépendances.

38voto

Palimondo Points 2337

Implicitement déballé options sont compromis pragmatique pour rendre le travail en environnement hybride qui a pour interagir avec les cadres de Cacao et de leurs conventions plus agréable, tout en permettant par étapes de la migration dans les plus sûrs de programmation: un changement de paradigme sans pointeurs null - forcée par la Swift compilateur.

Swift livre, dans Les Bases de chapitre, de section Implicitement Déballé Options dit:

Implicitement déballé options sont utiles lorsqu'une option de valeur est confirmée d'exister immédiatement après l'option est d'abord définie et peut certainement être supposé exister à chaque point par la suite. La principale utilisation de implicitement déballé options dans Swift est au cours de l'initialisation de classe, comme décrit dans le Propriétaire de Références et Implicitement Déballé en Option Propriétés.
...
Vous pouvez penser à un implicitement déballé option que de donner l'autorisation pour l'option d'être déballé automatiquement lorsqu'il est utilisé. Plutôt que de placer un point d'exclamation après l'option de nom à chaque fois que vous l'utilisez, vous placez un point d'exclamation après l'option du type lorsque vous déclarez.

Cela revient à utiliser les cas où la non-nil-ness de propriétés est établie via l'utilisation de la convention, et ne peut pas être exécutée par le compilateur lors de l'initialisation de classe. Par exemple, l' UIViewController propriétés sont initialisées à partir des Plumes ou des Storyboards, où l'initialisation est divisé en phases distinctes, mais après l' viewDidLoad() vous pouvez supposer que les propriétés existent généralement. Par ailleurs, afin de satisfaire le compilateur, il fallait être à l'aide de la forcé de déballage, de fixation en option ou facultatif de chaînage seulement à masquer le principal but de ce code.

Au-dessus de la partie de la Swift livre se réfère aussi à l' Automatique de Comptage de Référence chapitre:

Cependant, il existe un troisième scénario, dans lequel les deux propriétés doit toujours avoir une valeur, et ni la propriété devrait jamais être nil une fois l'initialisation terminée. Dans ce scénario, il est utile de combiner un propriétaire de la propriété sur une classe avec un implicitement déballé en option la propriété de l'autre classe.

Cela permet à la fois de propriétés à accéder directement (sans option déballage) une fois l'initialisation terminée, en évitant un cycle de référence.

Ce qui revient à les bizarreries de ne pas être une de ces ordures de la langue, donc la rupture de conserver des cycles est sur vous en tant que programmeur et implicitement déballé options sont un outil pour cacher ce caprice.

Que couvre l' "Quand utiliser implicitement déballé options dans votre code?". En tant que développeur de l'application, vous aurez surtout à les rencontrer dans les signatures de méthodes de bibliothèques écrites en Objective-C, qui n'a pas la capacité de s'exprimer en option types.

À partir de l'Utilisation de Swift avec Cocoa et Objective-C, section de Travail à néant:

Parce que Objective-C ne fournit aucune garantie qu'un objet est non-nul, Swift fait toutes les classes dans l'argument, les types et les types de retour facultatif importés Objective-C Api. Avant d'utiliser un Objectif-C objet, vous devriez vérifier pour s'assurer qu'il ne manque pas.

Dans certains cas, vous pouvez être absolument certain que l'Objective-C méthode ou propriété ne retourne jamais une nil référence d'objet. Pour rendre les objets dans ce scénario particulier plus commode de travailler avec, Swift importations types d'objets comme implicitement déballé options. Implicitement déballé en option types comprennent tous les dispositifs de sécurité en option types. En outre, vous pouvez accéder à la valeur directement sans vérification de nil ou de déballage de vous-même. Lorsque vous accéder à la valeur de ce genre de type facultatif en toute sécurité sans ôter d'abord, implicitement déballé en option vérifie si la valeur est manquante. Si la valeur est manquante, une erreur d'exécution se produit. Par conséquent, vous devriez toujours vérifier et de déballer un implicitement déballé en option vous-même, sauf si vous êtes sûr que la valeur ne peut pas être absent.

...et au-delà, c'est même là dragons

19voto

rickster Points 19870

D'une ligne (ou plusieurs) des exemples simples ne couvrent pas le comportement des options très bien oui, si vous déclarez une variable, et de lui fournir une valeur tout de suite, il n'y a aucun point dans une option.

Le meilleur des cas que j'ai vu jusqu'à présent est la configuration qui se passe après l'initialisation de l'objet, par l'usage qui est "garanti" pour suivre le programme d'installation, par exemple en vue de contrôleur:

class MyViewController: UIViewController {

    var screenSize: CGSize?

    override func viewDidLoad {
        super.viewDidLoad()
        screenSize = view.frame.size
    }

    @IBAction printSize(sender: UIButton) {
        println("Screen size: \(screenSize!)")
    }
}

Nous savons printSize sera appelé après le point de vue est chargé, c'est une méthode d'action relié à un contrôle à l'intérieur de ce point de vue, et nous avons fait en sorte de ne pas l'appeler autrement. De sorte que nous pouvons nous sauver nous-mêmes certains facultatif de vérification/liaison avec l' !. Swift ne peut reconnaître que la garantie (au moins jusqu'à ce que Apple résout le problème de l'arrêt), de sorte que vous dire au compilateur qu'il existe.

Cela rompt la sécurité de type à un certain degré. N'importe où vous avez une implicitement déballé en option est un endroit de votre application peut se bloquer si votre "garantie" n'est pas toujours tenir, c'est donc un outil à utiliser avec parcimonie. En outre, en utilisant ! tout le temps donne l'impression que vous êtes à crier, et personne n'aime ça.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X