当前位置: 首页 > 知识库问答 >
问题:

Swift 2:调用可以抛出,但未标记为“try”,并且未处理错误

鲁泰宁
2023-03-14

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

以下是错误:

调用可以抛出,但未标有“try”,并且不处理错误

法典:

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 _ {
        }

    }

共有2个答案

薄涵衍
2023-03-14

当调用在Swift中使用throws声明的函数时,您必须使用trytry!注释函数调用站点。例如,给定一个投掷函数:

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

这个函数可以像这样调用:

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

在这里,我们用<code>try</code>对调用进行注释,这会向读者发出这样的信息:此函数可能会引发异常,并且可能不会执行下面的任何代码行。我们还必须用<code>throws</code>注释此函数,因为此函数可能会引发异常(即,当<code>willOnlyThrowIfTrue()</code>抛出时,则<code>foo</code>将自动向上重新抛出异常。

如果您想调用一个声明为可能抛出的函数,但您知道该函数在您的情况下不会抛出,因为您给了它正确的输入,那么您可以使用<code>try

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

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

< code >试试看!是在运行时强制执行的:如果您使用< code>try!并且该函数最终抛出,那么您的程序的执行将因运行时错误而终止。

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

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.
}

如果出于某种原因,您需要清理需要运行但不在< code>deinit()函数中的代码,您可以使用< code>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()延迟,在途中进行清理。这是因为大多数代码不知道如何处理错误;它知道发生了什么错误,但它没有足够的信息来了解一些更高级别的代码试图做什么,以便知道如何处理错误。它不知道向用户呈现对话框是否合适,或者是否应该重试,或者是否需要其他方式。

然而,更高级别的代码应该确切地知道在出现任何错误时该做什么。所以异常允许特定的错误从最初发生的地方冒泡到可以处理的地方。

处理异常是通过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语法和错误处理模型的详细信息,请参阅《Swift编程语言》(Swift 2预发行版)。

关宏毅
2023-03-14

您必须捕获错误,就像您已经为<code>save()</code>调用所做的一样。由于您在这里处理多个错误,您可以<code>在单个do-catch块中依次尝试</code>多个调用,如下所示:

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,然后尝试调用该方法。例如:

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()
}
 类似资料:
  • 问题内容: 我正在尝试使用swiftyjson,但出现错误: 可以抛出呼叫,但是标记为“ try”,并且未处理错误。 我已验证我的源JSON很好。我一直在搜索,找不到解决此问题的方法 谢谢您的帮助! 问题答案: 您应该将其包装成一个块。在您的情况下:

  • 问题内容: 在安装Xcode 7 Beta并将Swift代码转换为Swift 2之后,我遇到了一些我无法弄清楚的代码问题。我知道Swift 2是新手,所以我搜索并找出了答案,因为没有任何相关内容,我应该写一个问题。 这是错误: 可以抛出呼叫,但未将其标记为“ try”,并且未处理错误 码: 快照: 问题答案: 您必须像处理呼叫一样捕获错误,并且由于您要在此处处理多个错误,因此可以在一个do-cat

  • 问题内容: 我使用以下命令创建了expressjs应用程序: 使用以下命令运行应用程序时,出现以下错误: 如何解决? 问题答案: 您曾经使用与8080相同的端口运行另一台服务器。 也许您在其他Shell中运行过,请关闭它,然后再次运行。 您可以检查端口号。 可用或不使用 另外,您可以使用lsof:

  • 我使用以下命令创建了expressjs应用程序: 当我使用:,我有以下错误: 如何修复它?

  • 下面是我的代码片段: 现在java用'unhandled exception type SQLException)标记指示语句(以及后面的所有语句)。gfsql.dosql抛出此异常并定义为: public ResultSet doSQL(String sqlCommand)抛出SQLException{ 有趣的是--如果我像这样重复“catch”块: 未标记“未处理”错误。(但是,重复的catc

  • 问题内容: 我正在尝试使用try-catch捕获SQL查询(而不是存储过程)中的错误。 由于某种原因,这无法处理我的错误,但我仍然得到: 消息213,级别16,状态1,第29行列名或提供的值数与表定义不匹配。 有什么帮助吗? 问题答案: 您有一个编译时错误,无法在try-catch中捕获。 BooksOnline: 编译和语句级重新编译错误 如果错误在与TRY-ATCH构造相同的执行级别中发生,则