Swift - 为SOAP Web服务创建请求和解析响应

时间:2015-02-12 16:21:48

标签: ios xml swift ios7 soap

我为我创建了2个辅助类。首先是一般的SOAP请求:

import Foundation

class ApiManager : NSObject {

    var token: String

    class var sharedInstance: ApiManager {
        struct Static {
            static var instance: ApiManager?
            static var disptachToken: dispatch_once_t = 0
        }

        dispatch_once(&Static.disptachToken) {
            Static.instance = ApiManager()
        }

        return Static.instance!
    }

    override init() {
        token = ""
        super.init()
    }

    func postSOAP(message: String, urlString: String, soapAction: String, completion: (result: NSData) -> Void) {

        var url = NSURL(string: urlString)

        var request = NSMutableURLRequest(URL: url!)

        var msgLength = String(countElements(message))

        request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.addValue(msgLength, forHTTPHeaderField: "Content-Length")
        request.addValue(soapAction, forHTTPHeaderField: "SOAPAction")
        if (!token.isEmpty) {
            request.addValue(".CAAUSGEX=" + token, forHTTPHeaderField: "Cookie")
        }
        request.HTTPMethod = "POST"
        request.HTTPBody = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) // or false

        let queue:NSOperationQueue = NSOperationQueue()

        NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
            completion(result: data)
        })
    }
}

每个请求的第二个:

class ContentManager : NSObject {

    private let apiManager = ApiManager.sharedInstance

    class var sharedInstance: ContentManager {
        struct Static {
            static var instance: ContentManager?
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            Static.instance = ContentManager()
        }

        return Static.instance!
    }

    override init() {
        super.init()
    }

    func login(email: String, password: String, completion: (token: String) -> Void) {
        var soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:LoginMethod><ns1:userName>" + email + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod></SOAP-ENV:Body></SOAP-ENV:Envelope>"


        let urlString = "https://someurl.svc/soap"
        let soapAction = "http://someurl/LoginMethod"

        ApiManager.sharedInstance.postSOAP(soapMessage, urlString: urlString, soapAction: soapAction) { (result) -> Void in
            var error: NSError?
            if let xmlDoc = AEXMLDocument(xmlData: result, error: &error) {

                // prints the same XML structure as original
                println(xmlDoc.xmlString)
                let token = xmlDoc.root["s:Body"]["GetResponse"]["LoginTokenResult"].stringValue
                println(token)
                completion(token: token)

            } else {
                println("description: \(error?.localizedDescription)\ninfo: \(error?.userInfo)")
            }
            completion(token: "")
        }
    }

它正在运作,但我想创造更好的解决方案。首先改进请求体。是不是可以从swift类创建它?假设我有类LoginMethod和属性userName和密码,我会调用一些方法,它会返回这样的字符串(值为变量值):

<ns1:LoginMethod><ns1:userName>" + userName + "</ns1:userName><ns1:password>" + password + "</ns1:password></ns1:LoginMethod>

然后我会添加xml的开头并结束,我会请求。

第二个问题是解析xml。我找到了AEXML并且效果很好但是我想要更聪明的东西。我想给它上课并尝试用xml中的值填充它。我的方法可能足以用于令牌但是如果我有响应对象数组的话。或者如果有错误或其他参数。

感谢您的帮助。

2 个答案:

答案 0 :(得分:5)

虽然仍处于测试阶段,但仍然涵盖了您正在寻找的内容,并为您提供了一个可以随意修改的良好基础:

http://wsdl2swift.com 

以下是一个示例用法: enter image description here

免责声明:我是作者。

答案 1 :(得分:4)

如果你想要一个易于使用的Soap解析器,你应该从你的WSDL创建soap classe。在这种状态下,没有swift的工具,但你可以找到objective-c的工具。之前,我使用WSDL2Objc生成了Objective-c类,它提供了一个soap服务(大约70%的类是纠正的)。如果你有大的SOAP服务,它可以节省你很多次。

我刚刚在网上找到了另一个工具(但高级功能不是免费的):http://easywsdl.com/作者说它与Swift兼容,但我是客人,我们必须使用Bridging Header。通常,使用Bridging Header,您可以在swift项目中导入Objective-C类。