我在使用defer语句的注销按钮上有代码。

我想知道何时在操作方法范围内更改defer语句代码的位置。

  • 我在方法末尾添加了defer语句,它向我显示警告。

  • 范围结束之前的“defer”语句始终立即执行;
    替换为“do”语句以使此警告静音

    代码:
    override func sendButtonTapped(sender: Any) {
    
        self.deleteCoreData()
        self.clearUserDefaults()
    
        // Clear view context
        AppDelegate.shared.persistentContainer.viewContext.reset()
    
        ....
        ....
    
        // Call after all code execution completed in this block's Scope
        defer {
            // Set isUserLoggedIn and change root view controller.
            UserDefaults.Account.set(false, forKey: .isUserLoggedIn)
            AppDelegate.shared.setRootViewController()
        }
    }
    
  • 然后,我在方法开始时添加了defer语句,但没有显示任何内容。

  • 代码:
    override func sendButtonTapped(sender: Any) {
    
        // Call after all code execution completed in this block's Scope
        defer {
            // Set isUserLoggedIn and change root view controller.
            UserDefaults.Account.set(false, forKey: .isUserLoggedIn)
            AppDelegate.shared.setRootViewController()
        }
    
        self.deleteCoreData()
        self.clearUserDefaults()
    
        // Clear view context
        AppDelegate.shared.persistentContainer.viewContext.reset()
    
        ....
        ....
    }
    

    谁能解释defer语句到底发生了什么?

    最佳答案

    概括起来,defer语句将在您所在的作用域的末尾执行。(.apple doc:https://docs.swift.org/swift-book/ReferenceManual/Statements.html#grammar_defer-statement)

    从苹果doc

    func f() {
        defer { print("First defer") }
        defer { print("Second defer") }
        print("End of function")
    }
    f()
    // Prints "End of function"
    // Prints "Second defer"
    // Prints "First defer"
    
    defer语句允许您定义一个操作,该操作将在其余要完成的操作之后(即作用域的末尾)执行

    考虑到将defer语句放在作用域的末尾,该警告也非常明确,它没有任何作用:
    func f() {
        print("TIC")
        defer { print("TAC") } // will be print at the end of the function
    }
    f()
    // Prints "TIC"
    // Prints "TAC""
    

    这与:
    func f() {
        print("TIC")
        print("TAC") // no defer, same result
    }
    f()
    // Prints "TIC"
    // Prints "TAC""
    

    更进一步

    那么,为什么警告会向您建议一个do块?
    实际上,前两个示例并非100%相同,当您使用defer语句时,它会创建自己的作用域
    func f() {
        // here you are in the scope of the `f()` function
        print("TIC")
        defer {
            // here you are the scope of the `defer` statement
            print("First defer")
        }
    }
    

    手动创建范围的最接近方法是do语句
    func f() {
        // here you are in the scope of the `f()` function
        print("TIC")
        do {
            // here you are the scope of the `do` statement
            print("First defer")
        }
    }
    

    来自苹果文档

    do语句用于引入新范围,并且可以选择包含一个或多个catch子句,这些子句包含与定义的错误条件匹配的模式。在do语句范围内声明的变量和常量只能在该范围内访问。

    如果您想了解有关范围的更多信息,这里有一些讲座:https://andybargh.com/lifetime-scope-and-namespaces-in-swift/

    本质上,对象范围定义了程序中可以访问该项目的区域。

    关于ios - 延迟声明的不同行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56472039/

    10-14 21:08