Swift required parameter logic - swift

In Swift you've got many possible ways to declare a method. You can use the # and _ sign to enforce using parameter names and you can also change the external definition of a parameter.
Somehow the compiler creates an error message for the following method:
func createCoffee(withSugar sugar:Bool, andMilk milk:Bool){
}
// Where I want to call it like this:
createCoffee(withSugar:true, andMilk: true)
Enforcing me to declare the method as followed:
func createCoffee(# sugar:Bool, andMilk milk:Bool){
}
// Resulting in the following way to call it
createCoffee(sugar:true, andMilk: true)
A strange thing in this, declaring the method as followed will not result in this enforced com
func createCoffee(firstParam sugar:Bool, andMilk milk:Bool){
}
// Resulting in the following way to call it
createCoffee(firstParam:true, andMilk: true)
In which way does the compiler decide to allow a different external parameter name?

External parameter names are used for greater description. Having the external parameter name as "with_____" makes Swift and XCode see it as redundant. The first parameter technically would always be "with___ interal parameter name ". It is purely for syntactical reading ease.

Related

What does _: mean in Swift?

So I was doing some reading, and I wanted to know what the following meant. Let's say for instance in Swift, you have a method like recordResponse(_:) what does the parameter mean?
I'm working with MVCs and was doing an exercise in a book that had that preset parameter. In the model, I'm supposed to use that method to record a passed answer of "true" or "false" (obviously a string not a boolean), to indicate that a current response was given from a method "currentQuestion".
The exercise in the online book also states that the same method recordResponse(_:) should check if the answer given from the question currentQuestion() method is correct or not.
It's a way of stating the name of the function. The function might be declared like this:
func recordResponse(s:String) {
// ...
}
Now, by default, the s is an internal parameter name only; the external parameter name is suppressed. So we need a notation that describes the function, recordResponse, as taking one parameter with no external name. That notation is recordResponse(_:). The colon follows each parameter name — here there is only one parameter, and has no external name, which is what the underscore indicates.
In the usage you are asking about, this notation is just that: a notation. It's a convention for giving the name of the function in a complete way, when humans talk to humans (as in a tutorial). But in Swift 2.2, this notation will become very important, because it will be part of the language — it's how you'll form a function reference. That is, it will be Swift's own name for the function.
I am giving a example for this
func test()
{
let strOne : String = "hello"
let _ : String = "Linuxn00b"
print(strOne)
}
in let strTwo line xcode produce a warnig that Having an "_" the "named parameter" will be explicitly unused.Happy coding .

What is _: in Swift telling me?

