2016-12-21 5 views
0

J'essaye de charger un fichier de mon ensemble d'applications dans Swift 3, et je suis tombé sur une situation étrange avec l'inférence de type Swift. Si j'utilise le code suivant, j'obtiens une erreur sur la troisième ligne qui indique Value of optional type "String?" not unwrapped.Swift Impossible Type Inférence

let url = NSURL(fileURLWithPath:Bundle.main.bundlePath) 
let url2 = url.appendingPathComponent("foo.txt") 
let path:String = url2?.path 

Pour corriger l'erreur que je déballe la valeur sur la troisième ligne en changeant à:

let path:String = url2?.path! 

Je reçois maintenant l'erreur Cannot force unwrap value of a non-optional type 'String'. Il semble que Swift ne puisse pas déterminer si la propriété path est String ou String?. La fonctionnalité de saisie semi-automatique dans Xcode indique qu'il s'agit d'un String, mais les documents indiquent qu'il s'agit d'un String?.

La correction suggérée par Xcode pour la première erreur était de remplacer url2?.path par (url2?.path)!, qui a finalement fini par fonctionner, mais je ne sais pas pourquoi cela fonctionne et les autres ne le font pas.

let path:String = (url2?.path)! 

Que se passe-t-il? Est-ce un bug d'inférence de type à Swift, ou suis-je manque quelque chose de super évident

+0

'laisser fooBundleURL = Bundle.main.bundleURL.appendingPathComponent ("foo.txt")' ' –

+0

let fooPath = fooBundleURL.path' –

+0

@LeoDabus Je suis d'accord que fonctionne, mais ma question est pourquoi le code fourni ne fonctionne pas. – Aderis

Répondre

1

Swift, en option Enchaînement comme:

let path:String = url2?.path! 

... est interprété comme:

let path:String = url2 != nil ? url2!.path! 
           : nil 

Comme vous voyez le type de path est non facultative String, de sorte que l'expression provoque une erreur .

(type de url2 est URL?, de sorte que le type de propriété path est String, pas String?.)


Ce n'est pas une réponse directe à votre question, mais je récrire votre code as:

let url = Bundle.main.bundleURL 
let url2 = url.appendingPathComponent("foo.txt") 
let path:String = url2.path 

Plus court, et ne vous inquiétez pas des options.

0

Vous avez oublié de déballer url2

appendingPathComponent retourne une valeur facultative et que vous essayez d'y accéder sans le déballer.

Ainsi,

let url2 = url.appendingPathComponent("foo.txt")! 

ou

guard let url2 = url.appendingPathComponent("foo.txt") else { } 

devrait fixer

EDIT

let path:String? = url2?.path 

travaille également

+0

Le '?' Après le 'url2' devrait en tenir compte. Si vous mettez un '?' Après un optionnel, alors il arrête l'exécution si l'optionnel est nul, mais continue si l'optionnel a une valeur. – Aderis

+0

Il utilise NSURL quand il devrait utiliser l'URL aussi URL méthodes appendingPathComponent URL de retour non facultatif 'func appendingPathComponent (_ pathComponent: String) -> URL' –

+1

@LeoDabus D'accord, je devrais probablement être, et merci pour le conseil. Je reviens à la vitesse après un certain temps, et je ne sais pas ce qui a été renommé sans le préfixe NS. – Aderis

0

Vous pouvez aussi le faire:

let url = Bundle.main.url(forResource: "foo", withExtension: "txt")! 
let path:String = url.path 
+0

'Bundle' a maintenant une méthode' url (forResource: withExtension:) '. Vous pouvez écrire quelque chose comme 'let url = Bundle.main.url (forResource:" foo ", avecExtension:" txt ")!' 'Let chemin: String = url.path'. – OOPer

+0

ok, merci pour cette suggestion je vais l'appliquer, et modifier ma réponse. –