我可以从Swift中的类init()抛出从文件加载的常量字符串吗?

Dri*_*ler 20 swift

如果在将类文件加载到类中的字符串时出现问题,我希望Swift中的类init()抛出错误.加载文件后,字符串不会被更改,所以我更喜欢使用let.这有效:

class FileClass {    
    var text: NSString = ""   
    init() throws {   
        do {
            text = try NSString( contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding ) }
        catch let error as NSError {
            text = ""
            throw error
        }      
    }
}
Run Code Online (Sandbox Code Playgroud)

但当我更换

var text: NSString = ""
Run Code Online (Sandbox Code Playgroud)

let text: NSString
Run Code Online (Sandbox Code Playgroud)

我得到一个类实例所有存储属性必须在从初始化器错误抛出之前初始化.

我尝试了各种方法,例如使文本可选

let text: NSString?
Run Code Online (Sandbox Code Playgroud)

但没有找到任何工作.它可以从文件加载文本,不可变,并为init()抛出错误?我可以吃蛋糕吗?

提前谢谢了!

Luc*_*tti 19

[更新] Swift版本> = 2.2

从Swift 2.2开始,您可以打破类初始化程序的执行,而无需填充所有存储的属性

class FileStruct {
    let text: String

    init() throws {
        do {
            text = try String(contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding ) }
        catch let error as NSError {
            throw error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift版本<= 2.1

目前在Swift中,class您无法在初始化每个存储的属性之前中断初始化程序的执行.

在另一方面,你没有这个约束与structs如此

struct FileStruct {
    var text: String

    init() throws {
        do {
            text = try String(contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding ) }
        catch let error as NSError {
            throw error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以避免使用do/catch块

struct FileStruct {
    var text: String

    init() throws {
        text = try String(contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding)
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我换了NSString,String因为我们使用的是Swift,而不是Objective-C ;-)


Cri*_*tik 12

您可以使用可用的初始化程序,因为它更适合这种情况.

class FileClass {
    let text: String
    init?() {
        guard let fileContents = try? NSString( contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding ) else {
            text = ""
            return nil
        }
        text = fileContents as String
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果要打印错误:

class FileClass {
    let text: String
    init?() {
        do {
            text = try String( contentsOfFile: "/Users/me/file.txt", encoding: NSUTF8StringEncoding )
        } catch let error as NSError {
            print("Error while reading: \(error)")
            text = ""
            return nil
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用比使用throw初始化程序更容易,因为您可以使用if-letguard-let:

if let file = FileClass() {
}
Run Code Online (Sandbox Code Playgroud)

, 要么

guard let file = FileClass() else {
    return
}
Run Code Online (Sandbox Code Playgroud)

let file: FileClass
do {
    file = FileClass()
} catch {
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,@Cristik!它更干净,但我不会丢失有关错误的信息吗?我发现调出带有错误描述的模式对话框有助于调试。 (2认同)