onkar onkar - 3 months ago 14
Swift Question

How to create a dictionary having string and function as key value pair in swift

I am looking to create a dictionary that will have

let urlDict:[String:Func] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]

func getLoginURL() -> String{
if (sandbox == true){
return sb_login_url
}else{
return live_login_url
}
}


func getResetPasswordURL() -> String{
if (sandbox == true){
return sb_reset_url
}else{
return live_reset_url
}

}


The purpose of this dict is to get/map functions based on the
KEY
and as per
KEY
corresponding function must be called which in turn will return return urls.

I have tried naming the dictionary but I am unable to do it

let urlDict:[String:Func] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
let urlDict:[String:Function] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
let urlDict:[String:Functions] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]


EDIT 1

class Constants{
private let sb_login_url = "http://IP_ADDRESS_COM/login_with_credentials"
private let live_login_url = "http://google.com"


private let sb_reset_url = "http://IP_ADDRESS_COM/forgot_password"
private let live_reset_url = "http://google.com"


func getLoginURL() -> String{
if (sandbox == true){
return sb_login_url
}else{
return live_login_url
}
}


func getResetPasswordURL() -> String{
if (sandbox == true){
return sb_reset_url
}else{
return live_reset_url
}

}
` let urlDict: [String: () -> String] = ["LOGIN": Constants.getLog‌​inURL(), "RESET":Constants.getResetPasswordURL()]

if let getFunc = urlDict[url_key] {
let url = (getFunc()) // foo}


}

Answer

You must specify the type of the functions (which are common for both getLoginURL and getResetPasswordURL) for the value slot in the dictionary, namely () -> String, a zero-arguments function returning a String instance.

func getLoginURL() -> String {
    return "foo"
}

func getResetPasswordURL() -> String {
    return "bar"
}

let urlDict: [String: () -> String] = 
    ["LOGIN": getLoginURL, "RESET":getResetPasswordURL]
/*            ^^^^^^^^^^^- note that you do not _call_ the functions,
                           as this would result in a String instance */ 

// get a function reference from the dictionary and invoke it
if let getFunc = urlDict["LOGIN"] {
    print(getFunc()) // foo
}

After your comments below, as well as your edit, it seems you want the get... functions to be class members if your class Constants (i.e., marked static).

class Constants {
    static var sandbox = true
    // I've just added this to test your example

    private static let sb_login_url = "http://IP_ADDRESS_COM/login_with_credentials"
    private static let live_login_url = "http://google.com"

    private static let sb_reset_url = "http://IP_ADDRESS_COM/forgot_password"
    private static let live_reset_url = "http://google.com"

    static func getLoginURL() -> String {
        if (Constants.sandbox == true){
            return Constants.sb_login_url
        } 
        else {
            return Constants.live_login_url
        } 
    }

    static func getResetPasswordURL() -> String{
        if (Constants.sandbox == true){
            return Constants.sb_reset_url
        } 
        else {
            return Constants.live_reset_url
        }
    }
}

let urlDict: [String: () -> String] = 
    ["LOGIN": Constants.getLoginURL, "RESET": Constants.getResetPasswordURL]

// get a function reference from the dictionary and invoke it
if let getFunc = urlDict["LOGIN"] {
    print(getFunc()) // http://IP_ADDRESS_COM/forgot_password
    Constants.sandbox = false
    print(getFunc()) // http://google.com
}