Swift PHP发布请求从任务中设置全局变量

Posted

技术标签:

【中文标题】Swift PHP发布请求从任务中设置全局变量【英文标题】:Swift PHP post request set global variable from task 【发布时间】:2016-06-29 02:16:17 【问题描述】:

我使用发布请求成功地从数据库中检索数据。 (我不想使用get request,因为我想向php发送验证。)不要担心php部分,应该没问题。

import UIKit

class mainPage: UIViewController, UITableViewDelegate, UITableViewDataSource 

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var toolBar: UIToolbar!
    var values:NSArray = []

    @IBOutlet weak var Open: UIBarButtonItem!
    override func viewDidLoad() 
        super.viewDidLoad()


        Open.target = self.revealViewController()
        Open.action = #selector(SWRevealViewController.revealToggle(_:))
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
        get()

    
    func get()
        let request = NSMutableURLRequest(URL: NSURL(string: "http://www.percyteng.com/orbit/getAllpostsTest.php")!)
        request.HTTPMethod = "POST"
        let postString = "user=\("ios")"
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) 
            data, response, error in
            if error != nil 

                print("error=\(error)")
                return
            

            print("response = \(response)")

            let array = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
            self.values = array
        
        task.resume()
    dispatch_async(dispatch_get_main_queue())  tableView.reloadData()
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    
    func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return 1
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        if values.count > 20
            return 20
        
        else
            return values.count
        
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as!postCell

        let maindata = values[values.count-1-indexPath.row]
        if maindata["category"] as? String == "Services"
            cell.postImg.image = UIImage(named: "tile_services")
        
        else if maindata["category"] as? String == "exchange"
            cell.postImg.image = UIImage(named: "tile_exchange")
        
        else if maindata["category"] as? String == "Tutors"
            cell.postImg.image = UIImage(named: "tile_tutoring")
        
        else if maindata["category"] as? String == "Sports"
            cell.postImg.image = UIImage(named: "tile_sports")
        
        else if maindata["category"] as? String == "Sublet"
            cell.postImg.image = UIImage(named: "tile_sublet")
        
        else if maindata["category"] as? String == "Events"
            cell.postImg.image = UIImage(named: "tile_events")
        
        else
            cell.postImg.image = UIImage(named: "tile_carpool")
        


        if maindata["category"] as? String == "Services" || maindata["category"] as? String == "Tutors" || maindata["category"] as? String == "Events"
            cell.title.text = maindata["title"] as? String
        
        else if maindata["category"] as? String == "Sublet" || maindata["category"] as? String == "Rideshare"
            cell.title.text = maindata["location"] as? String
        
        else
            cell.title.text = maindata["item"] as? String
        


        if maindata["category"] as? String == "Sublet" || maindata["category"] as? String == "Rideshare"
            cell.location.text = ""
        
        else
            cell.location.text = maindata["location"] as? String
        
        cell.category.text = maindata["category"] as? String
        cell.price.text = maindata["price"] as? String
        return cell
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
    

所以我有一个名为 values 的全局变量,它是一个 NSArray,我想将此数组的值设置为我从数据库中检索的数组。但是,在函数 get() 中,发布请求充当另一个线程,我必须编写 self.values = array 这不会改变我的全局变量的值。

我需要该值来在主数组中组织我的 tableview。

基本上,我的问题是如何从闭包中获取值并将其设置为全局变量。

谢谢!如果你们不明白我在说什么,请告诉我。

【问题讨论】:

使用调试器在self.values = array处添加断点,并检查array在该位置停止时的值(在左下视图或在控制台中键入p dump(array)) .另外我建议使用[AnyObject] 而不是NSArray 嘿,我在之前和那时检查过,数组提供了我想要从数据库中获取的正确信息。在任务关闭之外没有任何东西被保存 【参考方案1】:

您需要在 func get() 中添加一个完成处理程序,因为您正在执行 dataTaskWithRequest 这是一个 Async 调用。试试这个:

func get(finished: (isDone: Bool) -> ())
//your code
data, response, error in
            if error != nil 
                finished(isDone: false)
                print("error=\(error)")
                return
            


            print("response = \(response)")

            let array = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
            self.values = array
        

task.resume()
finished(isDone: true)

然后在你的viewDidLoad:

 override func viewDidLoad() 
        super.viewDidLoad()
   get  success in
   if success
//reload your tableview here



【讨论】:

这是一个不错的答案,但其他人为我提供了一个完成处理程序来传递数据,而不仅仅是一个布尔变量。谢谢!【参考方案2】:

闭包隐式地保留了 self,所以你实际上是在修改那个属性。但是在闭包中检索到数据后,您需要使用reloadCellsAtIndexPathinsertCellsAtIndexPathreloadData 刷新您的tableView。后者是最简单的方法,但完全替代了表的当前状态。

此外,您在闭包中导致了一个保留周期。您应该将 self 作为 weakunowned 属性传递,以让 ARC 完成其工作。欲了解更多信息:http://krakendev.io/blog/weak-and-unowned-references-in-swift

例子:

func get()
    let request = NSMutableURLRequest(URL: NSURL(string: "http://www.percyteng.com/orbit/getAllpostsTest.php")!)
    request.HTTPMethod = "POST"
    let postString = "user=\("ios")"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) 
        data, response, error in
        if error != nil 

            print("error=\(error)")
            return
        

        print("response = \(response)")

        let array = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
        self.values = array
        dispatch_async(dispatch_get_main_queue())  [unowned self] in
            self.tableView?.reloadData();
        
    
    task.resume()

【讨论】:

我刚刚编辑了我的代码,在我执行 task.resume() 之后我确实有 tableview.reloadData。这并没有真正做任何事情。 @PercyTeng 因为数据是异步传递的,所以当你用resume 发送请求后立即刷新它不会发生任何事情。实际分配数组时需要刷新它。 问题是,我正在将数据从数据库检索到任务线程中的变量数组,但我想先将其设置为全局变量“values”,并且我的 tableview 的值将根据“价值观”的价值。所以赋值数组的代码在那个线程中,但是给tableview赋值的代码在另一个线程中 我知道你的意思,我应该在为变量赋值后重新加载 tableview 数据,因为所有 tableview 数据都是从变量“values”加载的,但我的问题是我的代码从不为变量“values”,因为“values”是主线程中的全局变量,而我在另一个线程中获取我想要的数据,即发布请求 其他线程无所谓,self仍然被捕获在闭包内。设置 values 属性后,您不会在闭包中重新加载数据。您需要在闭包内设置 self.value 后立即执行此操作。您可以使用 `dispatch_async(dispatch_get_main_queue(), [unowned self] in ) 在主线程上执行它

以上是关于Swift PHP发布请求从任务中设置全局变量的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 需要从模型中访问 BaseController 中设置的全局变量

在 Magento 中设置全局变量,GUI 方式?

如何在 Laravel 中设置全局变量?

swift 在整个应用程序中设置自定义字体的全局外观。

如何在 VBA 中设置全局变量

在R中的引用类中设置全局变量