Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I created 2 helper classes for me. First for general SOAP request:

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

And second for each requests:

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: "")
        }
    }

It's working but I would like to create better solution. First improve requests body. Is is to possible to create it somehow from swift class? Let's say I would have class LoginMethod and with properties userName and password and I would call some method and it would return string like this (with values where are variables):

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

Then I would add begining of xml and end and I would have request.

Second problem is parsing xml. I found AEXML and It works great but again I would like to have something smarter. I would like to give it class and try to fill it with values from xml. My method could be enough for token but what if I have in response array of objects. Or if there are errors or other parameters.

Thanks for help.

share|improve this question

2 Answers 2

If you want a Easy-to-Use Soap parser, you should create soap classe from your WSDL. At this state, there is no tools for swift but you can find tools for objective-c. Before, I used WSDL2Objc to generate objective-c Classes that present a soap service (about 70% of classes are corrects). It can save you many times if you have big SOAP service.

I've just found another tool online (but premium features are not free): http://easywsdl.com/ The author says that it's compatible with Swift but I guest that we have to use Bridging Header. Normally, with Bridging Header, you can import Objective-C classes in your swift project.

share|improve this answer
    
I am really looking for swift solution. I found these projects before but it's not for my needs. –  Libor Zapletal Feb 25 at 14:55
    
As I said, there is no tool for swift right now. Correct me if I'm wrong. Another 'fast-food' solution for one-shot consum is to use SoapUI (soapui.org) to generate test-case then paste that xml into your 'postSOAP' (after adapt with your right values). –  HoaParis Feb 25 at 23:03
    
However, event use that solution, you still have to parser the result (xml format) to collect infos –  HoaParis Feb 25 at 23:09

This is an example of requesting a REST Web Service

var notes = []
var session = NSURLSession(configuration: 
    NSURLSessionConfiguration.defaultSessionConfiguration())

func loadNotes() -> Void {
    let reqURL = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8080/notes")!)
    let getNotesTask = session.dataTaskWithRequest(reqURL , completionHandler: 
        { (data, response, error) -> Void in

        var readJSONError:NSError?
        let noteTextJSONData = NSJSONSerialization.JSONObjectWithData(data, 
            options: NSJSONReadingOptions.AllowFragments, error: &readJSONError) as NSArray

        if let err = readJSONError {
            println(err.localizedDescription)
        } else {
            let mutableArray = NSMutableArray()
            for note in noteTextJSONData {
                mutableArray.addObject(note["name"] as NSString)
            }
            self.notes = mutableArray.copy() as NSArray
        }

        self.tableView.reloadData()
        println(response)
    })
    getNotesTask.resume()
}

With a SOAP request, It is quite similiar, but instead of NSJSONSerialization, you can use the NSXMLParser class to deal with the XML serialization.

Hope this helps!

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.