2015-05-31 1 views
1

Update: это что касается приложения Mac, созданный с помощью шаблона приложения на основе документов в Xcode, и я переопределениеНе похоже, чтобы избежать сила разворачивает в Swift

override func readFromFileWrapper(fileWrapper: NSFileWrapper, ofType typeName: String, error outError: NSErrorPointer) -> Bool 

I Я пытаюсь прочитать файл из NSFileWrapper, и кажется, что я не могу уйти от наличия хотя бы одного !.

Во-первых, я попытался

if let rtfData = files["textFile.rtf"]?.regularFileContents, 
     newString = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) { 
       text = newString 
       return true 
     } 

Так что я получаю эту ошибку

Value of optional type 'NSData?' not unwrapped; did you mean to use '!' or '?'?

И я должен либо бросить regularFileContents as NSData! или я должен заставить разворачивать его в инициализаторе в NSMutableAttributedString в (data: rtfData!).


Затем я попытался

let rtfData = files["textFile.rtf"]?.regularFileContents 

if (rtfData != nil) { 
    if let newString = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) { 
     text = newString 
     return true 
    } 
} 

Какие результаты в

Cannot find an initializer for type 'NSMutableAttributedString' that accepts an argument list of type '(data: NSData??, options: [String : String], documentAttributes: nil, error: nil)'"

Так я должен изменить инициализатору сказать data: rtfData!!, что я даже не уверен, что это означает .

Или, я могу наложить regularFileContents as NSData?, а затем я могу использовать только один ! в инициализаторе.

Обновление: Вот еще одна вещь, которую я пробовал с момента публикации. Я понял, в NSData?? двойной ? может быть из-за меня необязательно разворачивания NSFileWrapper (files["textFile.rtf"]?), поэтому я попытался это:

if let rtfWrapper = files["textFile.rtf"], 
    rtfData = rtfWrapper.regularFileContents, 
    newString = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) { 
     text = newString 
     return true 
    } 

Компилятор еще хочет меня, чтобы заставить разворачивать NSData.


Я довольно тщательно смущен.

Что NSData??, почему это «вдвойне» по желанию, почему это результат .regularFileContents, и как я могу безопасно без ! -ную весь путь, получить NSData и передать его intializer в NSMutableAttributedString в ?


Очередное обновление

Я подумал, может быть постоянная files может быть источником другого дополнительного упаковки:

let files = fileWrapper.fileWrappers 

Но компилятор не позволит мне if let его.Если я стараюсь, например,

if let files = fileWrapper.fileWrappers { 
    if let rtfFile = files["textFile.rtf"] { 
     if let rtfData = rtfFile.regularFileContents { 
      if let newString = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) { 
       text = newString 
       return true 
      } 
     } 
    } 
} 

Компилятор дает эту ошибку:

Bound value in a conditional binding must be of Optional type

О fileWrapper.fileWrappers

Переменная fileWrapper является параметром метода, который

override func readFromFileWrapper(fileWrapper: NSFileWrapper, ofType typeName: String, error outError: NSErrorPointer) -> Bool 

ответ

1

Вы можете использовать опциональное связывание для файла, а затем перейти оттуда:

if let file = files["textFile.rtf"], 
    contents = file.regularFileContents, 
    newString = NSMutableAttributedString(data: contents, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) { 
     text = newString 
     return true 
} 

Если вы используете fileWrappers словаря ([NSObject : AnyObject]), вы должны сделать некоторую дополнительную отливку. В этом примере используется файл, который у меня есть в этой файловой оболочке, но, надеюсь, он иллюстрирует идею:

var text: NSString! 

func someMethod(fileWrapper: NSFileWrapper) { 
    let files = fileWrapper.fileWrappers 

    if let file = files["test.json"] as? NSFileWrapper, 
     contents = file.regularFileContents, 
     newString = NSString(data: contents, encoding: NSUTF8StringEncoding) { 
      text = newString 
      println(text) 
    } 
} 
+0

Попытался, что это тоже не сработало. В вашем фрагменте компилятор будет жаловаться на 'data: contents' и будет принимать только данные: содержимое!' – magiclantern

+0

@kamera Нет, он не стал бы жаловаться на то, что' contents' является необязательным, потому что это не так (мы делаем необязательное связывание здесь, поэтому я разбил его на два назначения, поэтому каждая необязательная привязка может иметь место последовательно). Я просто тестировал его, и он работал нормально. – Rob

+0

Не может быть, что моя константа 'files' является проблемой? Где вы получаете его в своем фрагменте? Проверьте обновление моего вопроса. – magiclantern

1

Ваша строка:

files["textFile.rtf"]?.regularFileContents 

Возвращает двукратно завернутый дополнительный вариант. Один для словаря искать, один для .regularFileContents. Когда вы сделали if let, вы развернули его однажды: вот почему ваша ошибка:

// Value of optional type 'NSData?' not unwrapped; did you mean to use '!' or '?'? 

Но затем, на вторую версию, вы просто проверки если rtfData равен нуль - вы не разворачивать его:

if (rtfData != nil) 

Который дает вам двойное обертывание.

Самый простой способ обойти это заключается в использовании flatMap:

if let rtfData = files["textFile.rtf"].flatMap({$0.regularFileContents}) { 
    text = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) 
    return true 
} 

flatMap принимает необязательный, и разворачивает его, чтобы положить его в функцию, которая возвращает необязательная. Если либо исходный вариант, либо значение, возвращаемое функцией, оценивается равным нулю, все это значение равно нулю. Но значение, которое он возвращает, только однократно завернуто.

Что flatMap делает в основном:

if let lookup = files["textFile.rtf"] { 
    if let rtfData = lookup.regularFileContents { 
    let newString = NSMutableAttributedString(data: rtfData, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) 
    text = newString 
    return true 
    } 
} 

Этот код будет работать. Оба метода безопасно разворачивают rtfData дважды.

+0

Хмм. Stil get ** Значение необязательного типа «NSData?» не разворачивается; вы хотели использовать '!' или '?'? ** в 'data: rtfData' части инициализатора – magiclantern

+0

Изменено - newString не должно было находиться внутри оператора if let. – oisdk

+0

То же самое; все еще получая ту же ошибку компилятора. Может ли это быть константой 'files'? Посмотрите последнее обновление на мой вопрос – magiclantern