我想将应用程序包中的PDF加载到CGPDFDocument中。
是否有某种方法可以调用函数,如果任何不接受选项的参数的值为nil,则不会调用该函数并返回nil。
例如:
let pdfPath : String? = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf")
//I want to do this
let data : NSData? = NSData(contentsOfFile:pdfPath)
//I have to do this
let data : NSData? = pdfPath != nil ? NSData(contentsOfFile:pdfPath) : nil
let doc : CGPDFDocumentRef? = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data));
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1);
因为NSData.init?(contentsOfFile path:String),没有将path
定义为可选,即使它有一个可选的返回值,我必须先检查一下,如果参数为nil,则返回零。 data
赋值(而不是?:
运算符)是否有一些语法糖?
答案 0 :(得分:3)
使用以逗号分隔的多个可选绑定
func loadPDF() -> CGPDFDocumentRef?
{
if let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf"),
data = NSData(contentsOfFile:pdfPath),
doc = GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data)) {
return doc
} else {
return nil
}
}
或使用guard
声明
func loadPDF() -> CGPDFDocumentRef?
{
guard let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf") else { return nil }
guard let data = NSData(contentsOfFile:pdfPath) else { return nil }
return GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data))
}
所有显式类型注释都是语法糖,不需要。
修改强>
在您的特定情况下,您只需要检查文件是否存在,甚至这个 - 文件丢失 - 在iOS中是不太可能的。另一个好处是能够返回非可选的PDF文档。
func loadPDF() -> CGPDFDocumentRef
{
guard let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf") else {
fatalError("file nac_06.pdf does not exist")
}
let data = NSData(contentsOfFile:pdfPath)
return CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data!))!
}
答案 1 :(得分:0)
如果pdfPath
或data
为零,我假设您也不想继续执行该功能。在这种情况下,guard
将是最佳选择:
guard let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf") else {
// eventually also report some error
return
}
guard let data = NSData(contentsOfFile:pdfPath) else {
// eventually also report some error
return
}
// at this point you have a valid data object
你也可以将它组合成一个guard
语句,以减少代码重复,但是在这种情况下你会松开,知道两者中哪一个失败的可能性。
guard let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf"),
data = NSData(contentsOfFile:pdfPath) else {
// eventually also report some error
return
}
答案 2 :(得分:0)
有两种方法可以实现这一目标。
NSData
课程并创建您自己的convenience init?
方法guard
声明我更喜欢第二种方法:
func getPDF(path : String?) -> CGPDFDocumentRef?
{
guard let filePath = path,
data = NSData(contentsOfFile: filePath),
pdf = GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data)) else
{
return nil
}
return pdf
}
调用方法如:
let doc = getPDF(path : NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf"))
答案 3 :(得分:0)
你可以通过定义一个自定义运算符来处理这种情况。例如:
infix operator ^> {associativity left precedence 150}
func ^><T, U>(arg: T?, f: T->U?) -> U?{
if let arg = arg {
return f(arg)
} else {
return nil
}
}
运算符采用可选的左侧参数和采用非可选的函数,并返回另一个可选作为右侧参数。
然后您可以像这样编写代码:
let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf")
//the line below needs a NSData extension
let data = pdfPath ^> NSData.fileContents
let doc = data ^> CGDataProviderCreateWithCFData ^> CGPDFDocumentCreateWithProvider
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1)
请注意,要使其正常工作,您需要为NSData添加扩展名,因为您无法将init(contentsOfFile:)
初始值设定项映射到可传递给^>
的泛型函数。
extension NSData {
class func fileContents(path: String) -> NSData? {
return NSData(contentsOfFile: path)
}
}
^>
运算符的使用会恢复您编写函数名的顺序,如果您希望函数名与原始代码的顺序相同,则可以添加一个反向运算符来执行相同的操作:
infix operator ^< {associativity right precedence 150}
func ^< <T, U>(f: T->U?, arg: T?) -> U?{
if let arg = arg {
return f(arg)
} else {
return nil
}
}
let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf")
let data = NSData.fileContents ^< pdfPath
let doc = CGPDFDocumentCreateWithProvider ^< CGDataProviderCreateWithCFData ^< data
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1)