Swift - предотвращение повторного вызова функции - PullRequest
0 голосов
/ 27 сентября 2018

Мой основной код должен быть длинным, поэтому я попробую с более простым объяснением.Допустим, у меня есть глобальная переменная count, которая используется функциями.Если счетчик должен был быть вызван дважды по нашей причине, как показано в коде ниже ... как я могу сделать так, чтобы вывод "10, 10", а не "10, 20".

var count = 0

override func viewDidLoad() {

  helloWorld()

}


override func viewWillAppear(_ animated: Bool) {
    helloWorld()
}



func helloWorld(){
    var counter = 0
    for i in 1...10{
        count = count + 1
        counter = counter + 1
    }
    print(count)
}

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Изменить

func helloWorld(){
var counter = 0
for i in 1...10{
    count = count + 1
    counter = counter + 1
}
print(count)
}

на

func helloWorld(){
var counter = self.count
for i in 1...10{
    count = count + 1
}
print(count)
self.count = counter
}

Таким образом, вы сохраняете в счетчик значение счетчика до его изменения, а затем снова делаете его равным предыдущему.

ПРИМЕЧАНИЕ: Таким образом, вы всегда получите 10 при вызове helloWorld (), независимо от того, сколько раз вы вызываете функцию.

Вы можете изменить функцию, как показано ниже:

func helloWorld(_ countValue: Int){
var counter = self.count
for i in 1..<countValue{
    count = count + 1
}
print(count)
self.count = counter

}

Таким образом, вы можете выбрать верхний элемент счетчика, просто вызвав:

helloWorld(10)
helloWorld(20)

Совет: Не рекомендуется иметь функцию, которая изменяет внешнее значение

0 голосов
/ 27 сентября 2018

Используйте DispatchQueue со статическим токеном (кэшируемым через жизненный цикл приложения), вот полезное расширение:

extension DispatchQueue {

    private static var tokens: [String] = [] // static, so tokens are cached

    class func once(executionToken: String, _ closure: () -> Void) {
        // objc_sync_enter/objc_sync_exit is a locking mechanism
        objc_sync_enter(self)
        defer { objc_sync_exit(self) }
        // if we previously stored token then do nothing
        if tokens.contains(executionToken) { return }
        tokens.append(executionToken)
        closure()
    }
}

func doSomething() {
    DispatchQueue.once(executionToken: "doSomething") {
        print("This should be executed once")
    }
}

doSomething()
doSomething()
doSomething()

«Это должно быть выполнено один раз» будет напечатано только один раз.

Вы можететакже используйте ленивый механизм:

class SomeClass {
    lazy var executeOnce: () -> Void = {
        doSomething()
        return {}
    }()

    func doSomething() {
        print("This should be executed once")
    }
}

let someClass = SomeClass()
someClass.executeOnce()
someClass.executeOnce()
someClass.executeOnce()

Он готов к работе с потоками из коробки, поэтому вам не нужно беспокоиться о блокировке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...