【问题标题】:Update textfield failed from soap web service result从肥皂网络服务结果更新文本字段失败
【发布时间】:2017-12-20 18:08:57
【问题描述】:

我刚开始使用 swift4 为 ios 编写应用程序,我遇到了 2 个问题,我正在调用一个肥皂网络服务,它成功了, 我可以在输出中打印结果(xml格式的字符串),我想用这个结果更新一个文本字段的文本,因为这个任务在后台运行,我把下面的代码放在了completionHandler的闭包中:

@IBOutlet weak var txt1: UITextField!

func httpGet(request: URLRequest)-> String{
    let soapReqXML = "some code..."
    let is_URL: String = "http://xxx.x.x.12/soapservice.asmx"
    let url = URL.init(string: is_URL)       
    let my_Request = NSMutableURLRequest(url: url!)            
    let configuration = URLSessionConfiguration.default                    
    let session = URLSession(configuration: configuration, delegate: self, delegateQueue:OperationQueue.main)

    my_Request.httpMethod = "POST"  
    my_Request.httpBody = soapReqXML.data(using: String.Encoding.utf8, allowLossyConversion: false)
    my_Request.addValue("host add...", forHTTPHeaderField: "Host")
    my_Request.addValue("text/xml;charset =utf-8", forHTTPHeaderField: "Content-Type")
    my_Request.addValue(String(soapReqXML.count), forHTTPHeaderField: "Content-Length")
    my_Request.addValue("http://mservice.my.xx/SNA...", forHTTPHeaderField: "SOAPAction")

    var responseData : Data = Data()
    var _re : String = "000"
    let task = session.dataTask(with: my_Request as URLRequest, completionHandler: {data, response, error -> Void in                                            
        if error == nil {               
            responseData = data!                
            _re = self.stringFromXML(data:responseData);   // calling stringFromXML to convert data into string          
            print("the result is :"+_re) // working here, I can see the good result in the output                              
            //execute from the main thread to update txt1
            DispatchQueue.main.async(execute:{
                 self.txt1.text = re // first problem, the error is :Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
                 self.txt1.text = "text" // I even change into "text", same error happened here 
            })    
        }  
    })        
    task.resume()      
    return _re       // second problem, the return is always 000 
}

我的第一个问题是:如果我在 ipad 模拟器中调用该函数,在调试中,它是这样写的:txt1=(UITextField!) nil, 第二个问题是,返回总是000(初始值)

有人可以帮我检查一下吗?提前谢谢!

