从soap Web服务结果更新文本字段失败

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从soap Web服务结果更新文本字段失败相关的知识,希望对你有一定的参考价值。

我刚刚开始使用swift4为ios编写应用程序,我在这里遇到了2个问题,我正在调用soap web服务,它是成功的,我可以在输出中打印结果(字符串与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(初始值)

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

答案

你可以看到输出,所以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)
}
另一答案

第一个问题: 文本字段txt1是零。如果尚未正确初始化xib或storyboard中的视图或视图控制器,则会发生这种情况。如果您在xib或故事板中有插座(或任何自定义),则只有在使用正确的init函数时才会初始化它们。只需调用默认的init就不会初始化插座。 要从主包中名为MyViewController的xib初始化类MyViewController.xib的视图控制器:

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

要初始化一个MyViewController类的视图控制器,它位于主包中的myVC中并且具有标识符Main.storyboard

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()      
}

以上是关于从soap Web服务结果更新文本字段失败的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Drupal 视图中显示 Web 服务 (SOAP) JSON 结果

Java 使用 SSL 握手失败连接到 SOAP Web 服务

如何将 WS-Addressing 字段添加到 SOAP 消息

如何在 SENCHA TOUCH 中使用 SOAP Web 服务?

活动到片段通信:当我尝试从活动更新片段中的文本视图时,出现空指针异常

使用 SOAP 从 VBA 调用 Web 服务