2016-12-21 5 views
0

Я пытаюсь загрузить файл из моего пакета приложений в Swift 3, и я наткнулся на странную ситуацию с помощью метода ввода типа Swift. Если я использую следующий код, я получаю сообщение об ошибке в третьей строке, которая говорит Value of optional type "String?" not unwrapped.Swift Impossible Type Inference

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

Чтобы исправить ошибку я развернет значение на третьей линии, изменив его:

let path:String = url2?.path! 

теперь я получаю ошибку Cannot force unwrap value of a non-optional type 'String'. Кажется, что Swift не может определить, является ли свойство пути String или String?. Функция автозаполнения в Xcode говорит, что это String, но документы говорят, что это String?.

Предлагаемое исправление по Xcode для первой ошибки состояло в том, чтобы заменить url2?.path на (url2?.path)!, который, в конечном итоге, закончился, но я понятия не имею, почему это работает, а другие - нет.

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

Что происходит? Является ли это умозаключение ошибка типа в Swift, или я что-то отсутствует супер очевидное

+0

'пусть fooBundleURL = Bundle.main.bundleURL.appendingPathComponent ("foo.txt")' ' –

+0

пусть fooPath = fooBundleURL.path' –

+0

@LeoDabus Я согласен, что работает, но мой вопрос в том, почему предоставленный код не работает. – Aderis

ответ

1

В Swift, опционное сцепление как:

let path:String = url2?.path! 

... интерпретируются как:

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

Как вы видите тип path является неопциональными String, так что выражение вызывает ошибку ,

(тип url2 «s является URL?, поэтому тип недвижимости path является String, не String?.)


Это не является прямым ответом на ваш вопрос, но я бы переписать код as:

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

Короче, и не беспокойтесь о вариантах.

0

Вы забыли разворачивать url2

appendingPathComponent возвращает необязательное значение, и вы пытаетесь получить к нему доступ без разворачивая его.

Так,

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

или

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

должен исправить это

EDIT

let path:String? = url2?.path 

работы также

+0

'' 'после' url2' должен учитывать это. Если вы поместите «?» После опционального, то он прекратит выполнение, если необязательный параметр равен нулю, но продолжит, если параметр имеет значение. – Aderis

+0

Он использует NSURL, когда он должен использовать URL-адрес и URL-адрес appendingPathComponent методы возвращают URL-адрес, не являющийся необязательным 'func appendingPathComponent (_ pathComponent: String) -> URL' –

+1

@LeoDabus Согласен, я, вероятно, должен быть и спасибо за отзыв. Через некоторое время я возвращаюсь к быстрому и не знаю, что было переименовано без префикса NS. – Aderis

0

Вы также можете сделать это:

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

'Bundle' теперь имеет метод' url (forResource: withExtension:) '. Вы можете написать что-то вроде 'let url = Bundle.main.url (forResource:" foo ", withExtension:" txt ")!' 'Let path: String = url.path'. – OOPer

+0

ok, Спасибо за это предложение, я буду применять его и отредактировать свой ответ. –