swift 同步获取数据NSOperationQueue或NSURLSession

yyyllmsg  于 12个月前  发布在  Swift
关注(0)|答案(3)|浏览(106)

在我的应用程序中,我们必须在点击登录按钮时进行3次服务器调用。

1) will make a server call to get an OAuth token for user credentials
2) with the token from (1) we will get user privileges
3) with the token from (1) and with the valid privilege from (2) we will get the data to be displayed on the page after login in a tableview.

字符串
我对这种方法感到困惑。使用operationqueue添加依赖项或使用NSURLSession任务是一种好方法吗?
根据此堆栈溢出解决方案之一-Best practices for making a queue of NSURLSessionTasks,NSURLSession没有任何关于对请求进行排序的逻辑,即使将每台主机的最大连接数设置为1,它也只会调用最先完成的完成块
如果有其他更好的方法,让我知道。

hwazgwia

hwazgwia1#

你可以使用NSURLSession任务。首先调用第一个API方法,你将在完成处理程序(块)中获得响应。现在将其存储在任何公共属性中(当你想再次使用它时)。从完成处理程序调用第二个API方法,从第二个方法的完成处理程序,通过传递响应并使用存储有第一个API方法的对象的公共属性来调用第三个API方法。
只有当响应到达时才调用完成处理程序或块,因此通过这种方式您可以管理API调用。
希望这会有所帮助:)

pdsfdshx

pdsfdshx2#

在一天结束的时候,使用传统的“完成处理程序”方法的代码的 * 简化 * 版本可能如下所示:

fetchOAuthToken() { (token, error) in
    if let token = token {
        fetchPrivileges(token: token) { (privileges, error) in
            if let privileges = privileges {
               fetchData(token: token, privileges: privileges) { (data, error) in 
                   if let data = data {
                       // ... 
                   }
               }
            }
        }
    }
}

字符串
请注意,仅为简洁起见,代码不包含错误处理,也没有取消的方法。
依赖关系是通过 continuations 建立的,也就是完成处理程序。
另一种使用“类Scala”future的方法如下所示(使用 Promises 是非常类似的方法):

fetchOAuthToken().flatMap { token in
    fetchPrivileges(token: token).flatMap { privileges in
        fetchData(token: token, privileges).map { data in
            // ...
        }
    }
}.onFailure { error in
    print("Error: \(error)")
}


上面的语句创建了一个由三个任务组成的任务。
这种方法包含了完整的错误处理,尽管它可能并不明显。生产版本与上面的代码片段没有太大的不同-它可能只是增加了一种取消的方法。
有一些第三方库实现了类似于Scala的futures或Promises。
一种添加取消的方法可以如下所示:

let cr = CancellationRequest()
fetchOAuthToken(ct: cr.token).flatMap { token in
    fetchPrivileges(token: token, ct: cr.token).flatMap { privileges in
        fetchData(token: token, privileges, ct: cr.token).map { data in
            // ...
        }
    }
}.onFailure { error in
    print("Error: \(error)")
}


稍后,您可以取消组合任务(无论它当前正在执行什么):

cr.cancel()

注:

这个问题也可以用NSOperations解决。但是,它需要NSOperation的三个子类,以及一个或两个线程安全的助手类,这些助手类将用于将Op 1的结果“传输”到Op 2的输入,并将Op 2的结果“传输”到Op 3的输入。我估计这将需要大约500行代码--对于SO的答案来说太多了;)
“类Scala-like”future方法需要第三方库,而取消则需要另一个--或者你自己的实现(这并不难),或者一个提供所有功能的库。

6qqygrtg

6qqygrtg3#

// Importing the UIKit framework for iOS app development
import UIKit

// ViewController class conforming to UITableViewDelegate and UITableViewDataSource protocols
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    // Private instance of NewViewModel
    private var newviewmodel: NewViewModel?

    // IBOutlet for the UITableView in the storyboard
    @IBOutlet weak var mTableview: UITableView!

    // Override function called when the view loads
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set up the table view and initialize the view model
        SetUpTableview()
        newviewmodel = NewViewModel()

        // Fetch todos using the view model and reload the table view on completion
        newviewmodel?.fetchTodos { [weak self] in
            DispatchQueue.main.async {
                self?.mTableview.reloadData()
            }
        }
    }

    // Function to set up the table view
    func SetUpTableview() {
        mTableview.delegate = self
        mTableview.dataSource = self
        mTableview.register(UINib(nibName: "NewTableViewCell", bundle: nil), forCellReuseIdentifier: "NewTableViewCell")
    }

    // Number of sections in the table view
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    // Number of rows in the table view, using the count from the view model
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return newviewmodel?.numberOfTodos ?? 0
    }

    // Configure and return a cell for the table view
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "NewTableViewCell", for: indexPath)  as! NewTableViewCell
        cell.Title.text = newviewmodel?.getTodoAtIndex(indexPath.row).title
        cell.CompleteLbl.text = "\(String(describing: newviewmodel?.getTodoAtIndex(indexPath.row).completed))"
        cell.Id.text = "\(newviewmodel?.getTodoAtIndex(indexPath.row).id ?? 0)"
        cell.UserName.text = "\(newviewmodel?.getTodoAtIndex(indexPath.row).userId ?? 0)"
        return cell
    }

    // Set the height for each row in the table view
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200
    }
}

字符串

相关问题