I would like to improve the inability to retrieve data correctly because the processing is shifted to the background by HTTP communication.Or alternatives?

Asked 2 years ago, Updated 2 years ago, 77 views

Due to background processing, the order of operation of the functions below has changed and the return value of the functions is not expected.

let task=NSURLSession.sharedSession().dataTaskWithRequest......

This line and beyond are skipped and the function is terminated.

Could you tell me how to improve it?
This is the way to use Post.Alternatives are fine.

The code was too old, so I modified it to work properly except for the HTTP address.

In the following case, the print output order is "NG" ->HTML code.Correct HTML code ->"OK"

Thank you for your cooperation.

import UIKit

classViewController:UIViewController, NSURLSessionDelegate, NSURLSessionDataDelegate {

override func viewDidLoad(){
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from anib.

    print(Test())
}

override funcdidReceiveMemoryWarning(){
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func Test() - > String {
    let post="name=Masuda&addr=Tokyo"
    let postdata=post.dataUsingEncoding (NSShiftJISStringEncoding)!
    let url = NSURL (string: "http://moonmile.net/ios9/post.php")
    let req = NSMutableURLRequest (URL: url!)
    req.HTTPMethod="POST"
    req.setValue("application/x-www-form-urlencoded", for HTTPHeaderField: "Content-Type")
    let length = postdata.length
    req.setValue("\(length)" for HTTPHeaderField: "Content-Length")
    req.HTTPBody=postdata
    var textBuf: String = "NG"
    let task = NSURLSession.sharedSession().dataTaskWithRequest(req, completionHandler: {
        (data, res, err) in
        if data!=nil{

            let text = NSSstring(data:data!, encoding:NSShiftJISStringEncoding)

            print(NSString(data:data!, encoding:NSShiftJISStringEncoding))
            dispatch_async(dispatch_get_main_queue(), {
                textBuf="OK"
            })
        }
    })

    task.resume()
    return textBuf
}
}

ios swift xcode7

2022-09-29 21:49

2 Answers

"Waiting for termination" is a wrong solution just because asynchronous processing results are not immediately available.While waiting in a simple loop for an exit is a no-brainer, if you continue to wait for an unspecified amount of time in the expected method called by the main thread, as in this example, the main thread will slow down and compromise usability.

When writing code that uses asynchronous processing, you should remember the following principles:
1. The method that invokes asynchronous processing cannot return the result of the processing
2. After starting asynchronous processing, do nothing in that method anymore
3. Asynchronous processing results must be handled in the completion handler

In the case of real apps, it is inconceivable to simply print the contents of the String, so if you want to make it a generic method, one way is to have your method have a completion handler that passes the result as an argument instead of returning it as a return value.

If you rewrite the original example you gave me, it looks like this

import UIKit

classViewController:UIViewController, NSURLSessionDelegate, NSURLSessionDataDelegate {
    override func viewDidLoad(){
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from anib.

        Test({(result:String)->Void in// Asynchronous processing results must be handled in the completion handler
            print(result)
        })
    }

    override funcdidReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func Test(completionHandler:(String)->Void) {// Make your own method have a completion handler as well
        let post="name=Masuda&addr=Tokyo"
        let postdata=post.dataUsingEncoding (NSShiftJISStringEncoding)!
        let url = NSURL (string: "http://moonmile.net/ios9/post.php")
        let req = NSMutableURLRequest (URL: url!)
        req.HTTPMethod="POST"
        req.setValue("application/x-www-form-urlencoded", for HTTPHeaderField: "Content-Type")
        // Content-Length is not required when HTTPBody is specified in NSData
        req.HTTPBody=postdata
        var textBuf: String = "NG"
        let task = NSURLSession.sharedSession().dataTaskWithRequest(req, completionHandler: {
            (data, res, err) in
            if data!=nil{

                let text = String (data:data!, encoding:NSShiftJISStringEncoding)

                print(text)
                dispatch_async(dispatch_get_main_queue(), {
                    textBuf="OK"
                    completionHandler(textBuf) // Call your own completion handler in the completion handler
                })
            }
        })
        task.resume()
        // Do nothing in the method after starting asynchronous processing
    }
}

I don't think I've ever seen (in iOS and other programs) a way of writing where you wait for a button to be pressed in a loop like while!isButtonPressed{/*...*/}.(I used to do it normally when programming a one-board microcomputer a long time ago...) For asynchronous processing with communication, please learn a proper asynchronous processing pattern instead of waiting for it to be processed.


2022-09-29 21:49

The following code is the resolved code.

import UIKit

classViewController:UIViewController, NSURLSessionDelegate, NSURLSessionDataDelegate {

    var waiting = true // Add

    override func viewDidLoad(){
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from anib.

        print(Test())
    }

    override funcdidReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func Test() - > String {
        let post="name=Masuda&addr=Tokyo"
        let postdata=post.dataUsingEncoding (NSShiftJISStringEncoding)!
        let url = NSURL (string: "http://moonmile.net/ios9/post.php")
        let req = NSMutableURLRequest (URL: url!)
        req.HTTPMethod="POST"
        req.setValue("application/x-www-form-urlencoded", for HTTPHeaderField: "Content-Type")
        let length = postdata.length
        req.setValue("\(length)" for HTTPHeaderField: "Content-Length")
        req.HTTPBody=postdata
        var textBuf: String = "NG"
        let task = NSURLSession.sharedSession().dataTaskWithRequest(req, completionHandler: {
            (data, res, err) in
            if data!=nil{

                let text = NSSstring(data:data!, encoding:NSShiftJISStringEncoding)

                print(NSString(data:data!, encoding:NSShiftJISStringEncoding))
                dispatch_async(dispatch_get_main_queue(), {
                    textBuf="OK"
                    waiting = false // Add
                })
            }
        })

        task.resume()
        // Add
        while (waiting) {
            NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate:NSDate())
        }
        return textBuf
    }
}


2022-09-29 21:49

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.