Que signifie "erreur fatale: découverte inattendue nulle en déballant une valeur optionnelle"?

mon programme Swift s'écroule avec EXC_BAD_INSTRUCTION et cette erreur. Qu'est-ce que ça veut dire, et comment je le Répare?

erreur fatale: de façon inattendue trouvé nulle, tandis que d'ôter une valeur Facultative


ce post est destiné à recueillir des réponses aux questions "trouvé de façon inattendue néant", de sorte qu'ils ne sont pas dispersés et difficile à trouver. N'hésitez pas à ajouter votre propre réponse ou modifier la réponse wiki existante.

310
demandé sur jtbandes 2015-08-23 22:10:23

8 réponses

Cette réponse est wiki de la communauté . Si vous pensez qu'il pourrait être amélioré, n'hésitez pas à modifier !

Background: What is an Optional?

dans Swift, Optional est un type générique qui peut contenir une valeur (de toute nature), ou aucune valeur du tout.

dans beaucoup d'autres les langages de programmation, une valeur "sentinelle" particulière est souvent utilisée pour indiquer un manque d'une valeur . Dans L'Objectif-C, par exemple, nil (le pointeur nul ) indique l'absence d'un objet. Mais cela devient plus délicat quand on travaille avec des types primitifs - -1 devrait-il être utilisé pour indiquer l'absence d'un entier, ou peut-être INT_MIN , ou un autre entier? Si une valeur est choisie pour signifier "non entier", que signifie qu'il ne peut plus être traité comme une valeur valide .

Swift est une langue à sécurité de type, ce qui signifie que la langue vous aide à être clair sur les types de valeurs que votre code peut travailler avec. Si une partie de votre code attend une chaîne de caractères, tapez sécurité vous empêche de lui passer un Int par erreur.

dans Swift, tout type peut être rendu facultatif . Une valeur optionnelle peut prendre n'importe quelle valeur du type original, ou la valeur spéciale nil .

Les options

sont définies avec le suffixe ? sur le type:

var anInt: Int = 42
var anOptionalInt: Int? = 42
var anotherOptionalInt: Int?    // `nil` is the default when no value is provided

l'absence d'une valeur dans un facultatif est indiquée par nil :

anOptionalInt = nil

