Swift: syntax explanation - round brackets then "in" - ios

I following tutorial and confused with following code:
let rectToDisplay = self.treasures.reduce(MKMapRectNull){
(mapRect: MKMapRect, treasure: Treasure) -> MKMapRect in
let treasurePointRect =
MKMapRect (origin: treasure.location.mapPoint, size: MKMapSize (width: 0, height: 0))
return MKMapRectUnion(mapRect, treasurePointRect)
}
In fact, I'm not understand only that line:
(mapRect: MKMapRect, treasure: Treasure) -> MKMapRect in
Is that some kind of function or something? What is the output? Im not quite understand meaning of that construction (struct: struct, someClass: someClass) -> Struct in
What is that logic? What is the meaning of "in"?
If you wondering, treasure is custom class that contain coordinate properties - latitude, longitude, etc.
I understand the "whole" meaning of that code snippet, but syntax of that line confuse me a bit..
Could you provide an explanation? Thanks a lot!

In Swift there are two ways to declare a function: with func, and with a closure expression:
// this is a function that takes an Int and returns a String
func f(i: Int) -> String { return i.description }
f(1) // returns "1"
// this is also a function that takes an Int and returns a String
let g = { (i: Int) -> String in return i.description }
g(1) // returns "1"
The latter is a closure expression – a quick way of defining a new function inline. They are most commonly used with functions that take functions (for example map, which takes an array and a function that transforms an element of that array, and runs the function on each element creating another array).
The syntax for closure expressions is they start, within braces, with arguments and return type, and then an in, and then the function body. Unlike with func, which starts with the func keyword, then the arguments and return type, followed by the function body within braces.
You don't always see the in because it can be left off. There are lots of shorthands that allow you to skip the arguments and return type (and the return keyword) altogether. But sometimes you need to give them, and then you need the in keyword.
You can read more about closure expressions in the Apple Swift book. You can read more about functions and closure basics here.

Related

What does it mean if a mutating function setting it's self equals to another function

I was going through Apple's Arkit project sample. I was trying to understand the code since, I am still learning. I saw a function setting it self equals to another function can someone please explain what these functions are exactly doing. Please brief in detail.In the code the "mutating func normalize()" is setting it self to self.normalized why is it. What this code is doing. Can we not simply call "func normalized()" seems like we are re-creating the same function.
mutating func normalize() {
self = self.normalized()
}
func normalized() -> SCNVector3 {
if self.length() == 0 {
return self
}
return self / self.length()
}
func length() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
Values types in Swift can be mutable and immutable . So when you create struct( or any other value type) and assign it to variable (var) it is mutable and you call normalize() on it. It means that struct won’t be copied to another peace of memory and will be updated in place (will act like reference type). But when you assign it to constant (let) - it can’t be mutated so the only way to update values in this struct is to create new one with updated values as with normalized() method. Regarding your question - normalize() is just reusing logic for normalizing vector from normalized(). So this is completely fine solution. Assigning to self is only permitted in mutable methods. It’s basically rewrites value of struct with new one.
I'm assuming that this fragment is in a struct rather than a class.
self.normalized() makes a copy of self and divides the copy's components by its length and then returns the copy. self is not affected.
self.normalize() gets a normalised version of self and then replaces self by the copy. So it changes in place.
Under the hood, every member function passes self as an implicit argument. i.e. to the compiler the declaration looks like this:
func normalised(self: SCNVector3) -> SCNVector3
Putting mutating on the front of a function definition makes the hidden argument inout
func normalise(self: inout SCNVector3)
So, if you have
var a = SCNVector3(3, 4, 0)
let b = SCNVector3(4, 3, 0)
let c = b.normalized()
a.normalize()
After that code, c would be (0.8, 0.6, 0) and a would be (0.6, 0.8, 0). b would be unchanged.
Note that a has to be declared with var because it is changed in place by normalise()
Edit
In the comments khan asks:
What i am not able to understand is why do we have to create a func again we can use "func normalized"
The point being made is why can't we do something like this:
var a = SCNVector3(3, 4, 0)
a = a.normalized()
and not have the normalise() function at all?
The above will have exactly the same effect as a.normalize() and, in my opinion[1], is better style, being more "functional".
I think a.normalize() exists only because it is common in Swift to provide both forms of the function. For example, with sets you have both union() and formUnion(): the first returns the union of one set with another, the second replaces a set with the union of itself and another set. In some cases, the in place version of the function may be more efficient, but not, I think, with this normalize function.
Which you choose to use is a matter of your preference.
[1] Actually, the better style is
let a = SCNVector3(3, 4, 0).normalized()

