This question already has answers here:
Why does a function call require the parameter name in Swift?
(6 answers)
Closed 8 years ago.
I was following optional values tutorial, in which we have following method
func findIndexOfString (string : String, array : String[]) -> Int?{
for (index, value) in enumerate(array){
if(value == string){
return index
}
}
return nil
}
however if i call this method by
let indexFound = findIndexOfString("myString", neighbour) //neighbour is array of String
give error that "Missing argument label ''array" in call , means i have to call this by
let indexFound = findIndexOfString("myString", array:neighbour)
Is it made compulsory to mention argument label in call?
Yeah. It is compulsory for for class methods. You should use the parameter names except for the first parameter. There comes the difference between the class methods and functions, for functions you will not use(You cant unless function defines an external parameter name) the parameter names.
Related
Recently I saw the following code line in a book (about CoreData)
return modelURLs(in: modelName).compactMap(NSManagedObjectModel.init)
I know what the code does but the question is: Why and how does it work?
There should be a closure as the argument of the compactMap function but there's only a "NSManagedObjectModel.init" in NORMAL parenthesis. What's the secret about it? What is it doing there? I would understand it if there's a static/class property called init which returns a closure but I don't think there is.
Unfortunately the book doesn't say more about this line of code. I would like to have further readings from the apple docs but I can't find anything. When I make a google search about "init in closures" then I don't get helpful results.
So you guys are my last hope :)
By the way: the function modelURLs(in: modelName) returns an Array of URLs but that's not really important here.
When using closures different syntax can be used as in the below example that converts an int array to a string array
let array = [1, 2, 3]
The following calls to compactMap will all correctly convert the array and generate the same result
let out1 = array.compactMap({return String($0)})
let out2 = array.compactMap({String($0)})
let out3 = array.compactMap {String($0)}
let out4 = array.compactMap(String.init)
When there are two init methods that takes the same number and types of argument then you must add the full signature for the init method to use. Consider this simple example struct
struct TwoTimesInt: CustomStringConvertible {
let value: Int
let twiceTheValue: Int
var description: String {
return "\(value) - \(twiceTheValue)"
}
init(value: Int) {
self.value = value
self.twiceTheValue = 2 * value
}
}
With only 1 init method we can do
let out5 = array.compactMap(TwoTimesInt.init)
But if we add a second init method
init(twiceTheValue: Int) {
self.value = twiceTheValue / 2
self.twiceTheValue = twiceTheValue
}
Then we need to give the full signature of the init method to use
let out6 = array.compactMap( TwoTimesInt.init(value:) )
Another thing worth mentioning when it comes to which method is selected is to look at the full signature of the init method including if it returns an optional value or not. So for example if we change the signature of the second init method to return an optional value
init?(twiceTheValue: Int) {
self.value = twiceTheValue / 2
self.twiceTheValue = twiceTheValue
}
then compactMap will favour this init since it expects a closure that returns an optional value, so if we remove the argument name in the call
let out7 = array.compactMap(TwoTimesInt.init)
will use the second init while the map function on the other hand will use the first init method if called the same way.
let out8 = array.map(TwoTimesInt.init)
This question already has answers here:
How to capitalize each word in a string using Swift iOS
(8 answers)
Closed 5 years ago.
How can i capitalized each first letter of the result of this
self.namE.text = currentUser.displayName
self.handle.text = snapshotValue?["handle"] as? String
instead of "Bruce willis" i would like to have "Bruce Willis", i created this extension to capitalized the first letter
extension String {
func capitalizingFirstLetter() -> String {
return prefix(1).uppercased() + dropFirst()
}
}
but it obviously capitalize only the first word in a string, so how i have to modify this extension to get the right result? ( i looked in the doc but i didn't understand very well )
String in swift4 has already a capitalized computed property on itself, so without implementing anything yourself, you can get the desired result using this:
self.namE.text = currentUser.displayName.capitalized
E.g.:
self.namE.text = "bruce willis".capitalized
This question already has an answer here:
In Swift, does Int have a hidden initializer that takes a String?
(1 answer)
Closed 7 years ago.
I'm new to Swift. I saw this code online:
let number = Int("123")
I want to read a bit more about the "Int" type initialiser that take a string as a argument. However, when I looked at Apple's offical Swift documentations:
https://developer.apple.com/library/tvos/documentation/Swift/Reference/Swift_Int_Structure/index.html#//apple_ref/swift/struct/s:Si
I couldn't find a Int type initialiser that actually takes a string as its argument. Am I looking at the wrong place? Or is there something I'm missing or unaware of?
If you click on init(_:radix:) to expand the declaration then you'll see
Construct from an ASCII representation in the given radix.
Declaration
init?(_ text: String, radix radix: Int = default)
The first parameter is a string (and has an empty external parameter
name). The second parameter "radix" has a default value,
therefore it can be omitted when calling the function:
let number = Int("123")
but you can specify the radix to create a number from a string
representation in another base:
let numberFromHexString = Int("100", radix: 16) // Optional(256)
let numberFomOctalString = Int("077", radix: 8) // Optional(63)
There is also a "trick" which I learned at
"Jump to definition" for methods without external parameter names: If you write
let number = Int("123")
as
let number = Int.init("123")
then you can "command-click" on "init" in Xcode, and you are led
directly to the declaration
public init?(_ text: String, radix: Int = default)
This question already has answers here:
Why can't I check to see if my array of arrays contains a specific array?
(2 answers)
Closed 7 years ago.
Im trying to figure out how to check if array contains another array:
var grid: [[Int]]!
grid = []
grid.append([1,1])
if grid.contains([1,1]) {
}
but the line
if grid.contains([1,1]) {
throws the error:
Contextual type '#noescape ([Int]) throws -> Bool' cannot be used with
array literal
Swift arrays doesn't conform to Equatable by default. But you can still compare them in the predicate:
if (grid.contains { $0 == [1,1] } == true) {
}
It seems to me that there is a discrepancy in Swift's syntax between calling an initializer and a function with at least one paremeter.
Let's consider these two examples:
class SimpleClass {
var desc: String
init(desc: String) {
self.desc = desc
}
}
let aClass = SimpleClass(desc: "description")
and
func simpleFunc(a: Int, b:Int) -> Int {
return a + b;
}
let aVal = simpleFunc(5, b: 6)
It seems odd to me that the compiler forces you to omit the first label in a function call, otherwise you will get an error "Extraneous argument label 'a:' in call". Whereas if we want to omit the first label during initilization, you get the error "Missing argument label 'desc:' in call".
The language guide says:
When calling a function with more than one parameter, any argument after the first is labeled according to its corresponding parameter name.
Source: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html
The arguments to the initializer are passed like a function call when
you create an instance of the class.
Source: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html
I'm new to Swift so I hope I didn't miss something, but this seems like a syntax discrepancy, because initializers/ constructors are just kind of functions and forcing to omit the first label in a function call seems inconsistent to me.
That's because Swift focuses on readability; function calls to be able to be read like a sentence. See this, specifically the section on "Local and External Parameter Names for Methods". Your function, to comply with this style, should be more like:
func add(a: Int, to b: Int) -> Int {
return a + b
}
let c = add(1, to: 2)