【问题讨论】:

    标签: swift web-services asynchronous soap


    【解决方案1】:

    你可以看到输出,所以 re 不是 nil,因此 txt1 可能是 nil。检查 txt1 是否与界面生成器中的 UITextField 连接。

    第二个问题很清楚。 dataTask 在后台运行,因此 func httpGet 不会等待 dataTask 完成,然后继续运行代码“return _re”。而不是这个 func 以并行方式执行 dataTask 和 task.resume() (return _re) 之后的所有代码。所以 re 的初始值保持不变,因为 dataTask 需要一些时间来执行完成。

    你应该使用完成处理程序:

    func httpGet(request: URLRequest, completion: @escaping (String) -> ()) {
        let soapReqXML = "some code..."
        let is_URL = "http://xxx.x.x.12/soapservice.asmx"
        let url = URL(string: is_URL)
        let my_Request = NSMutableURLRequest(url: url!)
        let configuration = URLSessionConfiguration.default
        let session = URLSession(configuration: configuration, delegate: self, delegateQueue: .main)
    
        my_Request.httpMethod = "POST"
        my_Request.httpBody = soapReqXML.data(using: .utf8, allowLossyConversion: false)
        my_Request.addValue("host add...", forHTTPHeaderField: "Host")
        my_Request.addValue("text/xml;charset =utf-8", forHTTPHeaderField: "Content-Type")
        my_Request.addValue(String(soapReqXML.count), forHTTPHeaderField: "Content-Length")
        my_Request.addValue("http://mservice.my.xx/SNA...", forHTTPHeaderField: "SOAPAction")
    
        session.dataTask(with: my_Request as URLRequest, completionHandler: { data, response, error in
            if error == nil {
                let result = self.stringFromXML(data: data!)
                DispatchQueue.main.async {
                    self.txt1.text = result
                }
                completion(result)
            }
        }).resume()
    }
    

    用法:

    httpGet(request: request) { result in
        print(result)
    }
    

    【讨论】:

    • Hi@vlad1278,我查了一下,txt1和Interface builder中的UITextField连接了,我应用了你的建议使用补全,效果很好,两个问题都已经解决了同时! :) 所以非常感谢!
    【解决方案2】:

    第一个问题:
    txt1 的文本字段为零。如果您没有从 xib 或情节提要正确初始化视图或视图控制器,则可能会发生这种情况。如果您在 xib 或情节提要中有插座(或任何自定义),则它们只有在您使用正确的 init 函数时才会被初始化。简单地调用默认的 init 不会初始化出口。
      要从主包中名为 MyViewController.xib 的 xib 初始化类 MyViewController 的视图控制器:

    let myViewController = MyViewController.init(nibName:"MyViewController", bundle:Bundle.main)
    


      初始化类 MyViewController 的视图控制器,该控制器在主包中的 Main.storyboard 中具有标识符 myVC

    if let myViewController = UIStoryboard.init(name:"Main",bundle:Bundle.main).instantiateViewController(withIdentifier:"myVC") as? MyViewController{
     //use the vc
    }
    


      初始化在主包中的 xib 'MyView.xib` 中自定义的类 MyView 的视图:

    if let myView = Bundle.main.loadNibNamed("MyView",owner:self)?.first{
     //use your view
    }
    

    第二个问题:
    return _re 行在控制进入完成处理程序之前执行,_re 正在获取新值,因为网络调用是异步的。因此它返回初始值。如果你想异步返回一些数据,你应该使用完成处理程序。

    func httpGet(request: URLRequest,completionHandler:@escaping (String) -> ()){
       let soapReqXML = "some code..."
       let is_URL: String = "http://xxx.x.x.12/soapservice.asmx"
       let url = URL.init(string: is_URL)       
       let my_Request = NSMutableURLRequest(url: url!)            
       let configuration = URLSessionConfiguration.default                    
       let session = URLSession(configuration: configuration, delegate: self, delegateQueue:OperationQueue.main)
    
       my_Request.httpMethod = "POST"  
       my_Request.httpBody = soapReqXML.data(using: String.Encoding.utf8, allowLossyConversion: false)
       my_Request.addValue("host add...", forHTTPHeaderField: "Host")
       my_Request.addValue("text/xml;charset =utf-8", forHTTPHeaderField: "Content-Type")
       my_Request.addValue(String(soapReqXML.count), forHTTPHeaderField: "Content-Length")
       my_Request.addValue("http://mservice.my.xx/SNA...", forHTTPHeaderField: "SOAPAction")
    
       var responseData : Data = Data()
       var _re : String = "000"
       let task = session.dataTask(with: my_Request as URLRequest, completionHandler: {data, response, error -> Void in                                            
           if error == nil {               
               responseData = data!                
               _re = self.stringFromXML(data:responseData);   // calling stringFromXML to convert data into string          
               print("the result is :"+_re)        
               //execute from the main thread to update txt1
               DispatchQueue.main.async(execute:{
                    self.txt1.text = _re
               })    
               completionHandler(_re)
           }  
       })        
       task.resume()      
    }
    

    【讨论】:

    • 其实我从上周开始使用swift4进行测试,在项目文件夹中没有找到任何xib文件,可能是我创建的时候选择了“单视图应用”这个项目,所以关于第一个问题,我对你的解决方案没有太多了解,但是我接受了你的第二个建议,类似于@vlad1278,之后,这两个问题就神奇地消失了,也非常感谢你!跨度>
    猜你喜欢
    • 1970-01-01
    • 2021-07-29
    • 2017-01-16
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    相关资源
    最近更新 更多