Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am been to ios development for few months and eager to implement new things in my programming pattern.
Now i am learning closures and knew little things about its syntax,knew it can be used instead of delegate for callbacks. As well as implemented it in some UIViewAnimation and for sorting.
But really i want to know its uses apart from that.i.e where should we use closures in our basic programming. Like we use delegate when we want to send information from child to parent.. So any explanation or brief example on its actual which can be used in our day to day swift programming would be helpful?
Can anyone tell me how these closure actually computes the value
reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
In these example there is names and closure as an argument to a method..but how does this actually computes ?
Can you please explain how these works when passing closures in this animation code :
UIView.animateWithDuration(duration: NSTimeInterval,
animations: (() -> Void)?,
completion: ((Bool) -> Void)?)
I really want to know about the flow?
The two most used cases are completion blocks and higher order functions in Swift.
Completion blocks: for example, when you have some time consuming task, you want to be notified when that task is finished. You can use closures for that, instead of a delegate (or many other things)
func longAction(completion: () -> ()) {
for index in veryLargeArray {
// do something with veryLargeArray, which is extremely time-consuming
}
completion() // notify the caller that the longAction is finished
}
//Or asynch version
func longAction(completion: () -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
for elem in veryLargeArray {
// do something with veryLargeArray, which is extremely time-consuming
}
dispatch_async(dispatch_get_main_queue(), {
completion() // notify the caller that the longAction is finished
})
}
}
longAction { print("work done") }
In the example above, when you have a time consuming task, you want to know when the for loop finishes iterating through the very large array. You put the closure { println("work done") } as an input parameter for the function which will be executed after the for loop finishes its work, and print "work done". And what happened is that you gave a function (closure) to longAction and name it to completion, and that function will be executed when you call completion in longAction.
Higher order functions: you can use closures as input parameters for higher order functions, for example:
let array = [1, 2, 3]
let smallerThanTwo = array.filter { $0 < 2 }
With this, you can filter out the numbers that are smaller than 2.
UPDATED About how sorted (probably) works:
So the idea is, that sorted will go through the array, and compare two consecutive elements (i, i + 1) with each other, and swap them, if needed. What does it mean "if needed"? You provided the closure { (s1: String, s2: String) -> Bool in return s1 > s2 }, which will return true if s1 is lexiographically greater than s2. And if that closure returned true, the sorted algorithm will swap those two elements, and countinues this with the next two elements (i + 1, i + 2, if the end of the array is not reached). So basically you have to provide a closure for sorted which will tell "when" to swap to elements.
A closure is something like:
{ (params) -> returnType in
statements
}
Here are some reasons why to use it from the Apple doc
Inferring parameter and return value types from context
Implicit returns from single-expression closures
Shorthand argument names
Trailing closure syntax
Usually Closures does not has names in contrast to other functions. That means them can be used in every case when you want to pass chunk of code to some function without wrapping that code into named method. Sorting is the most popular example.
Closures can use variables outside of its borders. So called "Capturing Values"
Related
I want to observe two behaviorRelays with a single observer, wait for both relays to emitt their values, then in the subscription have two seperate closure arguemts, one for each relay. Something like this:
let one = firmwareService.basicIODeviceUnit.compactMap { $0?.canBeUpdated }
let two = firmwareService.motorDeviceUnit.compactMap { $0?.canBeUpdated }
Observable.of(one, two).flatMap{ $0 }.subscribe(onNext: { a, b in
print("--", a, b)
}).disposed(by: disposeBag)
The above code isn't allowed. The operators like merge or zip seem to bundle both relays into a single closure argumet so I guess they won't work. What do I use?
I have looked through this thread, so it should be possible, but I can't wrap my head around it since I use swift
RxJS Subscribe with two arguments
I'm not sure what you mean because zip does exactly what you want. So does combineLatest.
let one = firmwareService.basicIODeviceUnit.compactMap { $0?.canBeUpdated }
let two = firmwareService.motorDeviceUnit.compactMap { $0?.canBeUpdated }
Observable.zip(one, two)
.subscribe(onNext: { a, b in
print("--", a, b)
})
.disposed(by: disposeBag)
you can use combineLatest:
combineLatest is an operator which you want to use when value depends on the mix of some others Observables.
When an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified closure and emit items based on the results of this closure.
For reference follow this -
combineLatest meduim link
I have a view model with a few different functions that look like:
func somethingSignal() -> SignalProducer<Void, NSError>
{
return SignalProducer {
sink, disposable in
sink.sendNext(blabla)
sink.sendCompleted()
}
}
Now, these signals need to be run in sequence - one cannot start before the preivous has been Completed. I therefore have another function called something like:
func setup() -> SignalProducer<Void, NSError>
{
return somethingSignal()
.then(somethingSignal2())
.then(somethingSignal3())
}
I was under the impression that then is the function to use for this sort of behaviour. Signal3 shouldn't begin until Signal2 has completed, which shouldn't start until Signal1 has completed.
The function that calls setup has the start() call.
Where am I going wrong with this?
That looks correct!
Alternatively, you can concatenate all the signals:
SignalProducer<SignalProducer<(), NSError>, NSError>(values: [
somethingSignal(),
somethingSignal2(),
somethingSignal3()
])
.flatten(.Concat)
Since your type is Void you probably don't care about the values emitted. If you do, however, note that this has slightly different semantics: it will emit values from all the signals, unlike then.
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() {
}
I want to run different functions depending on selected level Integer
so if selected level is 1 then runfunc1(), if 2 then runfunc2()...
I know this is possible using if else
if levelselected == 1 {
runfunc1()
} else if levelseletecd == 2 {
runfunc2()
// ... and so on
}
Is there any better way than this, perhaps something like this
runfunc%i(),levelselected // I know its not correct but something similar
I dont want to write new code for every level, so any better way?
You can use something like:
var levelSelected = 0 //
var selector = Selector("runFunc\(levelSelected)")
if self.respondsToSelector(selector) {
NSThread.detachNewThreadSelector(selector, toTarget: self, withObject: nil)
}
You could have an array or dictionary of functions. A dictionary might be nicer since the logic for checking if the level is valid is a lot simpler:
let funcs = [1: runfunc1, 2: runfunc2]
if let funcToRun = funcs[levelselected] {
funcToRun()
}
However, you won't be able to easily dynamically build a function name from strings and numbers without using #objc functionality.
(except in the sense that you could make the key to the dictionary a string of the function name, but you still have to build the dictionary using actual function names determined at compile time)
That said, you can add to the funcs variable from elsewhere in the code so it does mean to can "hook up" new levels without changing this dispatching logic.
Not the exact solution you are looking for but this can make it easier :
Declare an array of the desired functions:
var levelFunctions: [()->()] = [runfunc1, runfunc2, runfunc3]
This syntax declares an array of functions that have zero argument and return nothing. You initialize this array with the required function names and then execute the desired function using the levelselected variable:
levelFunctions[levelselected]() // Or levelselected-1 if the variable is not zero-based
EDIT:
As Airspeed Velocity mentioned in the comment and his answer you should make sure the level is in the array bounds.
I prefer to create a function, for example runFuncFromLevel::Int -> (() -> Void). runFuncFromLevel return a proper function that you need.
func runFuncFromLevel(level: Int) -> () -> Void
{
switch level
{
case 1: return runfunc1
case 2: return runfunc2
default: return {}
}
}
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)