首页 文章

Swift 2:调用可以抛出,但它没有标记'try'并且没有处理错误

提问于
浏览
144

在我安装Xcode 7 beta并将我的swift代码转换为Swift 2之后,我遇到了一些我无法弄清楚的代码问题 . 我知道Swift 2是新的,所以我搜索并弄清楚,因为没有任何关于它,我应该写一个问题 .

Here is the error:

调用可以抛出,但它没有标记为'try',并且没有处理错误

Code:

func deleteAccountDetail(){
        let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
        let request = NSFetchRequest()
        request.entity = entityDescription

        //The Line Below is where i expect the error
        let fetchedEntities = self.Context!.executeFetchRequest(request) as! [AccountDetail]

        for entity in fetchedEntities {
        self.Context!.deleteObject(entity)
        }

        do {
            try self.Context!.save()
        } catch _ {
        }

    }

Snapshot:
enter image description here

2 回答

  • 38

    你必须像你已经为你的 save() 调用那样捕获错误,并且由于你在这里处理多个错误,你可以在一个do-catch块中顺序地多次调用 try ,如下所示:

    func deleteAccountDetail() {
        let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
        let request = NSFetchRequest()
        request.entity = entityDescription
    
        do {
            let fetchedEntities = try self.Context!.executeFetchRequest(request) as! [AccountDetail]
    
            for entity in fetchedEntities {
                self.Context!.deleteObject(entity)
            }
    
            try self.Context!.save()
        } catch {
            print(error)
        }
    }
    

    或者正如@ bames53在下面的评论中指出的那样,通常更好的做法是不要捕获抛出它的错误 . 您可以将方法标记为 throws ,然后 try 来调用该方法 . 例如:

    func deleteAccountDetail() throws {
        let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
        let request = NSFetchRequest()
    
        request.entity = entityDescription
    
        let fetchedEntities = try Context.executeFetchRequest(request) as! [AccountDetail]
    
        for entity in fetchedEntities {
            self.Context!.deleteObject(entity)
        }
    
        try self.Context!.save()
    }
    
  • 152

    调用在Swift中使用 throws 声明的函数时,必须使用 trytry! 注释函数调用站点 . 例如,给定投掷功能:

    func willOnlyThrowIfTrue(value: Bool) throws {
      if value { throw someError }
    }
    

    这个函数可以像:

    func foo(value: Bool) throws {
      try willOnlyThrowIfTrue(value)
    }
    

    这里我们用 try 注释调用,它向读者调用此函数可能抛出异常,并且可能不会执行任何后续代码行 . 我们还必须使用 throws 注释此函数,因为此函数可能抛出异常(即,当 willOnlyThrowIfTrue() 抛出时, foo 将自动向上重新抛出异常 .

    如果你想调用一个被声明为可能抛出的函数,但你知道它不会抛出你的情况,因为你给它正确的输入,你可以使用 try! .

    func bar() {
      try! willOnlyThrowIfTrue(false)
    }
    

    这样,当您保证代码不会抛出时,您不必添加额外的样板代码来禁用异常传播 .

    try! 在运行时强制执行:如果使用 try! 且函数最终抛出,则程序的执行将因运行时错误而终止 .

    大多数异常处理代码应如上所示:要么只是在发生异常时向上传播异常,要么设置条件,否则排除可能的异常 . 代码中的其他资源的清理应该通过对象销毁(即 deinit() )或有时通过 defer ed代码进行 .

    func baz(value: Bool) throws {
    
      var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
      var data = NSData(contentsOfFile:filePath)
    
      try willOnlyThrowIfTrue(value)
    
      // data and filePath automatically cleaned up, even when an exception occurs.
    }
    

    如果由于某种原因你有清理代码需要运行但不在 deinit() 函数中,你可以使用 defer .

    func qux(value: Bool) throws {
      defer {
        print("this code runs when the function exits, even when it exits by an exception")
      }
    
      try willOnlyThrowIfTrue(value)
    }
    

    大多数处理异常的代码只是让它们向上传播给调用者,通过 deinit()defer 进行清理 . 这是因为大多数代码都没有足够的信息来了解一些更高级别的代码正在尝试做什么,以便知道如何处理错误 . 它不知道向用户呈现对话是否合适,或者是否应该重试,或者是否适合其他情况 .

    但是,更高级别的代码应该确切知道在发生任何错误时该怎么做 . 因此,异常允许特定错误从最初发生的位置冒出来到可以处理的位置 .

    处理异常是通过 catch 语句完成的 .

    func quux(value: Bool) {
      do {
        try willOnlyThrowIfTrue(value)
      } catch {
        // handle error
      }
    }
    

    您可以拥有多个catch语句,每个语句都会捕获不同类型的异常 .

    do {
        try someFunctionThatThowsDifferentExceptions()
      } catch MyErrorType.errorA {
        // handle errorA
      } catch MyErrorType.errorB {
        // handle errorB
      } catch {
        // handle other errors
      }
    

    有关异常的最佳实践的更多详细信息,请参阅http://exceptionsafecode.com/ . 它专门针对C,但在检查了Swift异常模型后,我相信基础知识也适用于Swift .

    有关Swift语法和错误处理模型的详细信息,请参阅书籍The Swift Programming Language (Swift 2 Prerelease) .

相关问题