(notez que ce nil n'est pas le même que le nil dans L'objectif-C. Objectif-C, nil est l'absence d'un pointeur d'objet valide ; dans Swift, les options ne sont pas limitées aux objets/types de référence. Optional se comporte de la même façon que Haskell peut-être .)


Pourquoi ai-je " erreur fatale: de façon inattendue trouvé nulle, tandis que d'ôter une valeur Facultative "?

afin d'accéder à un option de valeur (si elle en a un), vous devez déballer . Une valeur optionnelle peut être déballée de manière sûre ou forcée. Si vous forcez-unwrap un optionnel, et il n'a pas ont une valeur, votre programme va planter avec le message ci-dessus.

Xcode vous montrera le crash en mettant en surbrillance une ligne de code. Le problème se produit sur cette ligne.

crashed line

cette collision peut se produire avec deux types différents de force-unwrap:

1. Force Explicite Déballage

Ceci est fait avec l'opérateur ! sur une option. Par exemple:

let anOptionalString: String?
print(anOptionalString!) // <- CRASH

comme anOptionalString est nil ici, vous obtiendrez un crash sur la ligne où vous forcez déballer.

2. Options Implicitement Non Emballées

ceux-ci sont définis par un ! , plutôt que par un ? après le type.

var optionalDouble: Double!   // this value is implicitly unwrapped wherever it's used

ces options sont supposées contenir une valeur. Par conséquent, chaque fois que vous accédez à une option implicitement déballée, elle sera automatiquement déballée pour vous. S'il ne contient pas de valeur, il se plantera.

print(optionalDouble) // <- CRASH

pour déterminer quelle variable a causé le crash, vous pouvez tenir pomme en cliquant pour afficher la définition, où vous pourriez trouver le type optionnel.

IBOutlets, en particulier, sont généralement implicitement non emballées optionnelles. C'est parce que votre XIB ou storyboard reliera les sorties à l'exécution, après initialisation. Vous devez donc vous assurer que vous n'ACCÉDEZ PAS aux prises de courant avant qu'elles ne soient chargées. Vous aussi devrait vérifier que les connexions sont correctes dans votre storyboard/fichier xib, sinon les valeurs seront nil à l'exécution, et donc crash quand ils sont implicitement déballés.


quand devrais-je forcer à déballer une option?

Force Explicite Déballage

en règle générale, vous ne devez jamais forcer explicitement le déballage d'un optionnel avec l'opérateur ! . Il peut y être des cas où l'utilisation de ! est acceptable – mais vous ne devez jamais utiliser si vous êtes sûr à 100% que cette option contient une valeur.

alors qu'il peut être une occasion où vous pouvez utiliser la force unwrapping, comme vous le savez pour un fait qu'un optionnel contient une valeur – il n'y a pas un simple endroit où vous ne pouvez pas décompresser en toute sécurité que optionnel à la place.

Implicitement Non Emballées Optionnelles

ces variables sont conçues pour que vous puissiez reporter leur assignation jusqu'à plus tard dans votre code. Il est votre responsabilité de s'assurer qu'ils ont une valeur avant d'y accéder. Cependant, parce qu'ils impliquent le déballage de force, ils sont encore intrinsèquement dangereux – comme ils supposer votre valeur est non-nulle, même mais attribuer Zéro est valable.

vous ne devez utiliser que des options implicitement non emballées comme un dernier recours . Si vous pouvez utiliser une variable paresseuse , ou fournir une valeur par défaut pour une variable – vous devriez le faire au lieu d'utiliser une option implicitement déballée.

cependant, il existe un quelques scénarios où les options implicitement non emballées sont bénéfique , et vous êtes toujours en mesure d'utiliser diverses façons de les déballer en toute sécurité comme indiqué ci – dessous-mais vous devriez toujours les utiliser avec la prudence nécessaire.


Comment puis-je gérer en toute sécurité les options?

la façon la plus simple de vérifier si une option contient une valeur, est de la comparer à nil .

if anOptionalInt != nil {
    print("Contains a value!")
} else {
    print("Doesn’t contain a value.")
}

toutefois, 99,9% du temps lorsque vous travaillez avec des options, que vous voulez accéder à la valeur qu'il contient, si elle contient. Pour ce faire, vous pouvez utiliser fixation facultative .

Option Obligatoire

la liaison optionnelle vous permet de vérifier si une option contient une valeur – et vous permet d'assigner la valeur libre à une nouvelle variable ou constante. Il utilise la syntaxe if let x = anOptional {...} ou if var x = anOptional {...} , selon si vous avez besoin de modifier la valeur de la nouvelle variable après l'avoir liée.

par exemple:

if let number = anOptionalInt {
    print("Contains a value! It is \(number)!")
} else {
    print("Doesn’t contain a number")
}

ce que cela fait est de vérifier d'abord que l'option contient une valeur. Si elle fait , alors la valeur" déballée " est assignée à une nouvelle variable ( number ) – que vous pouvez alors librement utiliser comme si elle était non-optionnelle. Si l'option ne contient pas de valeur, alors la clause else sera invoquée, comme vous le feriez attendre.

ce qui est soigné au sujet de la reliure optionnelle, est que vous pouvez déballer plusieurs optionals en même temps. Vous pouvez simplement séparer les relevés avec une virgule. La déclaration réussira si toutes les options étaient déballées.

var anOptionalInt : Int?
var anOptionalString : String?

if let number = anOptionalInt, let text = anOptionalString {
    print("anOptionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
    print("One or more of the optionals don’t contain a value")
}

une Autre astuce est que vous pouvez également utiliser des virgules pour vérifier une certaine condition sur la valeur, après déballage.

if let number = anOptionalInt, number > 0 {
    print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}

la seule prise avec utilisation de reliure optionnelle dans une instruction if, est que vous ne pouvez accéder à la valeur déballée qu'à partir de la portée de l'instruction. Si vous avez besoin d'accéder à la valeur de l'extérieur de la portée de la déclaration, vous pouvez utiliser un garde déclaration .

A guard statement vous permet de définir une condition de succès – et le champ d'application actuel ne continuera l'exécution que si cette condition est remplie. Ils sont définis avec la syntaxe guard condition else {...} .

ainsi, pour les utiliser avec une reliure optionnelle, vous pouvez faire ceci:

guard let number = anOptionalInt else {
    return
}

(notez que dans le corps de garde, vous doit utiliser l'un des déclarations de transfert de contrôle afin de sortir de la portée du code actuellement en cours d'exécution).

si anOptionalInt contient une valeur, elle sera déballée et assignée à la nouvelle number constante. Le code après le gardien continuera alors l'exécution. Si elle ne contient pas de valeur – le gardien exécutera le code dans les parenthèses, ce qui conduira au transfert de contrôle, de sorte que le code immédiatement après ne sera pas exécuté.

la vraie chose soignée au sujet des déclarations de garde est la valeur déballée est maintenant disponible à utiliser dans le code qui suit la déclaration (comme nous savons que le code futur peut seulement exécuter si l'option a une valeur). Il s'agit d'un grand pour éliminer ‘pyramides of doom’ créé par l'imbrication des déclarations if multiples.

par exemple:

guard let number = anOptionalInt else {
    return
}

print("anOptionalInt contains a value, and it’s: \(number)!")
Les gardes

supportent également les mêmes astuces que la déclaration if supportée, telles que le déballage de plusieurs options en même temps et l'utilisation de la clause where .

Si vous utilisez un si ou guard statement dépend complètement de savoir si un code futur nécessite le facultatif pour contenir une valeur.

Néant Opérateur De Coalescence

le néant opérateur de coalesceur est une version en style télégraphique du opérateur conditionnel ternaire , principalement conçu pour convertir les optionnels en non-optionnels. Il a la syntaxe a ?? b , où a est un en option et de type b est du même type que a (bien que généralement non-facultatif).

il permet essentiellement de dire "si a contient une valeur, déballez-la. Si elle ne retourne pas alors b à la place". Par exemple, vous pouvez l'utiliser comme ceci:

let number = anOptionalInt ?? 0

cela définira une constante number de type Int , qui contiendra soit la valeur de anOptionalInt , si elle contient une valeur, ou 0 dans le cas contraire.

c'est juste un raccourci pour:

let number = anOptionalInt != nil ? anOptionalInt! : 0

Chaînage Facultatif

vous pouvez utiliser optional Chaining pour appeler une méthode ou accéder à une propriété sur un optionnel. Cela se fait simplement en Suffixe le nom de la variable avec un ? lors de son utilisation.

par exemple, disons que nous avons une variable foo , de type un optionnel Foo instance.

var foo : Foo?

si nous voulions appeler une méthode sur foo qui ne renvoie rien, nous pouvons simplement faire:

foo?.doSomethingInteresting()

Si foo contient une valeur, cette méthode sera appelée sur elle. Si ce n'est pas le cas, rien de mal ne se produira – le code continuera tout simplement à être exécuté.

(ce comportement est similaire à l'envoi de messages à nil dans L'objectif-C)

cela peut donc également être utilisé pour définir des propriétés ainsi que des méthodes d'appel. Par exemple:

foo?.bar = Bar()

encore une fois, rien de mal ne se passera ici si foo est nil . Votre code va simplement continuer à être exécuté.

une autre astuce soignée que le chaînage facultatif vous permet de faire est de vérifier si le fait de définir une propriété ou d'appeler une méthode a été un succès. Vous pouvez le faire en comparant la valeur de retour à nil .

(ceci est parce qu'une valeur optionnelle retournera Void? plutôt que Void sur une méthode qui ne retourne rien)

par exemple:

if (foo?.bar = Bar()) != nil {
    print("bar was set successfully")
} else {
    print("bar wasn’t set successfully")
}

cependant, les choses deviennent un peu plus délicates en essayant d'accéder à des propriétés ou à des méthodes d'appel qui retournent une valeur. Parce que foo est optionnel, tout retour de celui-ci sera également facultatif. Pour gérer cela, vous pouvez soit déballer les options qui sont retournées en utilisant l'une des méthodes ci – dessus-ou déballer foo lui-même avant d'accéder aux méthodes ou d'appeler des méthodes qui retournent des valeurs.

aussi, comme le nom l'indique, vous pouvez ‘enchaîner’ ces déclarations ensemble. Cela signifie que si foo a un bien optionnel baz , qui a un bien qux - vous pouvez écrire ce qui suit:

let optionalQux = foo?.baz?.qux

encore une fois, parce que foo et baz sont optionnels, la valeur retournée de qux sera toujours optionnelle même si qux lui-même est optionnel.

map et flatMap

une caractéristique souvent sous-utilisée avec les options est la possibilité d'utiliser les fonctions map et flatMap . Ceux-ci vous permettent d'appliquer non-optionnel transforme en variables optionnelles. Si une option de a une valeur, vous pouvez appliquer une transformation donnée. Si elle n'a pas de valeur, il restera nil .

par exemple, disons que vous avez une chaîne optionnelle:

let anOptionalString:String?

en lui appliquant la fonction map – nous pouvons utiliser la fonction stringByAppendingString afin de la concaténer à une autre chaîne.

parce que stringByAppendingString prend un argument de chaîne non-optionnel, nous ne pouvons pas entrer nos facultatif chaîne directement. Cependant, en utilisant map , nous pouvons utiliser stringByAppendingString pour être utilisé si anOptionalString a une valeur.

par exemple:

var anOptionalString:String? = "bar"

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // Optional("foobar")

Cependant, si anOptionalString n'a pas de valeur, map sera de retour nil . Par exemple:

var anOptionalString:String?

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // nil

flatMap fonctionne de la même manière que map , sauf qu'il vous permet de retourner un autre facultatif à l'intérieur du corps de fermeture. Cela signifie que vous pouvez entrer un optionnel dans un processus qui nécessite une entrée non-optionnelle, mais peut sortir un optionnel lui-même.

try!

le système de gestion des erreurs de Swift peut être utilisé en toute sécurité avec Do-Try-Catch :

do {
    let result = try someThrowingFunc() 
} catch {
    print(error)
}

si someThrowingFunc() génère une erreur, celle-ci sera détectée en toute sécurité dans le bloc catch .

la constante error que vous voyez dans le bloc catch n'a pas été déclarée par nous - elle est générée automatiquement par catch .

vous pouvez également déclarer error vous-même, il a l'avantage de pouvoir le mouler dans un format utile, par exemple:

do {
    let result = try someThrowingFunc()    
} catch let error as NSError {
    print(error.debugDescription)
}

en utilisant try de cette façon est la bonne façon d'essayer, de saisir et de gérer les erreurs provenant des fonctions de lancer.

il y a aussi try? qui absorbe l'erreur:

if let result = try? someThrowingFunc() {
    // cool
} else {
    // handle the failure, but there's no error information available
}

mais le système de gestion des erreurs de Swift fournit également un moyen de "forcer l'essai" avec try! :

let result = try! someThrowingFunc()

les concepts expliqués dans ce post s'appliquent aussi ici: si une erreur est lancée, l'application va planter.

Vous ne devriez jamais utiliser try! si vous pouvez prouver que son résultat ne manquera jamais dans votre contexte - et cela est très rare.

la plupart du temps, vous utiliserez le système complet Do-Try-Catch - et le facultatif, try? , dans les rares cas où le traitement de l'erreur n'est pas important.


ressources

530
répondu Hamish 2018-07-03 17:57:23

TL; DR answer

Avec de très rares exceptions près , cette règle d'or:

éviter l'utilisation de !

Déclarer la variable en option ( ? ), pas implicitement déballé options (IUO) ( ! )

en d'autres termes, plutôt utiliser:

var nameOfDaughter: String?

au lieu de:

var nameOfDaughter: String!

Déballer variable en option à l'aide de if let ou guard let

soit variable unwrap comme ceci:

if let nameOfDaughter = nameOfDaughter {
    print("My daughters name is: \(nameOfDaughter)")
}

ou comme ceci:

guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")

cette réponse se voulait concise, pour une compréhension complète, lire la réponse acceptée

48
répondu Sajjon 2018-07-25 09:59:10

Cette question revient TOUT LE TEMPS . C'est l'une des premières choses avec lesquelles les nouveaux développeurs Swift se battent.

Contexte:

Swift utilise le concept d ' "optionnel" pour traiter des valeurs qui pourraient contenir une valeur, ou non. Dans D'autres langues comme C, vous pouvez stocker une valeur de 0 dans une variable pour indiquer qu'elle ne contient aucune valeur. Cependant, si 0 est une valeur valide? Alors vous pourriez utiliser -1. Si -1 est une valeur valide? Et ainsi de suite.

les options Swift vous permettent de configurer une variable de n'importe quel type pour contenir soit une valeur valide, soit aucune valeur.

vous mettez un point d'interrogation après le type lorsque vous déclarez une variable moyenne (type x, ou aucune valeur).

Une option est en fait un conteneur qui contient une variable d'un type donné, ou rien.

une option doit être "déballée" afin de récupérer la valeur à l'intérieur.

Le "!"l'opérateur est une force de "déballer" de l'opérateur. Il dit: "faites-moi confiance. Je sais ce que je fais. Je vous garantis que lorsque ce code sera activé, la variable ne contiendra pas zéro."Si vous vous trompez, vous vous écrasez.

à Moins que vous vraiment faire savez ce que vous faites, évitez de le "!"force l'opérateur de déballage. C'est probablement la plus grande source d'accidents pour les programmeurs Swift débutants.

comment traiter avec les optionnels:

il y a beaucoup d'autres façons de traiter les options qui sont plus sécuritaires. Voici quelques (liste non exhaustive)

vous pouvez utiliser" optional binding "ou" if let "pour dire" si cette option contient une valeur, enregistrez cette valeur dans une nouvelle variable non-optionnelle. Si l'option Ne contient pas de valeur, sautez le corps de cette instruction if".

voici un exemple de reliure optionnelle avec notre foo optionnelle:

if let newFoo = foo //If let is called optional binding. {
  print("foo is not nil")
} else {
  print("foo is nil")
}

notez que la variable que vous définissez lorsque vous utilisez la présentation facultative n'existe que dans le corps de l'instruction if.

alternativement, vous pouvez utiliser une instruction guard, qui vous permet de quitter votre fonction si la variable est nulle:

func aFunc(foo: Int?) {
  guard let newFoo = input else { return }
  //For the rest of the function newFoo is a non-optional var
}

les déclarations de garde ont été ajoutées dans Swift 2. Guard vous permet de préserver le "chemin d'or" à travers votre code, et d'éviter les niveaux sans cesse croissants d'ifs imbriqués qui en résultent parfois de l'aide "si laisser" de fixation en option.

il y a aussi une construction appelée"néant opérateur de coalescence". Il prend la forme "optional_var ?? replacement_val". Il retourne une variable non-optionnelle avec le même type que les données contenues dans l'optionnel. Si l'option contient zéro, il renvoie la valeur de l'expression après le "??" symbole.

donc vous pouvez utiliser le code comme ceci:

let newFoo = foo ?? "nil" // "??" is the nil coalescing operator
print("foo = \(newFoo)")

vous pouvez également utiliser try / catch ou la manipulation d'erreur de garde, mais généralement l'une des autres techniques ci-dessus est plus propre.

EDIT:

un autre gotcha, un peu plus subtil avec des optionnels, est "implicitement non enveloppé optionnels. Lorsque nous déclarons foo, nous pourrions dire:

var foo: String!

dans ce cas foo est toujours optionnel, mais vous n'avez pas à le déballer pour le référencer. Cela signifie que chaque fois que vous essayez de faire référence à toto, vous planter si c'est nul.

Alors ce code:

var foo: String!


let upperFoo = foo.capitalizedString

s'écrasera sur une référence à la propriété capitalizedString de foo, même si nous ne déballons pas foo. l'empreinte semble fine, mais elle ne l'est pas.

ainsi, vous voulez être vraiment prudent avec les options implicitement déballées. (et peut-être même les éviter complètement jusqu'à ce que vous avez une solide compréhension des optionnels.)

ligne de fond: lorsque vous apprenez Swift pour la première fois, prétendre le "!"le caractère n'est pas partie de la langue. Il est probable que vous aurez des problèmes.

35
répondu Duncan C 2017-11-11 11:40:19

tout d'Abord, vous devez savoir ce qu'est une valeur Facultative. Vous pouvez faire un pas vers le Launage de programmation Swift

pour plus de détails.

Deuxièmement, vous devez savoir que la valeur optionnelle a deux statuts. L'une est la valeur totale, et l'autre est la valeur nulle. Donc, avant d'implémenter une valeur optionnelle, vous devriez vérifier dans quel état elle est.

Vous pouvez utiliser if let ... ou guard let ... else et ainsi de suite.

Une autre façon, si vous ne voulez pas vérifier son état avant votre implémentation, vous pouvez aussi utiliser var buildingName = buildingName ?? "buildingName" à la place.

9
répondu QiunCheng 2016-07-30 07:18:28

puisque les réponses ci-dessus explique clairement comment jouer en toute sécurité avec des options. Je vais essayer d'expliquer quelles Options sont vraiment rapide.

une autre façon de déclarer une variable optionnelle est

var i : Optional<Int>

Et en Option type est rien mais une énumération avec les deux cas, j'.e

 enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none 
    case some(Wrapped)
    .
    .
    .
}

donc attribuer un zéro à notre variable "i". Nous pouvons le faire var i = Optional<Int>.none ou pour affecter une valeur, nous passeront une certaine valeur var i = Optional<Int>.some(28)

selon swift, "Zéro" est l'absence de valeur. Et pour créer une instance initialisée avec nil nous devons nous conformer à un protocole appelé ExpressibleByNilLiteral et grand si vous l'avez deviné, seulement Optionals se conformer à ExpressibleByNilLiteral et se conformer à d'autres types est découragé.

ExpressibleByNilLiteral a une seule méthode appelée init(nilLiteral:) qui initialise un instacé avec zéro. Vous souvent coutume d'appeler cette méthode et selon la documentation swift, il est déconseillé d'appeler cet initialiseur directement car le compilateur l'appelle chaque fois que vous initialisez un type optionnel avec nil littéral.

même moi doit envelopper (sans jeu de mots) ma tête autour des optionnels: D Heureux Swfting Tous .

8
répondu Tharzeez 2017-11-17 16:15:19

j'ai eu cette erreur Une fois quand j'ai essayé de définir mes valeurs de sortie de la méthode prepare for segue comme suit:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // This line pops up the error
            destination.nameLabel.text = item.name
        }
    }
}