Swift iOS take in a input and use it for function name

func callFunctionName(parameters: String) -> returnType
{
var somevalue = parameters
var returnValue = somevalue()
return returnValue
}
Is there a way to take in a input and use it as a function name?
example: let say input is green, I want to call function green. if input is red call function red etc...
Or to have a huge if statement to check each input to call different functions
This is not possible in Swift. You will have to store any functions you want to call in your own dictionary, and then use that to look up functions by name.
A "huge statement" might be feasible for a small number of functions, and it would certainly perform faster, but the ideal approach would be to store them in a dictionary.
However, if you are dealing with objects:
if exampleObject.respondsToSelector("exampleFunction")
{
exampleObject.performSelector("exampleFunction")
}
This approach currently works with all classes, be it Objective-C or Swift.
This is easily possible in Objective-C by using:
[self performSelector:NSSelectorFromString(#"green")];
But Swift is less dynamically typed than Objective-C and has less support for reflection. The Objective-C way I described above is very prone to crashes at runtime if the input (e.g. "purple" if you didn't have a function for purple) doesn't match a function that exists.
Using a big if statement is not an unreasonable way to approach it.
As the other answers said, an if statement is probably the best way to go about this.
override func viewDidLoad() {
if someValue = green {
green() //This will run whatever you have in the green() function below
}
}
func green() {
//put code for output of green here
}
Then all you have to do is make separate functions for all your outputs such as the green() func
This is the closest I could get. (And it's partially based on the answer of Vatsal Manot)
The idea is to use closures.
First of all we define the return type of the closure: let's use Int (of course you can change this later).
typealias colorClosureReturnType = Int
Now lets define the type of a closure that receives no parameters (you can change this too) and returns colorClosureReturnType
typealias colorClosureType = () -> (colorClosureReturnType)
Fine, now lets create a dictionary where the key is a String and the value is a closure of type colorClosureType:
let dict : [String: colorClosureType] = [
"red": { return 0 /* you can write here all the logic you need */ },
"green": { return 1 /* also here */},
"blue": { return 2 /* and here */}
]
Usually I let Swift Type Inference to infer the type of the variable/constant. But this time for sake of clarity I explicitly declared the type of the dictionary.
Now we can build a simple function that receives a String and return an optional colorClosureReturnType.
func callClosure(colorName: String) -> colorClosureReturnType? {
return dict[colorName]?()
}
As you can see the function look in the dictionary a closure associated to the key received as param. If it does found it then runs the closure and returns the results.
If the dictionary does not contain the requested key then the function returns nil. That's why the return type of this function is colorClosureReturnType? and not colorClosureReturnType.
Finally some tests:
callClosure("red") // 0
callClosure("green") // 1
callClosure("blue") // 2
func callFunctionName(parameters: String) -> ()
{
_ = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector(parameters), userInfo: nil, repeats: false)
}
func green() {
}

what does "->" mean in swift when declaring functions?

example function
func example(titles: [String]) `->` [UIButton] {
}
and where could i find more docs on this topic (docs relevant to functions declaring in swift)?
There is no > in swift function declarations - someone botched up the HTML rendering in the page you were reading. It was supposed to be -> (an arrow made up of a hypen and the greater than operator) that's used to denote the return type of the function.
The text was supposed to read
func example(titles: [String]) -> [UIButton] {
}
Which means the example function has one parameter called titles of type [String] (array of String) and it returns a [UIButton] (array of UIButton).
Assuming you're talking about -> the portion after that denotes the return value of the function.

swift overload operator for member type

I have a question about operator overloading in swift.
In my code I have a structure that goes like this:
struct Position {
///The horisontal index for a chessboard [A-H]
let horisontal : String
///The vertical index for a chessboard [1-8]
let vertical : Int
}
What I need next is a way to change the horizontal index in the manner of index +- some integer number. What I do then is to overload the '+' operator, like this:
func + (left: Position.horisontal, right: Int) -> Bool {
//Some implementation in here
}
And then my world crashes. The compiler tells me: "'horisontal is not a member type of 'Position'"
What is it that I do not know to help me in this situation? Why the compiler refuses to acknowledge the existence of 'horisontal'? What else can I do to achieve addition between a String and an Int?
Remark
Mind you, this works just fine, but I do not think it is in the good spirit of operator overloading:
func + (left: String, right: Int) -> Bool {
//Some implementation in here
}
Why the compiler refuses to acknowledge the existence of 'horisontal'?
Because horisontal [sic] is not a type, it's a member of the Position type.
A more appropriate solution would be to define a closed enum for row and column positions.

Swift playground execution speed

Is there a way to increase execution speed of a playground?
I want to iterate many cycles and not to wait 10 minutes.
For example:
import UIKit
var count = 0
for var i = 0; i < 1000000000; i++ {
count++
}
This code will execute a way too long. But I want to get quick result.
One of the biggest performance killer is the output at the right side of the playground. Now I will show you how to minimize this output.
See at the end for your example code.
Best Performance
The most performant way is to make all the performance critical code in a .swift file inside the Sources folder in the playground.
Note: In order to use the functions, classes, properties and methods from the Sources folder you have to mark them public. If you want to subclass a class it has to be marked open.
Good Performance but ugly code
The following method (I think this is not official/intended) can be used to disable the playground output but also leads to ugly code. However it is good for temporary disabling the output.
There are two main ways (and two tricks) to achieve the minimum amount of output (If you find a better way let us know):
Use parenthesis around Void (or Void?) expressions like assignments (normally leads to no output, see also 3.).
var x = 0 // output: 0
(x = 1) // NO output
(x = 2 * x - 1) // NO output
(x.negate()) // NO output
Note: In Swift an assignment returns Void and in case of optional chaining it is Void?.
var x: (Int, Int)? = nil
if (x?.0 = 0) != nil {
// assignment was successful (x!=0 and now x=(0, x.1))
} else {
// assignment was not successful (x==nil)
}
Initialize and declare variables separately.
var x: Int // NO output
(x = 0) // NO output
If 1. does not work add an additional no-op (no operation) line above or below ().
This happens in single line closures (and probably in some other contexts) for example: (see also the code below)
[1, 4, 5, 6].mmap{
() // without this line the line below would yield to an output
($1 = $0 + 1)
} as [Int]
Instead of wrapping every line in parenthesis you can also use a tuple of all the expressions which is then assigned to a variable:
var a: Any // this may be a useful definition in this context
var x: Int
var y: Int
(a = (x = 0,
y = 1,
x = y + 1,
y = x*x))
However this could lead to a indentation disaster...
Where it does not work (I've found no way how to remove the output; This list is probably not complete):
returns in functions and closures
Declaration of Optional variables e.g.: var x: Int?
An example of a new map method on Sequence
Usage: See above at Point 3.
The signature of Sequence.map is
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
Since I have not found a way how to remove the output of returns one can use a closure with an inout argument (get the "return" value with an assignment). A possible signature could then be:
func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]
so we can pass nil in the inout argument since it is a good default for every possible U without imposing a constraint on U which could require an instance generator (e.g.: init() { ... }).
Unfortunately Swfit has a hard time to infer U so you would need to help the compiler with explicit type annotations. In addition var newElement: U? does return nil in the sidebar.
Now I will use Any instead of U?:
extension Sequence {
// ATTENTION: this is not as performant as the normal `map`!
func mmap<U>(transform: (Element, inout Any) -> ()) -> [U] {
var result: [U]
(result = [U]())
for element in self {
var newElement: Any
(newElement = 0) // some placeholder element
(transform(element, &newElement))
// assume the inout element to be of type `U`
(result.append(newElement as! U))
}
return result // the ONLY output in this method
}
}
Your example code
Using Swift 4
var count = 0
for i in 0..<1_000_000_000 {
(count += 1)
if count % 100_000 == 0 {
// print only every 100_000th loop iteration
print(count)
}
}
Without the parenthesis: about 10.000 loop iterations per second
With parenthesis: about 10.000.000 loop iterations per second !!!
I feel your pain, I was playing around with printing 2D functions to [Double] then converting to UIImageView. One of the steps was iterating over millions of pixels, and it took forever.
Anything computationally intensive, or repetitive, or potentially time consuming should be put in the "Sources" folder of the playground. That way the code is precompiled before your playground is run. Put the output of that for loop in a public function that you can call from the playground. Then you won't have to sit there watching the playground count all the times it went through the for loop.
I had a such problem and I have solved it after days of trials. All I needed to do is move all my code in folder Sources of playground. So, after that the execution speed was enhanced.
I hope it helps you.
Note: don't forget to use open classes.
To speed up the build in Xcode Playground and prevent the loading icon to keep spinning forever:
go to the sidebar on the right, and change iOS to macOS in Playground Settings
instead of importing UIKit, import Foundation
(this would work if you're not trying to use specific stuff from the UIKit framework)

Resources