Swift NSString function syntax usage - ios

I have a basic question about swift function calling syntax. I have read documentation but not able to figure it out. So decided to put a query over here.
A piece of code i wrote
var string1 = NSString().stringByAppendingString("First string")
var string2 = NSString.stringByAppendingString("Second string")
println(string1)
println(string2)
Both string have same function calling but return type is different. And only difference here is (). I got out put like
First string
(Function)
Question is why its not giving a warning/error. Is it that var string2 holds method body of stringByAppendingString? Whats going on, New swift developer like me can easily make a this type of typo mistake and not able to figure out.
Can you please explain why its not return value?

This happens because swift methods are curried functions (you can find detailed explanation in Ole Begemann's post).
So what you actually got in the following line:
var string2 = NSString.stringByAppendingString("Second string")
is a function that takes a string as parameter and returns the result of
"Second string".stringByAppendingString(parameter)
You can check that by calling string2 as an ordinary function:
string2("123")
// Prints: "Second string123"

Related

Adding elements to an empty array throws errors

I am trying to added elements to an empty string array and I tried to follow this post add-value-to empty-array but none the options are helping me as they result in Xcode throwing errors each time.
here is the code if have tired:
var tasks = [String]()
tasks += ["something"]
This gave me 6 errors on x code with the first being Consecutive declaration on a line must be separated by ; then it says it's an invalid redeclaration of tasks followed by a bunch of errors saying to make it a func. When I try the .append func instead of += it gives the same errors
Now if I try this:
var tasks = [String]()
var tasks = ["Something"]
it only gives me the invalid redeclaration error but I do not believe this the correct way to add elements to the array
Hopefully, this helps explain my issue and sorry for the weird beginner question but thank for the help in advance
I looked at the code in your pastebin and the issue is that you had both the declaration and assignment on separate lines in the class definition.
class TableViewController: UITableViewController {
//temp list of tasks
var tasks = [Sting]()
//giving some default values in the cell
tasks.append(["something"])
You also spelled String wrong, but that is not relevant for the fix.
Another issue is a type mis-match. You declare an array of String, which would be [String]. However, you are attempting to add an array of String to an another array of String, which is wrong.
tasks.append(["something"])
Instead, you should have
tasks.append("something")
This now adds an element of String to your array of Strings.
Finally, you can do one of two things:
Assign the array at creation
var tasks = ["something"]
or assign it inside a function, like your ViewDidLoad
You can't use += with a [String] (array of Strings) and String.
Here's an example I ran in a playground:
var array: [String] = []
array.append("A")
print(array)
It prints ["A"]. Without seeing your code it will be hard to diagnose if there is another problem.
Update after looking at your code:
var tasks = [Sting]() // Should be String
tasks.append(["something"])
You can't append in the declaration, you'll need to add the append to a function (try viewDidLoad or viewWillAppear to test). ["something"] is an array of String, not a String. You'll need to use "something" instead.

Using stringInterpolationSegment string initializer in swift

While researching the String Structure Reference from Apple (String Structure Reference)
There are initializer methods that accepts Int parameters such as:
init(stringInterpolationSegment expr: Int)
I attempted by writing the code below to learn how to use it plus learn the difference between pass by reference vs. pass by value but can't get it to work using the following:
struct Soho {
var myCountry = "America"
init(stringInterpolationSegment expr: Int){
}
}
How should swift code be structured in order to use this string initializer?
From https://developer.apple.com/reference/swift/string/1539185-init, Apple says:
Creates a string containing the given value’s textual representation.
Do not call this initializer directly. It is used by the compiler when interpreting string interpolations.
(emphasis mine)
And they show you an example in https://developer.apple.com/reference/swift/stringinterpolationconvertible, where we see that indeed we should use String interpolation with "\()".

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.

swift declare variable of subtype with reference of super type

I'm trying to use polymorphism in swift but I'm doing something wrong; I have the following scenario:
class Character : NSNode {
let characterName = "name"
}
class World : NSNode {
let character : NSNode = Character()
// getting error here, NSNode does not have a property "characterName"
character.characterName = "new name"
}
what's the correct way of declaring a variable of type Character() but has reference type NSNode()?
(character as Character).characterName = "new name"
This feature of Swift is not unusual. You have typed character as NSNode so that is all the compiler knows about it. To tell the compiler what sort of object it really is (e.g. what subclass of NSNode), you cast down.
There is nothing wrong with your declaration, provided you are willing to cast down every time you want to access a Character feature. But did you have some reason for not just typing character as a Character to begin with? After all, Swift knows perfectly that this means it is also an NSNode. It seems to me that you may have your notion of polymorphism somewhat topsy-turvy.

Function not working in Swift

So I've been trying to learn a bit of Swift and I've been looking at functions with return types. I added this function, and it should work, but I still get the error "Could not find member 'convertFromStringInterpolationSegment.' I've looked at other stack overflow questions and have tried to apply their answers, but to no avail. Some help would be greatly appreciated.
func getGasPrices2(price1: Double, price2:Double, price3:Double)
{
return "The prices are \(String(price1)), \(String(price2)), \(String(price3))."
}
getGasPrices2(3.59, 3.69, 3.79)
You forgot to declare a return type. Since you want to return a String, the function needs to declare that:
func getGasPrices2(price1: Double, price2:Double, price3:Double) -> (String)
I'm sure that Apple will work on these wonderful error messages. :)
As Alvin stated, you were simply missing the return type
-> (String)
...in the function's declaration.
I find myself doing the same thing, forgetting the return type at the end, as I'm still getting used to writing in Swift while having the function-type-declaration-first of Objective-C habit
...
Basically your function in Swift...
func getGasPrices2(price1: Double, price2:Double, price3:Double) -> (String)
...is equivalent* to
-(NSString*)getGasPrices2: (double)price1 price2:(double)price2 price3:(double)price3
...in Objective-C*
*Strings in Swift aren't exactly the same as NSStrings but both functions would be able to accomplish what you are looking to do; one in Objective-C, the other in Swift (as long as you make sure to actually return a String/NSString at the end :-)

Resources