puis j'ai découvert que je ne peux pas régler les valeurs des sorties du contrôleur de destination parce que le contrôleur n'a pas encore été chargé ou initialisé.

donc je l'ai résolu de cette façon:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // Created this method in the destination Controller to update its outlets after it's being initialized and loaded
            destination.updateView(itemData:  item)
        }
    }
}

Contrôleur De Destination:

// This variable to hold the data received to update the Label text after the VIEW DID LOAD
var name = ""

// Outlets
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    nameLabel.text = name
}

func updateView(itemDate: ObjectModel) {
    name = itemDate.name
}

j'espère que cette réponse aide n'importe qui là-bas avec le même problème que j'ai trouvé la réponse marquée est une grande ressource pour la compréhension des optionnels et la façon dont ils fonctionnent, mais n'a pas abordé la question elle-même directement.

4
répondu Wissa 2018-04-13 14:06:00

fondamentalement, vous avez essayé d'utiliser une valeur nulle dans les endroits où Swift n'autorise que les valeurs non nulles, en" dupant " le compilateur pour qu'il pense qu'il y a une valeur nulle, permettant ainsi à votre application de compiler.

Il y a plusieurs scénarios qui conduisent à ce genre d'erreur fatale:

  1. un wraps forcé:

    let user = someVariable!
    

    si someVariable est nul, alors vous aurez un accident. En faisant une force unwrap vous avez déplacé le nil vérifier la responsabilité du compilateur pour vous, essentiellement en faisant un déroulage forcé que vous garantissez au compilateur que vous n'aurez jamais des valeurs nul là-bas. Et devine ce qui arrivera si ça arrive?

    Solution

    ? L'utilisation de fixation en option (aka si-let), ne la variable de traitement, là:

    if user = someVariable {
        // do your stuff
    }
    
  2. moulages forcés:

    let myRectangle = someShape as! Rectangle
    

    ici par moulage de force vous dites le compilateur à no plus d'inquiétude, car vous aurez toujours une instance Rectangle là. Et tant que titulaire, vous n'avez pas à vous inquiéter. Les problèmes commencent lorsque vous ou vos collègues du projet commencez à faire circuler des valeurs non rectangulaires.

    Solution

    ? L'utilisation de fixation en option (aka si-let), ne la variable de traitement, là:

    if let myRectangle = someShape as? Rectangle {
        // yay, I have a rectangle
    }
    
  3. implicitement optionnelles non emballées. Supposons que vous avez la définition de classe suivante:

    class User {
        var name: String!
    
        init() {
            name = "none yet"
        }
    
        func nicerName() {
            return "Mr/Ms " + name
        }
    }
    

    maintenant, si personne ne rate la propriété name en la mettant à nil , alors cela fonctionne comme prévu, cependant si User est initialisé à partir d'un JSON qui manque de la touche name , alors vous obtenez l'erreur fatale en essayant d'utiliser la propriété.

    Solution

    ? Ne les utilisez pas :) sauf si vous êtes sûr à 102% que le bien aura toujours une valeur non nulle au moment où il doit être utilisé. Cependant, dans la plupart des cas la convertir en optionnel ou non-optionnel fonctionnera. En le rendant non-optionnel, le compilateur vous aidera aussi en indiquant les chemins de code que vous avez manqués en donnant une valeur à cette propriété

  4. sans lien les points de vente. C'est un cas particulier du scénario 3. En gros, tu as une classe chargée de XIB que tu veux utiliser.

    class SignInViewController: UIViewController {
    
        @IBOutlet var emailTextField: UITextField!
    }
    

    maintenant si vous avez manqué la connexion de la prise à partir de l'éditeur XIB, puis l'application sera crash dès que vous voulez utiliser la prise. La Solution? Assurez-vous que toutes les prises sont reliés. Ou utilisez l'opérateur ? sur eux: emailTextField?.text = "my@email.com" . Ou déclarer la sortie optionnel, mais dans ce cas, le compilateur va vous forcer à déballer tout le code.

  5. valeurs provenant de L'Objectif-C, et qui n'ont pas d'annotations de nullité. Supposons que nous ayons la classe D'objectif C suivante:

    @interface User: NSObject
    @property NSString *name;
    @end
    

    maintenant si aucune annotation de nullité n'est spécifiée (soit explicitement ou via NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END ), alors la propriété name sera importée dans Swift comme String! (une option IUO - implicitement déballée). Dès qu'un code swift souhaitez utiliser la valeur, il va se planter, en nul cas.

    Solution

    ? Ajoutez des annotations de nullité à votre code objectif-C. Attention cependant, le compilateur objectif-C est un peu permissif quand il s'agit de nullabilité, vous pourriez vous retrouver avec des valeurs nulles, même si vous les avez explicitement marquées comme nonnull .

0
répondu Cristik 2018-10-12 22:38:02

erreur fatale: de façon inattendue trouvé nulle, tandis que d'ôter une valeur Facultative

il est dit que vous utilisez la variable dont la valeur n'est pas initialisée ou fixée à zéro.

e. g

var tempVar: String?
print(tempVar!)

tempVar n'est pas initialisé donc l'application se bloque dans ce cas donc vous devez utiliser

print(tempVar ?? "") 

consultez Facultatif Chaîne pour plus de détails information

-3
répondu CrazyPro007 2018-05-19 14:24:50