Swift gives syntax error while func calling - ios

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.

Related

Xcode 8 :function types cannot have argument label breaking my build

It seems that for some reason Swift have chosen to make coding in it less readable by forcing users to remove completion handler parameter labels. I have read the Swift discussion and still think it's a mistake. At least they could have made it optional.
When building using Xcode 8 - is there a way to force the compiler to use Swift 2.3 so I don't get these errors anymore?
I have updated the option to use legacy Swift (under build settings)
but I still seem to get this error:
Function types cannot have argument label 'isloggedIn'; use '_'
instead
How can I keep my labels in my completion handlers?
The Swift designers decided to prohibit argument labels for function types.
The reasoning is explained here: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
This is a frustrating and questionable choice, as prohibiting argument labels makes it much easier to incorrectly invoke closures, which seems more important than simplifying the language's type system.
Usability > ideology.
A workaround to consider. You can't do:
func doStuff(completion: (foo: Int, bar: String) -> Void) {
...
completion(foo: 0, bar: "")
}
... but you can do:
func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
...
completion((foo: 0, bar: ""))
}
i.e. have a single unnamed argument to your closure which is a tuple, in this case (foo: Int, bar: String).
It's ugly in its own way, but at least you retain the argument labels.
Based on the information above - it appears that the only way to really fix this and ensure that its performant is to raise a proposal to
Make argument labels optional with a view to :
improving the speed of development ( without argument labels it requires us to scroll up to the top of the method each time we put in the completion handler.
Reduce Errors : ( I have already had several errors caused due to incorrect completion handler entries especially with those that expect boolean values)
Make code more readable across team members. Not everyone has only one team member and thus being able to easily pick up other peoples code is a must have.
Lastly good programming practice means that the solution should look as much like the actual item being developed. completionhandler: (newvalues, nil) looks less like the item being managed than completionhandler(results: newValue, error:nil)
I would love for people reading this to share their feedback/ comments
on this below before I submit it so I can show there are others that
support this.
Edit:
I have submitted the pitch here :
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html
which appears to have been agreed. It looks like its going to happen, however the discussion is whether this is submitted as a Swift 4 improvement ( highly probable)
You have to use _ to make your parameters unnamed, and that is unfortunate. Instead of tacking _ on to each parameter and then blindly calling your function I would suggest making a wrapper object.
Since losing named parameters for function types introduces more risk that you will call the function with the wrong values, I would suggest wrapping the parameters in a struct and having that be the one and only parameter to your function.
This way the fields of you struct are named, and there is only one type of value to pass into your function. It is more cumbersome than if we were able to name the parameters of the function, but we can't. At least this way you'll be safer and you'll feel less dirty.
struct LineNoteCellState {
var lineNoteText: String?
var printOnInvoice = false
var printOnLabel = false
}
Here is an example of it being used:
cell.configure(editCallback: { (_ state: LineNoteCellState) in
self.lineNoteText = state.lineNoteText
self.printOnInvoice = state.printOnInvoice
self.printOnLabel = state.printOnLabel
})
Semi-workaround, note the _
completion: (_ success: Bool) -> Void

What is the difference between '(String)' and 'String' in a Swift error message

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.

Forced to use parameter names, but only some of them [duplicate]

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.

syntax error for function-- missing parameter

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.

Swift : missing argument label 'xxx' in call

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

Resources