1

I have a method definition in a swift project:

class func fireGetRequest(urlString: String!, username: String?, password: String?, completionBlock:(NSDictionary)->Void) {
    //check if user passed nil userName
    if username == nil || password == nil {
        // retrieve userName, password from keychain
        // here we have OR check since we have single value from pair it is of no use and can be considered as corrupted data
        // so it is better to retrieve stable data from keychain for further processing
        let (dataDict, error) = Locksmith.loadDataForUserAccount(kKeychainUserAccountName)

        // no error found :)
        // use data retrieved
        if error == nil {
            username = dataDict[kKeychainUserNameKey]
            password = dataDict[kKeychainUserPwdKey]
        }
    }

    // do something with username, password
}

Here I am doing following things:

  1. Checking if any of username, password is nil or not
  2. If any of those is nil then trying to set respective values from a dictionary

Problem is - I am clueless on resolving below errors:

enter image description here

Similar method in objective-c works perfectly:

+ (void)fireGetRequestWithUrlString:(NSString *)urlString userName:(NSString *)username userPwd:(NSString *)password{
    NSDictionary *dataDict = @{kKeychainUserNameKey: @"Some user name", kKeychainUserPwdKey: @"Some password"};

    if (!username || !password) {
        username = dataDict[kKeychainUserNameKey];
        password = dataDict[kKeychainUserPwdKey];
    }

    // do something with username, password
}

Any ideas?

Update 1:

As suggested in answers I declared function parameters- username and password as var but then I started getting these compilation errors:

enter image description here

To resolve this I did type casting but again another error:

enter image description here

On force downcasting, below error:

enter image description here

Still clueless :(

Finally solved :)

if let dataDictionary = dataDict {
                    username = dataDictionary[kKeychainUserNameKey] as! String?
                    password = dataDictionary[kKeychainUserPwdKey] as! String?
                }
Devarshi
  • 16,440
  • 13
  • 72
  • 125

2 Answers2

8

Function parameters are constants by default.

Define the mutable parameters explicitly as var

Swift 2

class func fireGetRequest(urlString: String!, var username: String?, var password: String?, completionBlock:(NSDictionary)->Void) 

Swift 3

class func fireGetRequest(urlString: String!, username: String?, password: String?, completionBlock:(NSDictionary)->Void){
   var username = username
   var password = password
   //Other code goes here
}
Chanchal Raj
  • 4,176
  • 4
  • 39
  • 46
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thanks for your answer, I tried as suggested but was again caught in compilation error, please see my updated question. – Devarshi Aug 29 '15 at 07:44
  • as both `username` and `password` are optionals, just downcast optional to String `username = dataDict[kKeychainUserNameKey] as? String`. If the dictionary contains the appropriate key, you get an optional string otherwise `nil` – vadian Aug 29 '15 at 07:56
  • thanks for guiding me in correct direction, I was finally able to resolve the sequence of compilation errors, I will accept your answer :) – Devarshi Aug 29 '15 at 08:01
  • with you "solved" syntax you still get a runtime error if the dictionary doesn't contain one of the keys and `as! String?` is a confusing syntax. Either cast optional `as?` or forced `as!`, but omit the question mark after the type, in both cases on success the resulting type is the type of the target variable – vadian Aug 29 '15 at 08:05
2

You should declare the username and password as var. The default is let.

class func fireGetRequest(urlString: String!, var username: String?, var password: String?, completionBlock:(NSDictionary)->Void) {
    // ...
}

See also: The Swift Programming Language: Functions

Constant and Variable Parameters

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

However, sometimes it is useful for a function to have a variable copy of a parameter’s value to work with. You can avoid defining a new variable yourself within the function by specifying one or more parameters as variable parameters instead. Variable parameters are available as variables rather than as constants, and give a new modifiable copy of the parameter’s value for your function to work with.

Community
  • 1
  • 1
Bannings
  • 10,376
  • 7
  • 44
  • 54
  • Thanks for your answer, I tried as suggested but was again caught in compilation error, please see my updated question. – Devarshi Aug 29 '15 at 07:44