What is the simplest way to write a piece of code that can be executed only once?
I know a way but has a problem.
first, I write a Boolean variable that has negative value but can be set to positive and cannot change after that
var hasTheFunctionCalled : Bool = false {
didSet{
hasTheFunctionCalled = true
}
}
and then write the function and the code inside it:
func theFunction(){
if !hasTheFunctionCalled{
//do the thing
}
hasTheFunctionCalled = true
}
but the problem is that the variable can be changed from somewhere else in the scope and this solution doesn't really look so simple and concrete.
A simple solution is to take advantage of lazy variables in the following way:
// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
// Do something once
}()
...
// Then to execute it, just call
_ = myFunction
This ensures that the code inside the myFunction closure is only executed the first time that the program runs _ = myFunction
Edit: Another approach is to use so called "dispatch once tokens". This comes from Objective-C and was available in Swift until Swift 3. It is still possible to make it work, however you will need to add a little bit of custom code. You can find more information on this post -> dispatch_once after the Swift 3 GCD API changes
Edit2: Should be _ = myFunction and not _ = myFunction(), as JohnMontgomery pointed out.
You might use a static bool inside a struct nested into the function itself doing so:
func theFunction(){
struct Holder { static var called = false }
if !Holder.called {
Holder.called = true
//do the thing
}
}
One possible technique is to put the code into the initializer of a static type property, which is guaranteed to be lazily initialized only once (even when accessed across multiple threads simultaneously):
func theFunction() {
struct Once {
static let once = Once()
init() {
print("This should be executed only once during the lifetime of the program")
}
}
_ = Once.once
}
(Compare Singleton in the "Using Swift with Cocoa and Objective-C" reference.)
Example:
print("Call #1")
theFunction()
print("Call #2")
theFunction()
print("Done")
Output:
Call #1
This should be executed only once during the lifetime of the program
Call #2
Done
You can do smth like:
class Once {
var already: Bool = false
func run(#noescape block: () -> Void) {
guard !already else { return }
block()
already = true
}
}
and than use it like
class ViewController: UIViewController {
let once = Once()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
once.run {
cameraMan.setup()
}
}
}
ref: https://dev.to/onmyway133/how-to-run-action-once-in-swift-3k7o
Depending on what you are doing inside your method : you may check if the end result has already been accomplished :
e.g. if you instantiate a class, check if it is different from nil
You can also use UserDefaults, and the knowledge that the default UserDefault Bool is false:
if !UserDefaults.standard.bool(forKey: "ExecuteOnce") {
func()
UserDefaults.standard.set(true, forKey: "ExecuteOnce")
}
This code will execute exactly once.
Related
In Swift I am trying to implement a method "tap" similar to the method which exists in Ruby.
I've come up with the following example code:
private protocol Tap {
mutating func tap(_ block: (inout Self) -> Void) -> Self
}
private extension Tap {
mutating func tap(_ block: (inout Self) -> Void) -> Self {
block(&self)
return self
}
}
extension Array: Tap {}
var a = Array(repeating: "Hello", count: 5)
a.tap {
$0.append("5")
}.tap {
$0.append("7")
}
print(a) // (Expected) => ["Hello", "Hello", "Hello", "Hello", "Hello", "5", "7"]
I'm not super familiar with mutating functions, inout parameters, or Swift in general, but the code above looks like it should work to me. tap works as expected when it's not being included in a method chain. When I include it as part of a method chain, like in the above example, the Swift compiler complains:
Cannot use mutating member on immutable value: function call returns immutable value
Can anyone explain to me why this doesn't work? Can anyone provide a working solution and explain why that solution works?
Edit:
Another example usage would be:
let user = User(fromId: someId).tap {
$0.firstName = someFirstName
$0.lastName = someLastName
}
tap is a convenience thing that comes from Ruby. I'm mainly interested in understanding why the types in my function aren't working out right.
The return self returns a copy of the original array, not the original array itself. Until this copy is stored as a var, it cannot be mutated. So, this would work:
var b = a.tap {
$0.append("5")
}
b.tap {
$0.append("7")
}
But not without storing b as a var first. Of course, you wouldn't create a b in the first place, you would just use a repeatedly as you already pointed out.
So, the issue is that you can accomplish tap once, but cannot chain taps. This is because the return of self is implicitly immutable, and you cannot call a mutating function on an immutable value. Changing tap to a non-mutating function could get you what you want:
private extension Tap {
func tap(_ block: (inout Self) -> Void) -> Self {
let copy = self
block(©)
return copy
}
}
var a = Array(repeating: "Hello", count: 5)
a = a.tap({$0.append("5")}).tap({$0.append("7")})
Because each invocation of tap( returns a copy of the original modified by the given block, you can call it on immutable types. That means that you can chain.
The only downside is that new a = in the beginning.
I have recently read about how to add "Traits/Mixins" to a struct/class in Swift by creating a protocol and extending that protocol with a default implementation. This is great as it allows me to add functionality to view the controller without having to add a bunch of helper objects to said view controller. My question is, how do I stub calls that are provided by these default implementations?
Here is a simple example:
protocol CodeCop {
func shouldAllowExecution() -> Bool
}
extension CodeCop {
func shouldAllowExecution() -> Bool {
return arc4random_uniform(2) == 0
}
}
struct Worker : CodeCop {
func doSomeStuff() -> String {
if shouldAllowExecution() {
return "Cop allowed it"
} else {
return "Cop said no"
}
}
}
If I wanted to write two tests, one that verifies that the String "Cop allowed it" is returned by doStuff() when CodeCop does not allow execution, and another test that verifies that the String "Cop said no" is returned by doStuff() when CodeCop does not allow execution.
This is simple enough to do by writing an additional protocol in your test target, called CodeCopStub, that inherits from CodeCop:
protocol CodeCopStub: CodeCop {
// CodeCopStub declares a static value on the implementing type
// that you can use to control what is returned by
// `shouldAllowExecution()`.
//
// Note that this has to be static, because you can't add stored instance
// variables in extensions.
static var allowed: Bool { get }
}
Then extend CodeCopStub's shouldAllowExecution() method, inherited from CodeCop, to return a value depending on that new static variable allowed. This overrides the original CodeCop implementation for any type that implements CodeCopStub.
extension CodeCopStub {
func shouldAllowExecution() -> Bool {
// We use `Self` here to refer to the implementing type (`Worker` in
// this case).
return Self.allowed
}
}
All you have left to do at this point is to make Worker conform to CodeCopStub:
extension Worker: CodeCopStub {
// It doesn't matter what the initial value of this variable is, because
// you're going to set it in every test, but it has to have one because
// it's static.
static var allowed: Bool = false
}
Your tests will then look something like this:
func testAllowed() {
// Create the worker.
let worker = Worker()
// Because `Worker` has been extended to conform to `CodeCopStub`, it will
// have this static property. Set it to true to cause
// `shouldAllowExecution()` to return `true`.
Worker.allowed = true
// Call the method and get the result.
let actualResult = worker.doSomeStuff()
// Make sure the result was correct.
let expectedResult = "Cop allowed it"
XCTAssertEqual(expectedResult, actualResult)
}
func testNotAllowed() {
// Same stuff as last time...
let worker = Worker()
// ...but you tell it not to allow it.
Worker.allowed = false
let actualResult = worker.doSomeStuff()
// This time, the expected result is different.
let expectedResult = "Cop said no"
XCTAssertEqual(expectedResult, actualResult)
}
Remember that all of this code should go in your test target, not your main target. By putting it in your test target, none of it will affect your original code, and no modification to the original is required.
I am not sure if that is what you are looking for, but one way you can test this behavior without updating your code is by updating your project structure the following way:
Keep the CodeCop protocol in one file (let's say CodeCop.swift) and add the extension code into another one (CodeCop+shouldAllowExecution.swift)
While CodeCop.swift is linked to both your main target and your test target, CodeCop+shouldAllowExecution.swift is only in the main target.
Create a test file CodeCopTest.swift, only available in the test target, who contains another default implementation of shouldAllowExecution that will help you run your test.
Here's a potential CodeCopTest.swift file
import XCTest
fileprivate var shouldCopAllowExecution: Bool = false
fileprivate extension CodeCop {
func shouldAllowExecution() -> Bool {
return shouldCopAllowExecution
}
}
class PeopleListDataProviderTests: XCTestCase {
var codeCop: CodeCop!
override func setUp() {
super.setUp()
codeCop = CodeCop()
}
override func tearDown() {
codeCop = nil
super.tearDown()
}
func testWhenCopAllows() {
shouldCopAllowExecution = true
XCTAssertEqual(codeCop.doSomeStuff(), "Cop allowed it", "Cop should say 'Cop allowed it' when he allows execution")
}
func testWhenCopDenies() {
shouldCopAllowExecution = false
XCTAssertEqual(codeCop.doSomeStuff(), "Cop said no", "Cop should say 'Cop said no' when he does not allow execution")
}
}
I'm not talking about pointers to C functions, but to a method within a Swift type.
struct Test: GeneratorType {
var methodPointer: mutating () -> Bool? // Non-working guess
var which: Bool
init() {
which = false
methodPointer = which ? &testMethod1 : &testMethod2 // Also non-working guess
}
//...
}
The compiler says "mutating" isn't legal as part of a function declaration. (Actually, it just suggests a semi-colon there.) And for the pointer initialization (after I remove mutating), the compiler thinks I'm trying to call the functions and use their results instead. I want to use the methods as objects in-and-of themselves here, not as a function call. Later on I want to use the pointed-to method within next; without figuring this out, I'll have to resort to an enumeration flag and manually choosing which method to call within next.
I hope there's some part of closure mechanics that allows this. Maybe something like this page, which describes functions returning functions. But none of the examples I've seen mention mutating methods.
See if this helps you.
class Something {
var f: ( () -> Int )?
let f1 = { () -> Int in /* do some action here */ return 1}
let f2 = { () -> Int in /* do some action here */ return 2}
func ff(which: Bool) {
f = which ? f1 : f2
}
func act() {
if let f = f {
f()
}
}
}
Here is how I do it -
class FcnArgs { //#goal pass a fcn as arg
class func demo() {
let fPtr = funcToPointTo; //#type '((Int)->String)'
print(fPtr(4));
}
class func funcToPointTo(_ i : Int) -> String {
print("I Was passed \(i)");
return "I was returned";
}
}
FcnArgs.demo() output:
I Was passed 4
I was returned
Please excuse me for the poor title. Will update it if something better comes in mind.
Tested on: Xcode Version 7.2.1 (7C1002)
I want to take advantage of Swift's lazy stored properties to compute the value of a property while in a "background" queue before accessing it from the main queue.
Here is a class defining a lazy stored property
class Cache {
lazy var heavilyComputational = {
return 42
}()
}
This is an example usage
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
let _ = cache.heavilyComputational
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
That works.
Warning aside, IMO the intent is not clear.
A lazy property is lazily computed yes but in this case, the "where", "when" and "why" are equally important and not as clear.
Tried to clarify intent by being "clever" using a struct like so
struct Compute {
var function: () -> Void {
didSet{
function()
}
}
}
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
Compute {
cache.heavilyComputational
}
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
but the compiler "outsmart" me by removing the instruction (AFAICT) since the Compute instance isn't used. FWIW, this is on the Debug configuration and I can only assume on Release it will be even more aggressive.
For comparison, this works as expected (*not the didSet call)
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
let compute = Compute {
cache.heavilyComputational
}
compute.function()
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
but by that time, the whole purpose is defeated.
1. Have I misunderstood something?
2. Is there a native construct to allow for something like this in Swift?
3. If not, is there a way to rewrite this code so that the intent is clear?
4. Why the didSet is not called?
Sample project: https://github.com/qnoid/compute
It seems you kinda realise the problem. As far as I know, didSet won't be triggered if it's in the init method.
In your case, when you do
Compute {
cache.heavilyComputational
}
It's actually using init method of the struct to set the function property which will not trigger the didSet.
And in your second attempt, since you explicitly call the function() which will then call cache.heavilyComputational, so you trigger the lazy initialization of heavilyComputational manually. It's pretty much equivalent to your original (without the Compute struct) method.
To make your struct works without calling the function, you have to do some hacks.
struct Compute {
var function: () -> Void = {} {
didSet{
function()
}
}
init(function: () -> Void) {
setFunction(function)
}
private mutating func setFunction(function: () -> Void) {
self.function = function
}
}
So then you can just do
Compute {
cache.heavilyComputational
}
For further improvement, I'll have to think about it.
I believe I have found a simple answer to this.
struct Compute {
init(f: () -> Void) {
f()
}
}
Happy with that answer for question 3, the rest remain. Tho, worry I might be bitten by some future compiler optimisation.
following is a code sample you can run in a playground
import Foundation
class TempNotifier {
var onChange: (Int) -> Void = {t in }
var currentTemp = 72
init() {
// 1.
onChange = { [unowned self] temp in
self.currentTemp = temp
}
// 2.
onChange = {[unowned self] temp in
self.tempHandler(temp)
}
// 3.
unowned let s = self
onChange = s.tempHandler
}
deinit {
println("deinit")
}
private func tempHandler(temp: Int) {
self.currentTemp = temp
}
}
var tN: TempNotifier? = TempNotifier()
tN = nil
It illustrates 3 ways of assigning a value to a block with potential retain-cycle. Case 1. and 2. create no retain cycle due to unowned self however in case 3. it seems like there is no way to break the retain cycle (deinit is never printed). As you can see, I even tried to create a local unowned reference.
Is this the desired behaviour, is it "by design"? Or am I missing something?
Thanks!
Cross-posted from https://devforums.apple.com/message/1122247
Yes, this is the designed behavior.
Accessing a method without calling it, like s.tempHandler, is equivalent to a closure expression like { x in s.tempHandler(x) }. Here s is not marked unowned or weak, and hence is retained by the closure. If you want it to be captured as unowned or weak, you must explicitly write out the closure.