I am using http://wsdl2swift.com/ to create an iOS Swift JSON Client who is calling an asmx-WebService.
Everything works great, i can build the connection, receive the result JSON-String inside the response XML, and it is printed inside the libraries "makeSoapConnection"-Function.
But if i call
let client = SyedAbsarClient()
let gam = GetAllBla()
gam.cpMyId = "12"
client.opGetAllBla(gam){(response: GetAllBlaResponse?, error:NSError?) -> Void in
print(response?.cpGetAllBlaResult)
}
i only get "nill"
As mentioned on the website, the utility is still under progress, For now, it returns the actual xml response that you can parse
print(response?.xmlResponseString)
Related
I have built and deployed a firebase function that returns Hello World when called and deployed it to Firebase functions
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send('{"Message":"Hello fromn Firebase"}');
};
However When I call it from iOS through firebase functions it returns an internal error that 'response was not a dictionary'. Passing a value through does not affect it
functions.httpsCallable("getCampaign").call {(result, error) in
if let error = error as? NSError{
switch FunctionsErrorCode(rawValue: error.code) {
case .internal:
print("Internal error \(error.localizedDescription)")
print(result)
default:
print("Error \(error.localizedDescription) \(error.code) \(error.domain)")
}
}
I assume that this is most likely because iOS is expecting a dictionary to be returned, how can I change this so it allow a string to be returned. Thanks for your help.
You're mixing two types of Cloud Functions:
HTTP functions, which are called with GET or POST HTTP calls from within your Swift code.
Callable functions, which are calling using the firebase-functions SDK in your Swift code.
Your Cloud Functions code is written using the first, while the Swift code is using the second. The two types of Cloud Functions can't be matched.
So you will either have to conver the Cloud Functions to be declared as shown in writing callable Cloud Functions, or use a standard HTTP call in your Swift code.
I am currently developing an application for iOS. Most of the features that I wanted implemented I have already finished, but there is one feature in particular that I really need to have - Network Errors handling.
So for example: A user is trying to refresh his data inside my application. Instead of my app crashing or simply not doing anything, I would love for that exception to be caught, identified and then display a corresponding message on screen using AlertDialogs. for example:
Network Error - title;
Unreachable host, please check your network connectivity and try again - Message;
OK - button;
I was able to have this working in my Android application and it's quite useful, however, I am quite new to Swift and iOS development, so, please help me out here and point me in the right direction.
I am currently using latest Alamofire for sending HTTP Requests, here is my example of HTTP Request that I have implemented inside my application.
func loadProfile() {
let url = Constants.profileURL
let headers: HTTPHeaders = ["Cookie": "username; password"]
AF.request(url, method: .post, headers: headers).response {response in
if let data = response.data, let dataString = String(data: data, encoding: .utf8) {
if dataString.contains(Constants.loginSuccess) {
//Do something
}
}
}
}
Alamofire's DataResponse (and all response types) contain the Result of serialization. You can use that value to check whether serialization, and the request in general, succeeded or failed. You can then pass the result value to completion handlers to be dealt with as you wish.
I want to send an error to my iOS Application using Firebase Cloud Functions.
But I don't get any error when I use my url:
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
print(error) // Print nil
}
I have tried all these:
res.status(400).send("error");
res.status(400).send(New Error("error"));
console.error(new Error('A problem occurred'));
res.render({error:...})
Yea there is no way. The error message you send back like res.status(400).send("error"); is in the body itself. If you look at FIRFunctions.m file, it ignores that as it returns a firebase error message instead "Unimplemented" and "Internal" which are totally unconceptual and misleading messages. Like you get unimplemented error for res.status(400).send("error"). So the bottom line, the iOS SDK doesn't support it. You can to write your own localized error messages in your client side which is actually at the end better.
I use URLRequestConvertible to groups my web calls, and to reduce the boilerplate code. But in each responseJSON I still have boilerplate to process my JSON response. They all look like these,
Check response.result.isSuccess
Check response.result.value as? the type data I expect (mostly a dictionary)
Check for the success indicator in dictionary
If succeed then retrieve the data I need.
And because I group the related calls in one URLRequestConvertible, their responses have the similar format that I actually have the 5th step to further retrieve the "real" data I am looking for.
So is there any way to reduce these boilerplate codes in responseJSON?
BTW, I actually come up with a kludge solution for it. But I was wondering is there any common practice for that?
I raised the same question at alamofire forum #2099 and got the answer to use ResponseSerializer
But after check the ResponseSerializer document I realize my home-made solution was not as crappy as I thought (using ResponseSerializer seems rather complicated)
So my solution is to add a static verify method to my Router and let it do the basic verification work (from Step #1 to Step #5)
static func verify(json:DataResponse<Any>, request:Router) -> result //needs the 2nd
parameter b/c is a static method
Now my calling method changed to these,
var result = CallResult.fail
Alamofire.request(Router.Callback(input))
.responseJSON { response in
result = Router.verify(json:response,request:Router.Callback(input))
}
.responseJSON { _ in //AS I already parsed response into my result
//process the result now
}
I'm just exploring using Alamofire and it is excellent but I'd like to do something that I feel is possible just not sure how.
Our authentication with the server uses one-time-use bearer tokens. So for every request made I have to store the new token sent down with that request.
What I'd like to do is intercept every response that comes back and check the Authorisation header. Save it to disk and then forward to the place waiting for the actual data.
Is this possible with Alamofire?
If so, please could you point me in the right direction.
Thanks
OK, after a bit of searching the github and head scratching I decided to create a new response serialiser by extending the Request type.
I created a new saveAuth() block like so...
extension Request {
public static func AuthSaver() -> ResponseSerializer<Bool, NSError> {
return ResponseSerializer { request, response, data, error in
guard error == nil else { return .Failure(error!) }
if let auth = response?.allHeaderFields["Authorization"] as? String {
Router.OAuthToken = auth // this uses a didset on the Router to save to keychain
}
return .Success(true)
}
}
public func saveAuth() -> Self {
return response(responseSerializer: Request.AuthSaver()) {_ in}
}
}
I can call it like...
Alamofire.request(Router.Search(query: query))
.validate()
.responseSaveAuth() // this line
.responseJSON {
response in
// ...
}
It still requires adding in each place that I want to strip out the newly sent auth token but it means I can choose when not to do it also and it's a single line of code.
It's maybe not the most elegant code in the extension (I'm still getting to grips with it all) but it makes it much easier to save the authentication each time.
I have solved this by only having one place in my app that sends network requests. Basically, I have a "network manager" that builds up NSURLRequests and pipes them to one function that actually sends the request (in my case it's an NSOperation sub class). That way I have only one location that I'm reading responses from.