how to call a function with success and failure? - ios

I've got a function:
func retrieveArticleWithTopic(topicId id: String, success: ([Newsfeed] -> Void), failure: (NSError -> Void)) {
client.fetchEntries(["content_type": ContentType.Article.rawValue, "include": 10]) { (results) in
// TODO: some more code will go here
var feeds = [Newsfeed]()
success(feeds)
}
}
Which I need to pass a ID as a string to. Im struggling to call this function and pass values to it. I've tried:
ContentManager().retrieveTopics(TopicID:"Hello")
But I get an error that reads Missing argument for parameter failure in call.
How do pass a string to this function?

The success and failure parameters are required (they don't have default values). You must pass two blocks:
retrieveTopics(topicID: "hello", success: { newsfeeds in
print("retrieved \(newsfeeds)")
}, failure: { error in
print("error: \(error)")
})

You should call like this:
retrieveArticleWithTopic(topicId: "", success: { (newsfeeds) in
}) { (error) in
}
Or you don't want to handle success or failure, you can make it optional.
func retrieveArticleWithTopic(topicId id: String, success: ([Newsfeed] -> Void)?, failure: (NSError -> Void)?) {
}
retrieveArticleWithTopic(topicId: "", success: nil, failure: nil)

Related

How to call a method which takes a closure as a parameter in Swfit?

I try to write a method as below:
class ThisIsExample{
func theMethod(inside:((Error?)->Void)->Void){
//some implementation
}
}
But, when I try to call this method, I don't know how to do that.
I wrote code below:
let example = ThisIsExample()
example.theMethod { ({(err) in }) in
print("print something")
}
I try to write another closure, which is { (err) in } inside the closure
But it is not workable, I'll receive error message like
Contextual closure type '((Error?) -> Void) -> Void' expects 1
argument, but 0 were used in closure body
So...could anyone please teach me how to call this method in correct way, thank you so much.
Although not sure what is the purpose of nested closure. But if you want to use this approach then you should call the closure in this way,
example.theMethod { (closure) in
closure(NSError.init())
}
You can do some thing like this:
func theMethod(inside:(Error?) -> ()) {
print("Closure as paramater")
}
This will take Error as closure parameter and return void.
you can call this function as below:
theMethod { (error) in
}
Something Like This
class NewClass
{
class func myCustomFunc(_ parameter1: String, parameterDict : [String : AnyObject]?, success:#escaping (String) -> Void, failure:#escaping (String) -> Void)
{
/// Just example Bool
var result : Bool = false
/// Get the parameter you sent while calling this Clousure block
let myParamString = parameter1
let paramDict = parameterDict
/// Share the output in case of Success and Failure
if (result){
success("success")
}
else{
failure("Failure")
}
}
}
Usage
NewClass.myCustomFunc("demoStr", parameterDict: [:], success: { (succesString) in
if succesString == "success"{
}
}) { (failureStr) in
if failureStr == "failure"{
}
}
This Function Accepts Parameter and Also give Different blocks depend upon closures

Swift 2 - Extra argument in call

I've created a error handling class, which is suppose to make my calls easier, however i keep getting an error Extra limit argument in call. I've double checked that their is 7 arguments in both, how come i get this error?
Class
class GetOrganization {
func request(
lastPage: Int?,
limit: Int,
location: CLLocation,
radius: Int?,
success successCallback: (JSON) -> Void,
error errorCallback: (statusCode: Int) -> Void,
failure failureCallback: (error: Error) -> Void
) {
Provider.request(.Organizations(lastPage, limit,location.coordinate.longitude, location.coordinate.latitude, radius)) { result in
switch result {
case let .Success(response):
do {
try response.filterSuccessfulStatusCodes()
let json = try JSON(response.mapJSON())
successCallback(json)
}
catch {
errorCallback(statusCode: response.statusCode)
}
case let .Failure(error):
failureCallback(error: error)
}
}
}
}
*Where i get the error**
GetOrganization.request(
lastPage: lastPage,
limit: limit,
location: location,
radius: nil,
success: { data in
}, error: { err in
print(err)
}, failure: { faillure in
// oh well, no network apparently
})
It is not a static function, so you can't call it like GetOrganization.request. Either set the func request as static func request or create an object and access it via that object.

Enum within a class as argument

I'm building a class to act as my API helper and I've nested an enum inside my class to show the response state:
class API {
enum Response {
case Success, Error, ServerError, ClientError
}
func load(handleResponse ((API.Response, JSON?) -> Void)) {
// Load in data with Alamofire
// Call handleResponse(.Success, data) at some point
}
}
To use my API, I am trying to write something like the following:
API.load { (status: API.Response, data: JSON?) in
...
}
I'm getting an error as follows with my code above:
Cannot convert value of type '(API.Response, JSON?) -> ()' to expected argument type 'API'
It seems like the '.' in the type is a problem, but I'm not sure how to fix it.
Please try this
class API {
enum Response {
case Success, Error, ServerError, ClientError
}
class func load(handleResponse: ((API.Response, JSON?) -> ())) {
}
}
API.load { (response, json) -> () in
}

Can swift closures be set to a default value when used as a parameter in a function?

A pretty handy feature of Swift functions is that function parameters can have default values:
func someFunction(parameterWithDefault: Int = 42) {
//if no arguments are passed to the function call,
//value of parameterWithDefault is 42
}
If a parameter is a closure, is there a way to make it have a default value? See the example below:
func sendBody(
body: NSData? = nil,
success: (data: NSData) -> Void,
failure: (data: NSData?) -> Void) {
}
Is there a way to not force the developer to pass a value for success or failure when calling sendBody?
Yes, functions are just values, so you can supply them as defaults
// just to show you can do it with inline closures or regular functions
func doNothing<T>(t: T) -> Void { }
func sendBody(
body: NSData? = nil,
success: (data: NSData) -> Void = { _ in return },
failure: (data: NSData?) -> Void = doNothing
)
{ }
Alternatively, you could make them optional, that way you can detect if the caller passed one:
func sendBody(
body: NSData? = nil,
success: ((NSData) -> Void)? = nil,
failure: ((NSData?) -> Void)? = nil
)
{ success?(NSData()) }
sendBody(success: { _ in print("ah, yeah!") })
Also worth noting if you’re doing this: if the caller uses the trailing closure syntax, this will be the last closure in the argument list. So you want the last one to be the one the user is most likely to want to supply, which is probably the success closure:
func sendBody(
body: NSData? = nil,
success: ((NSData) -> Void)? = nil,
failure: ((NSData?) -> Void)? = nil
)
{
if success != nil { print("passed a success closure") }
if failure != nil { print("passed a failure closure") }
}
// this prints "passed a failure closure"
sendBody { data in
print("which closure is this?")
}
Other than this, the order in the function declaration doesn’t matter to the caller – defaulted arguments can be supplied in any order.
You could do something like this,
let defaultSuccess: NSData -> Void = {
(data: NSData) in
}
let defaultFailure: NSData? -> Void = {
(data: NSData?) in
}
func sendBody( body: NSData? = nil, success: (data: NSData) -> Void = defaultSuccess, failure: (data: NSData?) -> Void = defaultFailure) {
}
Then, you may be able to call either one of these methods. Notice sendBody which is called with default parameters.
sendBody()
sendBody(body: , success: , failure: )
You can also call with all the variants like passing just one of the argument in the above method, for that you have to call it with named parameter.
sendBody()
sendBody(body:)
sendBody(failure: )
sendBody(success:)
sendBody(body: , success: , failure: )
How to set a default value for a function parameter. Swift 4 and (probably) 5.
func someFunction(age: Int, doSomething:#escaping () -> Void = {}){
//do work here
//
doSomething()
}
Then you can do this
someFunction(age: 18) {
print("hello")
}
someFunction(age: 19)
You may or may not need to use the #escaping keyword. See Swift #escaping and Completion Handler for that.
My preferred way to specify public facing closures - in particular completion closures which you might want to store somewhere for later - is to define a typealias for them, like this:
public typealias FooCompletion = (String) -> Void
Then in the public facing function you can easily make it optional like this:
var onCompletion: FooCompletion? = nil
public func foo(completion: FooCompletion? = nil) {
// Store completion for later
onCompletion = completion
}
The completion parameter is optional, so it's allowed to be nil, and the default value is nil, meaning the caller doesn't have to specify it. Also, because you use the type in more than one place, if you need to change its definition during development there's only one place to do so. It's easy to call too:
private func someBackgroundThing() {
var completionString = "done"
...
onCompletion?(completionString)
}

SWIFT IOS return 2 different objects in a same function

I want to return request if all went well and return error if something went wrong.
func afnwPost(url: String,client_id: String, client_secret:String,grant_type:String, userparam: String, passwordparam:String)-> AnyObject{
var parameters = ["client_id":client_id,"client_secret":client_secret,"grant_type":grant_type,"username":userparam,"password":passwordparam]
manager.POST( url,
parameters: parameters,
success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
return responseObject
},
failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
println("Error: " + error.localizedDescription)
return error
})
}
The call method
var respuesta = obtenerToken.afnwPost(host_oauth,
client_id: client_id,
client_secret:client_secret,
grant_type:grant_type_token,
userparam: textfieldUsuario.text,
passwordparam: textfieldContrasenya.text)
You can return two different objects by using a Tuple like that:
//Dummy method to show how it works.
func yourFunction()->(responseObject:AnyObject, error:String){
return (responseObject, error)
}
To access them again, do something like that:
var yourResult = yourFunction()
println(yourResult.responseObject)
println(yourResult.error)
Of course you will have to check, which value is nil when you receive the returns of your function.

Resources