func say(name:String, msg:String) {
println("\(name) say \(msg)")
}
say("Henry","Hi,Swift") <---- error because missing argument label 'msg' in call
I need to use
say("Henry",msg:"Hi,Swift")
Why ? If I put more than two var in func so that I need to write var name instead of first var when I call this func
It's really trouble, and I don't see any explain in iBook Swift tutorial.
One possible reason is that it is actually a method. Methods are very sneaky, they look just like regular functions, but they don't act the same way, let's look at this:
func funFunction(someArg: Int, someOtherArg: Int) {
println("funFunction: \(someArg) : \(someOtherArg)")
}
// No external parameter
funFunction(1, 4)
func externalParamFunction(externalOne internalOne: Int, externalTwo internalTwo: Int) {
println("externalParamFunction: \(internalOne) : \(internalTwo)")
}
// Requires external parameters
externalParamFunction(externalOne: 1, externalTwo: 4)
func externalInternalShared(#paramOne: Int, #paramTwo: Int) {
println("externalInternalShared: \(paramOne) : \(paramTwo)")
}
// The '#' basically says, you want your internal and external names to be the same
// Note that there's been an update in Swift 2 and the above function would have to be written as:
func externalInternalShared(paramOne paramOne: Int, #paramTwo: Int) {
print("externalInternalShared: \(paramOne) : \(paramTwo)")
}
externalInternalShared(paramOne: 1, paramTwo: 4)
Now here's the fun part, declare a function inside of a class and it's no longer a function ... it's a method
class SomeClass {
func someClassFunctionWithParamOne(paramOne: Int, paramTwo: Int) {
println("someClassFunction: \(paramOne) : \(paramTwo)")
}
}
var someInstance = SomeClass()
someInstance.someClassFunctionWithParamOne(1, paramTwo: 4)
This is part of the design of behavior for methods
Apple Docs:
Specifically, 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.
Notice the autocomplete:
This is simply an influence of the Objective-C language. When calling a method, the first parameter of a method does not need to be explicitly labelled (as in Objective-C it is effectively 'labelled' by the name of the method). However all following parameters DO need a name to identify them. They may also take an (optional) local name for use inside the method itself (see Jiaaro's link in the comments above).
Simple:
Wrong call function syntax's( its not same in c/c++/java/c#)
Incorrect:
say("Henry")
Correct:
say(name:"Henry")
PS: You must always! add "name function parameter" before value.
Swift 3.0 update:
In swift 3.0, methods with one param name per inputs are required to have that param name as part of the function call. So if you define the function like this
func say(name:String, msg:String) {
print("\(name) say \(msg)")
}
Your function call will have to be like this
self.say(name: "Henry",msg: "Hi,Swift")
If you want to have English like readable function labels but do not want to change input param name, you can add the label in front of the parameter names, like this
func say(somethingBy name:String, whoIsActuallySaying msg:String) {
print("\(name) say \(msg)")
}
Then calling it like this
self.say(somethingBy: "Henry",whoIsActuallySaying: "Hi,Swift")
This is a quirk in the compiler. Functions (which are not members of a class) and class methods have different default behavior with regards to named parameters. This is consistent with the behavior of named parameters in objective-C (but makes no sense for someone new to swift with no experience with objective-C).
Here's what the language reference has to say about named parameters for functions (specifically parameters where an external name for the parameter is not given, and the parameter does not have a default value)
However, these parameter names are only used within the body of the
function itself, and cannot be used when calling the function. These
kinds of parameter names are known as local parameter names, because
they are only available for use within the function’s body.
For information about class methods, see Logan's answer.
Please find the small code for understanding in swift 3+.
func sumInt(a:Int,b:Int){
print(a+b) // Displays 3 here
}
sumInt(a: 1, b: 2) // not like in other languages
Related
I wrote a function that takes a non-optional String as a parameter.
I declared a variable property of type String, which is also not an optional.
When I try to call my function with this property as an argument, I get the following error.
Cannot invoke 'localesForCountryCode' with an argument list of type '(String)'
Notice that the error lists the type as '(String)' not 'String'. What do the parens signify? I thought they meant that the type was optional, but nothing is declared as an optional anywhere.
My Function (An extension of NSLocale):
func localesForCountryCode(countryCode: String) -> [NSLocale] {
let localeIdentifiers = localeIdentifiersForCountryCode(countryCode)
var locales = [NSLocale]()
for localeIdentifier in localeIdentifiers {
let localeForIdentifier = NSLocale(localeIdentifier: localeIdentifier)
locales.append(localeForIdentifier)
}
return locales
}
Code That Calls My Function
let currentCountryCode = "US"
var localesForCurrentCountry = [NSLocale]()
func updateWithNewLocation(newLocation: CLLocation) {
geoCoder.reverseGeocodeLocation(newLocation, completionHandler: { (placemarks, error) -> Void in
if placemarks.count > 0 {
let placemark = placemarks.first as! CLPlacemark
self.currentCountry = placemark.country
self.localesForCurrentCountry = NSLocale.localesForCountryCode(self.currentCountryCode)
}
})
}
Update 1
When I move my function code from the NSLocale extension to the view controller from which I am calling the function, the error goes away. Any ideas why this may be the case? Absolutely no changes to the function were made.
Update 2
I continue to run into this problem. The following is another example. Again, it seems to happen only when a function is called as a class method.
I was rereading your question and realized that your question is not really your question. Your problem has nothing to do with parentheses (see below about why). You're just calling the wrong method. NSDateComponentsFormatter is a class. stringFromTimeInterval() is an instance method. You have to crate an actual date formatter to work with. If you want a default one, you can do this:
return NSDateComponentsFormatter().stringFromTimeInterval(unwrappedTimespan)
Note the extra set of parentheses. Your probably don't want the default one, though. You probably want to configure one. See Date Formatters for an introduction to that topic. Note that date formatters can be pretty expensive to create, so you usually want to reuse them.
You're doing the same thing with localesForCountryCode. This is an instance method, not a class method. You have to create an NSLocale first.
This does open up an interesting topic, though. Why does NSDateComponentsFormatter.stringFromTimeInterval() act like a function that you're just passing the wrong arguments to? Why doesn't it say "hey, you're calling a class method?" It's because it is a function that you're just passing the wrong arguments to.
Every method is really just a curried function that takes the target object as the first parameter. See Ole Begemann's quick intro to the topic: Instance Methods are Curried Functions in Swift.
Some more on your explicit question about parentheses:
As others have noted, a (String) is a one-tuple of String. The important point is that in Swift, any type is trivially convertible to a one-tuple of that type, so the extra parentheses here are unimportant. There is no meaningful distinction between String and (String) in Swift.
All Swift functions technically take one value and return one value. So one can correctly think of:
func f(x: Int, y: Int) -> Int
as a function that takes a tuple (Int,y:Int) and returns an Int (or possibly (Int); I believe Swift actually does the former, though). This is subtly connected to how currying works in Swift. In a simpler case:
func f(x: Int)
This is a function that technically takes (Int) and returns (). That's why sometimes you will see (Type) show up in error messages. But it is not a meaningful distinction.
String - it's simple String type.
But (String) - it's a compound type called Tuple.
That means you passing to you function Tuple, not String.
A compound type is a type without a name, defined in the Swift language itself. There are two compound types: function types and tuple types. A compound type may contain named types and other compound types. For instance, the tuple type (Int, (Int, Int)) contains two elements: The first is the named type Int, and the second is another compound type (Int, Int).
In general the error message says (String) because that is the tuple / list of parameters. If you method would expect a String and afterwards an Int an error message might mention (String, paramName: Int)
So basically so far everything looks fine. You need to show us the code for us to be able to fix your exact problem. Because String and (String) normally should match in the given scenario.
Consider the following example:
func k (a:String, b:Int) {}
k(12, b:"123")
which will cause the error
Cannot invoke 'k' with an argument list of type (Int, b:String)
While
k("12", b:123)
does what you would expect.
I am new in swift and I am following apples doc for studying it.
apple doc
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", day: "Tuesday")
I just copy above code from apple doc and try to run in playground but in last line its gives me syntax error and telling that remove day: in that.
When I am remove day: in fun calling its run perfectly
greet("Bob", "Tuesday")
Is there any mistake in apple doc or I am doing something wrong?
Naming the parameters of a function works different, depending on where the function is defined (and again different on initializers)
The way, you defined the function is global, outside of a class. In this case the function call does not name parameters.
If you would define the function inside a class, your first try would work perfectly fine. In functions inside a class (methods) you name the parameters except the first one. If you would like to have the first name, too, you would use
func greet(#firstParameter: String, secondParameter: String) ...
And to complete all that, initializers need all parameters named. Even the first one and even without the #.
Does all that sound a bit confusing? Well, Apple had the same opinion and according to what was said on WWDC 2015 they change the behavior in Swift 2 and make it more consistent.
These are Swift "functions" not "methods". They do not need parameter names. You can still add them in the declaration for readability, but you cannot use it while calling.
On the other hand, class "methods" are named and work as you expected.
If you still need named parameters while calling, try this:
func greet(name: String, #day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", day: "Tuesday")
This will give you expected results.
Find this in documentation:
However, these parameter names are only used within the body of the
function itself, and cannot be used when calling the function. These
kinds of parameter names are known as local parameter names, because
they are only available for use within the function’s body.
A note on methods and functions:
Simply put, methods belong to a class. Functions don't. From documentation:
Functions are self-contained chunks of code that perform a specific
task. You give a function a name that identifies what it does, and
this name is used to “call” the function to perform its task when
needed.
Note that Swift 2.0 makes no difference between method calls and function calls, so in Swift 2.0, your way is valid.
In function:
func greet(name: String, day: String) -> String {
}
"name" and "day" are variables not the label as in Obj C. You can write "day" as label as:
func greet(name: String, day day: String) -> String {
}
You have to understand that a new language like Swift is bound to change. This is one of those changes, it was introduced during WWDC 2015.
Apple has unified how you define and call functions and methods, so that the behaviour is the same. They completely removed the # from func definitions and made it a requirement that the name of the 1st argument of func be included in the name, and the all other arguments have the option of either having a name, or not.
These are examples of valid func declarations in Swift 2.0, which is to be released with Xcode 7 and iOS 9.
func moveShapeToPosition(position: CGPoint, andScaleBy scale: CGFloat)
func moveShapeToPosition(position: CGPoint, scale: CGFloat)
func moveShapeToPosition(position: CGPoint, _ scale: CGFloat)
And to call them.
moveShapeToPosition(CGPoint(x: 0, y: 0), andScaleBy: 1)
moveShapeToPosition(CGPoint(x: 0, y: 0), scale: 1)
moveShapeToPosition(CGPoint(x: 0, y: 0), 1)
It's the version of Swift made the difference.
I run the demo in Xcode 7.0 Beta, it works perfectly.
Besides, when I try to call greet like greet("Bob", "Tuesday") in Xcode 7.0 Beta, it gives me the error that the day: is missing.
However, when I run it in the Xcode 6.4, it complaints the same as yours.
In Swift, functions and methods are different. you can find detailed answer here.
You must be created function which means you may have created it inside Viewdidload(it's my guess). So you can't specifically give the function parameter name.
if you've created method (outside the viewdidload) then you can call like you've tried
greet("Bob", day: "Tuesday")
or
Check for Shorthand External Parameter Names for external parameter names.
This question already has answers here:
Function Parameter Names don't behave according to documentation
(2 answers)
Closed 7 years ago.
I'm new to Swift and I've read the Swift Function Documentation and as far as I understand a function has to be built this way:
func funcName(param1:Type, param2:Type) -> Return {
//Whatever istructions
}
And has to be called this way:
funcName(1, 2);
Very easy, and here is from the original Apple documentation:
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
println(halfOpenRangeLength(1, 10))
// prints "9"
So in this last example when calling the halfOpenRangeLength function I don't have to specify the name of the parameters (start and end).
So I did my function in XCode:
func assegnaRisposte(uno:String, due:String, tre:String, quattro:String){
button1.setTitle(uno, forState: UIControlState.Normal)
button2.setTitle(due, forState: UIControlState.Normal)
button3.setTitle(tre, forState: UIControlState.Normal)
button4.setTitle(quattro, forState: UIControlState.Normal)
}
But when I call it this way I get the error Missing argument lables 'due:tre:quattro:' in call:
assegnaRisposte("Davide", "Andrea", "Sergio", "Roberto")
And the XCode fix imposes me to do it this way:
assegnaRisposte("Davide", due: tre: "Andrea", "Sergio", quattro: "Roberto")
So I'M FORCED to place 3 of the parameter names. If I place the first parameter (uno) it throws an error, so I have to put ONLY due, tre and quattro
As far as I read I can specify the parameter names placing a dash in front of the parameter, and also, I'm not FORCED to use them.
Can somebody explain me why is this?
There is a difference between functions and methods in Swift in naming, basically:
the default naming of functions is that there are no external
parameter names.
the default naming for methods is that there are external
parameter names expect the first parameter.
And you can read about the differences between methods and functions here or here.
Updated:
If you don't want to use external parameter names, you should declare your method like:
func assegnaRisposte(uno:String, _ due:String, _ tre:String, _ quattro:String){
...
}
Check out this section from Apple's The Swift Programming Language book:
Local and External Parameter Names for Methods
The default behavior of local names and external names is different
for functions and methods.
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.
I try to understand the main concept of callbacks in swift
I have the following code:
typealias ImageHandler = (String,NSError?) -> Void
func PostOnSocialMedia(image:String?){
println(0)
Post({(image)->Void in
println(1)
})
println(2)
}
func Post(handler:ImageHandler){
println(3)
}
my code output is 0,3,2 and my question is why doesn't print the number 1.
It’s not printing 1 because you are passing in a function that is never called.
This:
Post({ (image)->Void in
println(1)
})
declares a temporary function (a “closure expression” – a quick easy way to declare anonymous functions, between the { }) that takes an argument of a (String,NSError?) pair, and returns nothing. Then it passes that function into the Post function.
But the Post function does nothing with it. For a function to run, it needs to be called. If you changed your Post function like so:
func Post(handler:ImageHandler){
println(3)
// call the handler that was passed in...
handler("blah",nil)
}
you’ll see it printing a 1.
Note, the image argument received by PostOnSocialMedia and the image argument variable inside the temporary function are two different variables – scoping rules mean the one declared inside the temp function masks the one in the outer scope. But they are very different (in fact, they’re different types – one is a string, and the other is a 2-tuple of a string and an error).
Try reading this for a short intro on first-order functions and closures in Swift.
I am learning swift from apple book. while writing code in xcode, I am getting error that parameter missing form function.
according to Apple code should be
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
while calling this function :
println(halfOpenRangeLength(1, 10)) // According to Apple.
but when I type above line it says insert end
so this statement changes to
println(halfOpenRangeLength(1, end:10))
why this happens?
Thanks
Swift always gives the first parameter a local parameter name and no external parameter name. This means you don't need to call it when you use the method.
After that, every parameter is given both a local and external parameter name. This is meant to be for clarity's sake. As Leonardo said, you can avoid having to name the second parameter by placing an underscore (_) in front of the parameter name.
In case you ever want to, you can also provide an external parameter name for the first variable by placing a hashtag (#) in front of the parameter name.
You can check out more information about this in Apple's Swift Documentation: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
use this instead I've checked it and it works
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
println("\(halfOpenRangeLength(1, 10))")
If you don't want it to require the argument name you just need to add _ in front of it and it will not bug you about it anymore:
vv
func halfOpenRangeLength(start: Int, _ end: Int) -> Int {
Swift gives automatic external names to parameters following these rules:
global functions: no automatic external names
class/struct/enum methods: automatic external names for all parameters but the first
initializers: automatic external names for all parameters
That said, if it doesn't work in your case, requiring you to specify the external name for the 2nd parameter, than it probably means you've declared that function as a class or struct method, not as a global function.