gpt4 book ai didi

swift - 在 swift 单例中调用异步函数的正确方法

转载 作者:行者123 更新时间:2023-11-28 06:13:41 24 4
gpt4 key购买 nike

我想为我的应用程序构建一个分析类,并且我正在使用单例。

如果我运行它,tagEvent 函数会立即运行,而不是首先运行 openSession(),因此 sessionId 返回 nil。我如何通过适当的初始化创建这样的类,并像单例实例一样在应用程序范围内使用它。

Analytics.swift

final class Analytics {
public static let instance = Analytics()
private var baseUrl = "http://localhost"
public var deviceId: String?

private init(){
self.deviceId = SomeFunctionGetsDeviceID()
}

func openSession(){
// make an API call to create a session and save sessionId to UserDefaults
if let url = URL(string: self.baseUrl + "/session"){
let params:[String:Any] = ["deviceId": "\(self.deviceId!)"]

var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: params, options: [])

AnalyticsSessionManager.sharedManager.request(request as URLRequestConvertible).validate().responseObject(completionHandler: { (response: DataResponse<SessionOpenResponse>) in
if response.result.value != nil {
UserDefaults.standard.set(response.result.value?.sessionId, forKey: "sessionId")
}
})
}
}

func closeSession(){
// make an API call to close a session and delete sessionId from UserDefaults
...
}

func tagEvent(eventName: String, attributes: [String : String]? = nil) {
if let url = URL(string: self.baseUrl + "/event"),
let sessionId = UserDefaults.standard.string(forKey: "sessionId"){
...
// make an API call to create an event with that sessionId
}
}
}

AppDelegate.swift

func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Analytics.instance.openSession()
Analytics.instance.tagEvent(eventName: "App Launch", attributes:
["userID":"1234"])
}

最佳答案

我最好的猜测是 openSession 函数正在异步执行工作,并且 tagEvent 调用在异步代码完成之前进入。有几种解决方法:

1) 添加同步,这样 tagEvent 代码将等待 openSession 调用完成(如果正在进行)。如果不在进行中,或许应该自动调用openSession,等待完成,然后执行那个函数中的代码

2) 从 openSession 添加一个完成处理程序,在该外壳内您可以调用 tagEvent,例如:

func openSession(completionHandler: @escapaing (Bool) -> ()){
// make an API call to create a session and save sessionId to UserDefaults
...
UserDefaults.standard.set(someSessionID, forKey: "sessionId")

// when done with async work
completionHandler(true)
}

然后在您的应用委托(delegate)中:

Analytics.instance.openSession() { (success)
Analytics.instance.tagEvent(eventName: "App Launch", attributes:["userID":"1234"])
}

3) * 这是我修复它的方式 * 我不会在类外调用 openSession。我会向 Analytics 类添加一个标志:

private var initialized = false

在openSession函数中,一切搞定后设置这个

initialized = true

在 tagEvent 函数中:

func tagEvent(eventName: String, attributes: [String : String]? = nil) {
// Check for initialization
if (!initialized) {
openSession() { (success) in
// perform your tagEvent code
})
} else {
if let url = URL(string: self.baseUrl + "/event"),
let sessionId = UserDefaults.standard.string(forKey: "sessionId"){
...
// make an API call to create an event with that sessionId
}
}
}

关于swift - 在 swift 单例中调用异步函数的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45741252/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com