如何使用回调闭包 Swift 在控制器、检查器和返回之间传递数据

How to pass data between controller, checker and back using callback closures Swift

提问人:Maria Mezhova 提问时间:9/19/2021 更新时间:9/20/2021 访问量:363

问:

我是 Swift 的新手,这是我想问社区的第一个问题。 我有一个带有 textField、自定义按钮和标签的视图控制器,我还有一个单独的检查器来检查输入的 textField 单词是否正确。因此,当我按下按钮时,检查器正在检查和更改标签的颜色(如果 textfield.text 为空,则为绿色/红色/透明。如何使用回调闭包来实现这一点?提前非常感谢您!

这是我的ViewController:

final class FeedViewController: UIViewController {

    private let checkTextField: UITextField = {
        let textField = MyCustomTextField(
            font: UIFont.systemFont(ofSize: 16),
            textColor: .black,
            backgroundColor: .white,
            placeholder: "Enter the word")
        
        return textField
    }()
    
    private lazy var checkButton: UIButton = {
        let button = MyCustomButton(
            title: "Check the word",
            titleColor: .white,
            backgroundColor: .systemGray,
            backgroundImage: nil) {

        }
        button.layer.cornerRadius = 6
        button.clipsToBounds = true
        return button
    }()
    
    private let colorLabel: UILabel = {
        let label = UILabel()
        label.alpha = 0
        label.toAutoLayout()
        return label
    }()
 
    private let checker: CheckTextField
    
    init(checker: CheckTextField) {
        self.checker = checker
        super .init(nibName: nil, bundle: nil)
    }

这是我的检查器:

class CheckTextField {
    
    private let correctWord = "correct word"
    
    func check( word: String) {
        

    }
}

我已经设法通过通知完成了这项任务,但关闭对我来说太复杂了:(

iOS Swift 回调 闭合

评论


答:

0赞 Caleb 9/19/2021 #1

闭包实际上是接收和调用它的方法的一个参数,所以如果你想在它完成检查时调用某个闭包,你需要将其添加为参数:check(word:)

func check(word: String, closure: ()->Void)

如果要将参数传递给闭包,也需要指定该参数:

func check(word: String, closure: (status: CheckResult)->Void)

我只是在这里编造的;我只是需要一些类型,你可以用它来传达检查的结果。它可以是枚举,例如:CheckResult

enum CheckResult {
    case ok;
    case bad;
    case empty;
}

现在,在函数中,可以使用适当的值调用闭包,例如:.为了更具体,让我们填写你的空函数:checkclosure(.ok)

class CheckTextField {
    private let correctWord = "apple"
    
    func check(word: String, closure: (_ status: CheckResult)->Void) {
        if word.count == 0 {
            closure(.empty)
        } else if word == correctWord {
            closure(.ok)
        } else {
            closure(.bad)
        }
    }
}

那么我们可以这样使用它:

let checker = CheckTextField()

checker.check(word:"apple") { print($0) }       // ok
checker.check(word:"pear") { print($0) }        // bad
checker.check(word:"jackfruit") { print($0) }   // bad
checker.check(word:"") { print($0) }            // empty

您可以替换 替换为代码来设置标签颜色或您可能想要执行的任何其他操作。这很好,因为它将有关视图的详细信息排除在类之外。print($0)CheckTextField

评论

0赞 YanivH 9/19/2021
我想在上面的答案中补充一点,您还可以用于更复杂的检查,而不仅仅是单词比较。有关示例,请参阅以下链接:nshipster.com/swift-regular-expressionsRegex
1赞 Maria Mezhova 9/24/2021
感谢您的支持!在你的帮助下,我终于设法解决了我的问题:)
3赞 Saifullah ilyas 9/20/2021 #2

您可以在数据发送类中定义 clousure,如下所示

class DataSenderClass  {
var dataPassClousure:((String)->Void)?
func sendHere(){
    // i am invoking closure from here
    dataPassClousure?("hi i am data")
}

} 这是dataPassClousure接受字符串作为参数(你可以根据你的选择进行调整,也可以使用对象,也可以将多个参数传递给你的闭包)发送/传递给接收方类。 只需在数据接收器类中收听新数据,如下所示

class DataReceiverClass {
let senderObject = DataSenderClass()
func receiveHere() {
    //each time data change from sendHere function this closure invoke . perform your action
    senderObject.dataPassClousure = {arug1 in
        print("received data is \(arug1)")
    }
}

}

评论

0赞 Maria Mezhova 9/24/2021
谢谢!令人惊讶的是,它非常简单有效:)))