更新:这是关于在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?'的值没有打开;你的意思是用'!'还是'?'?
我必须要么强制转换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
}
}
结果是
找不到类型'NSMutableAttributedString'的初始值设定项,它接受类型'的参数列表'(数据:NSData ??,选项:[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
的结果,如何在没有!
的情况下安全地 -in all,获取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
答案 0 :(得分: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
接受一个可选项,然后将其解包并将其放入返回可选项的函数中。如果原始可选项或从函数返回的值计算为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
两次。
答案 1 :(得分: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)
}
}