Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 将类编写为帮助器服务并从另一个类调用它_Swift - Fatal编程技术网

Swift 将类编写为帮助器服务并从另一个类调用它

Swift 将类编写为帮助器服务并从另一个类调用它,swift,Swift,我正试图理解如何在Swift中实现这一点 例如,假设我有以下UIViewController class ViewController: UIViewController { let logoutButton: UIButton = { let button = UIButton() button.setTitle("Logout", for: .normal) button.setTitleColor(UIColor.black, fo

我正试图理解如何在Swift中实现这一点

例如,假设我有以下UIViewController

class ViewController: UIViewController {

    let logoutButton: UIButton = {
        let button = UIButton()
        button.setTitle("Logout", for: .normal)
        button.setTitleColor(UIColor.black, for: .normal)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 24)
        button.addTarget(self, action: #selector(onPressLogout), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        navigationItem.title = "Logged in"

        view.addSubview(logoutButton)
        NSLayoutConstraint.activate([
            logoutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            logoutButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
    }

    @objc fileprivate func onPressLogout() {
        AuthService.logOut()
    }
}
还有一个AuthService

final class AuthService {
    static func logOut() -> Void {
        print("Logout Pressed")
    }
}
我想做的是在按下
onPressLogout
时,在我的
AuthService
上调用
logOut

我想了解的是,我应该如何以正确和最好的方式访问
注销

比如说,像我现在这样?类上的静态方法

我应该创建一个这样的实例吗

lazy var auth = AuthService()
然后通过
auth.logout()
调用logout,而不使用
static
关键字


我对创建这些“助手”类的最佳方法感到困惑。

我不知道AuthService的确切用法,但你可以考虑用一种模式来写。

这保证只启动类的一个实例。单例模式示例:
URLSession.shared
UserDefaults.standard


<> P>这样,您就可以像“代码> AuthService”、“共享”、“登录”()、“代码”>或“代码> AuthService”、“共享”、“ISUSER LogGEDIN < /代码>

< P>我不知道AuthService的确切用法,但您可以考虑将其写入模式。

这保证只启动类的一个实例。单例模式示例:
URLSession.shared
UserDefaults.standard


这样,您就可以通过类似于
AuthService.shared.logout()
AuthService.shared.isUserLoggedIn

的方式访问它。我可能会使用


这将允许您调用类似于
AuthService.shared.logOut()的方法
我可能会使用


这将允许您调用类似于
AuthService.shared.logOut()的方法使用单例是一种常见的做法

对于可测试性,我建议将AuthService作为依赖项注入。首先,我要创建一个协议:

protocol AuthServiceProtocol {
    func logOut()
}
然后我将使我的服务符合该协议。(注意:这个类可以设置为一个单例,对于我在这里演示依赖注入的目的来说,这并不重要。)

我将向视图控制器添加一个类级变量:

class ViewController: UIViewController {
    var authService: AuthServiceProtocol?

    //existing code...
}
注销功能需要更改如下:

@objc fileprivate func onPressLogout() {
    authService?.logOut()
}
创建视图控制器后,我会将服务传递给它:

let vc = ViewController()
vc.authService = AuthService()
就这样。我可以在这样的操场上进行测试:

//TEST by forcing view to load and sending fake button touch event
let _ = vc.view
vc.logoutButton.sendActions(for: .touchUpInside)

//prints... "Logout Pressed"

现在,我可以编写一个真正的单元测试,通过一个没有依赖关系的模拟服务。这使我能够更可靠地测试视图控制器。

使用单例是一种常见做法

对于可测试性,我建议将AuthService作为依赖项注入。首先,我要创建一个协议:

protocol AuthServiceProtocol {
    func logOut()
}
然后我将使我的服务符合该协议。(注意:这个类可以设置为一个单例,对于我在这里演示依赖注入的目的来说,这并不重要。)

我将向视图控制器添加一个类级变量:

class ViewController: UIViewController {
    var authService: AuthServiceProtocol?

    //existing code...
}
注销功能需要更改如下:

@objc fileprivate func onPressLogout() {
    authService?.logOut()
}
创建视图控制器后,我会将服务传递给它:

let vc = ViewController()
vc.authService = AuthService()
就这样。我可以在这样的操场上进行测试:

//TEST by forcing view to load and sending fake button touch event
let _ = vc.view
vc.logoutButton.sendActions(for: .touchUpInside)

//prints... "Logout Pressed"

现在,我可以编写一个真正的单元测试,通过一个没有依赖关系的模拟服务。这使我能够更可靠地测试视图控制器。

我认为您使用该协议有点过分。从外部注入
AuthService
是一个好主意,但是为什么要使用协议呢?对于单元测试来说,使用模拟服务而不是真正的服务是很有价值的。真正的服务可能依赖于难以控制的外部数据或网络。我知道,但它也会让你的整个应用程序充满不必要的协议,这些协议需要维护,并且只由一个类实现。不要对UI进行单元测试。为UI创建集成测试,也就是说,编写一个测试,该测试将实际单击正在运行的应用程序实例中的按钮。您不能对UI进行单元测试,因为UI只是UIKit、数据模型和服务之间的连接器,所以您的测试最终会复制UI代码。去那里,这不是个好主意。代码覆盖率很高,但实际上没有发现bug。好的,我们可以不同意。我已经成功地对视图控制器进行了单元测试。UI与其他代码没有任何不同。您编写的代码仍然可能存在bug。也许你的UI代码是没有bug的,但是我已经用这种技术在我的代码中发现了bug。我认为你在这个协议上走得太远了。从外部注入
AuthService
是一个好主意,但是为什么要使用协议呢?对于单元测试来说,使用模拟服务而不是真正的服务是很有价值的。真正的服务可能依赖于难以控制的外部数据或网络。我知道,但它也会让你的整个应用程序充满不必要的协议,这些协议需要维护,并且只由一个类实现。不要对UI进行单元测试。为UI创建集成测试,也就是说,编写一个测试,该测试将实际单击正在运行的应用程序实例中的按钮。您不能对UI进行单元测试,因为UI只是UIKit、数据模型和服务之间的连接器,所以您的测试最终会复制UI代码。去那里,这不是个好主意。代码覆盖率很高,但实际上没有发现bug。好的,我们可以不同意。我已经成功地对视图控制器进行了单元测试。UI与其他代码没有任何不同。您编写的代码仍然可能存在bug。也许你的UI代码没有bug,但我用这种技术发现了代码中的bug。你问错了问题。您的代码有一个致命的缺陷:您的
onPressLogout
将永远不会被调用!所以你永远不能打电话给你的助手或其他任何事情。你的按钮坏了。你问错问题了。您的代码有一个致命的缺陷:您的
onPressLogout
将永远不会被调用!所以你永远不能打电话给你的助手或其他任何事情