What does the lone underscore mean in function definitions?
e.g. map(_:)
I understand that when defining functions I can do:
func myFunc(_ string: String) { ... }
Would I then refer to that as myFunc(_:) instead of myFunc(_string:), i.e. purposefully hiding the parameter name?
The _ is used to define that the parameter is not named
If you have multiple _ it states that you do not need to name the parameters in your function call
func myFunc(name:String, _ age:String){
}
myFunc(“Milo", "I'm a really old wizard")
If you do not use the underscore you would use
myFunc(“Milo”, age: "I'm a really old wizard")
The _ is not necessary for function calls. It is just used to indicate that something does not need to have a name.
In regards to how you would refer to your function, You would not have to pass any name for the function call.
But since you also don’t define a parameter type this seems to me like an invalid example (it at least doesn’t work in Xcode 7 with Swift 2.0)
Edit:
Since Swift 3.0
myFunc(name: “Milo”, age: "I'm a really old wizard")
Should be used
Swift needs a convention for saying what the name of a function is, including not only the function name itself (before the parentheses) but also the external names of the parameters. The convention is that the names are followed by colons. So here's a function declaration (in Swift 2.0):
func myFunc(param1 param1:String, param2:String, param3:String) {}
And here is that function's name:
myFunc(param1:param2:param3:)
In real life, however, it is possible (indeed likely) that one or more parameters will not externalize any name. Thus we need a placeholder for that name. The underscore is that placeholder - just as the underscore is the symbol in the declaration suppressing externalization of the name. So, here's another function declaration (in Swift 2.0):
func myFunc2(param1:String, _ param2:String, _ param3:String) {}
And here is that function's name:
myFunc2(_:_:_:)
[The Swift 2.0 spec is important here. In Swift 2.0, the first param name is always not externalized by default, and the other param names are externalized by default. In Swift 1.2 and before, the externalization rules depended on where the declaration appeared, which was unnecessarily inconsistent and confusing.]
When referring to a function, in order to disambiguate it is necessary to provide the function name along with the external names of any parameters that it expects.
For example,
func myFunc(myString string: String) { ... }
and
func myFunc(_ string: String) { ... }
represent two different functions, one where an external label is provided for the first String parameter when the function is called and the other where no label is used, as in:
myFunc(myString: "hi")
and
myFunc("hi")
So, in order to identify a function we include the external label for each parameter where ':' indicates that a parameter is to be provided - e.g. yourFunc(arg1:arg2:) will take 2 arguments.
When no external label is used, we place an underscore ('_').
For the 2 functions given above, we would uniquely identify them using:
myFunc(myString:) and myFunc(_:)

Create and run a Selector with several parameters for class functions

I have a situation where I use a class to do a number of conversions with a large number of rules which have the general form of:
private class func rule0(inout account: String, _ version: Int) -> String? {
return nil; // Use default rule.
}
The function names just increase the rule number: rule1, rule2 etc...
I get the rule number from an external source and now want to find a generic way to call the right rule function depending on the given rule number. I could use a big switch statement, but I'm more interested in generating a selector from a string and call that.
My attempts led me to:
let ruleFunction = Selector("rule\(rule):_:");
let result = ruleFunction(&account, version);
but that only causes this error on the second line:
'(inout String, #lvalue Int) -> $T4' is not identical to 'Selector'
What is the right way to accomplish that? And btw, what means "$T4"? That error message is hard to understand, to say it friendly.
Additional note: I'm aware of approaches using a timer or detouring to Obj-C, but am rather interested in a direct and pure Swift solution. How is the Selector class to be used? Can it be used to directly call what it stands for? How do classes like NSTimer use it (detour to Obj-C?)?
A couple of approaches that don't use Selector. If all of the "rules" have the same signature, then you could either put them in an array, with the index of the function in the array indicating the rule number, like this:
let functionArray = [rule0, rule1, rule2, rule3] // etc...
Then, when it is time to call the function, you just access the one you want with a subscript:
let result = functionArray[ruleNumber](account, version)
You could do the same thing with a dictionary that looked something like this:
let functionDict = ["rule0": rule0, "rule1": rule1] // etc...
And then get the function using the string value that you create when you get the rule number from your external source:
let result = functionDict["rule\(ruleNumber)"]?(account, version)
The dictionary approach would work better if you weren't able to guarantee that rule0 would always be at index 0 in the array.
A caution, though: I have tried this and I've been able to get it to work without the inout keyword, but not with it. I don't know if it is a bug, or what, but Swift doesn't seem to want to let me create arrays or dictionaries of functions that take inout parameters.
If you absolutely require the inout parameter for your function to work, then my suggestion won't help. If there is a way to do what you want without the inout, then this might be the solution for you.

Swift method parameters, not always named?

Trying to do a basic web view app for experimenting, I ran into the loadRequest method. Methods with swift accept the named parameters, however loadRequest does not. Just wondering on the reasoning for this? I found the inconsistency kind of odd.
import UIKit
class ViewController: UIViewController {
#IBOutlet var webView: UIWebView
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "http://en.wikipedia.org")
let request = NSURLRequest(URL: url)
self.webView.loadRequest(request)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The parameters in standalone functions and instance methods in a class are handled differently. The Swift book has this to say about it:
“Swift gives the first parameter name in a method a local parameter
name by default, and gives the second and subsequent parameter names
both local and external parameter names by default. This convention
matches the typical naming and calling convention you will be familiar
with from writing Objective-C methods, and makes for expressive method
calls without the need to qualify your parameter names.”
An example:
class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes: Int) {
count += amount * numberOfTimes
}
}
var myCounter = Counter()
myCounter.incrementBy(3, numberOfTimes: 4)
println(myCounter.count) // 12
There are somewhat complicated rules around what the default behavior is for named parameters. However, they are all centered around the idea of making Swift method calls read the same way that Objective-C method calls are read. There are two types of names for each parameter: external and internal. External names are used when calling the function / method / initializer, and internal names are used only within the implementation of the function / method / initializer.
With initialization methods, the "initWith" is left off but otherwise it is the same. So ---[NSURL initWithString:] becomes NSURL(string:).
initializers do not have an identifying function name before their
parentheses in the way that functions and methods do. Therefore, the
names and types of an initializer’s parameters play a particularly
important role in identifying which initializer should be called.
Because of this, Swift provides an automatic external name for every
parameter in an initializer if you don’t provide an external name
yourself
All other methods are defaulted to not name the first parameter but name all of the following parameters.
Swift gives the first parameter name in a method a local parameter
name by default, and gives the second and subsequent parameter names
both local and external parameter names by default. This convention
matches the typical naming and calling convention you will be familiar
with from writing Objective-C methods, and makes for expressive method
calls
Functional calls have a 3rd rule applied to them. They default to not have any external name.
If you want users of your function to provide parameter names when
they call your function, define an external parameter name for each
parameter, in addition to the local parameter name. You write an
external parameter name before the local parameter name it supports

What is the usecase for ignored parameters in Swift

In Swift, you can write the following:
func foo(_:Int) -> { return 1 }
Where the underscore is an ignored parameter. I only know this because of the documentation, but cannot think of ANY usecase on why you would even do this. Am I missing something?
Ignoring parameters (or members of a tuple, which are pretty close to the same thing) makes sense when:
You're overriding a superclass function or implementing a function defined by a protocol, but your implementation of that function doesn't need one of the parameters. For example, if you hook app launching but don't need a reference to the shared UIApplication instance in that method:
override func application(_: UIApplication!, didFinishLaunchingWithOptions _: NSDictionary!) -> Bool { /* ... */ }
You're providing a closure (aka block in ObjC) as a parameter to some API, but your use of that API doesn't care about one of the parameters to the closure. For example, if you're submitting changes to the Photos library and want to throw caution to the wind, you can ignore the success and error parameters in the completion handler:
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
// change requests
}, completionHandler: { _, _ in
NSLog("Changes complete. Did they succeed? Who knows!")
})
You're calling a function/method that provides multiple return values, but don't care about one of them. For example, assuming a hypothetical NSColor method that returned components as a tuple, you could ignore alpha:
let (r, g, b, _) = color.getComponents()
The reasoning behind this is that it makes your code more readable. If you declare a local name for a parameter (or tuple member) that you don't end up using, someone else reading your code (who could well be just the several-months-later version of yourself) might see that name and wonder where or how it gets used in the function body. If you declare upfront that you're ignoring that parameter (or tuple member), it makes it clear that there's no need to worry about it in that scope. (In theory, this could also provide an optimization hint to the complier, which might make your code run faster, too.)
Perhaps you're overriding a method and your override ignores one of the parameters? Making it clear that you're ignoring the parameter saves future coders from having to look through your code to work out that it's not using the parameter and makes it clear that this was intentional. Or maybe it's to create some sort of Adapter pattern where you make it clear that one of the parameters is being ignored.