1

更新:这是关于在 Xcode 中使用基于文档的应用程序模板创建的 Mac 应用程序,我正在覆盖

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

我正在尝试从 NSFileWrapper 读取文件,似乎我无法摆脱其中至少有一个文件!

首先,我试过

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

所以我得到这个错误

可选类型“NSData?”的值 未拆封;你的意思是用'!' 或者 '?'?

而且我必须要么强制转换,要么必须在 NSMutableAttributedString 的初始化程序 ( )regularFileContents as NSData!中强制解包它。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
    }
}

这导致

找不到接受类型为“(数据:NSData??,选项:[String:String],documentAttributes:nil,错误:nil)”的参数列表的“NSMutableAttributedString”类型的初始化程序

所以我必须将初始化程序更改为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,以及我怎样才能安全地,不用!-ing 一路获取 NSData 并将其传递给 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
            }
        }
    }
}

编译器给出了这个错误:

条件绑定中的绑定值必须是可选类型

关于fileWrapper.fileWrappers

变量是方法的fileWrapper参数,即

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

2 回答 2

1

您的线路:

files["textFile.rtf"]?.regularFileContents

返回一个双重包装的可选。一个用于字典查找,一个用于.regularFileContents. 当您执行 时if let,您将其打开一次:这就是您的错误是:

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

但是,在您的第二个版本中,您只需检查是否rtfData为 nil - 您不会打开它:

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接受一个可选项,并将其解包以将其放入一个返回可选项的函数中。如果原始可选值或函数返回的值的计算结果为 nil,则整个事物的计算结果为 nil。但是它返回的值只是单独包装的。

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两次。

于 2015-05-31T17:22:42.317 回答
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字典 (a [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)
    }
}
于 2015-05-31T17:37:12.060 回答