Swift 3 Linux с Perfect: добавьте запланированный таймер с интервалом в цикл выполнения

Я пытаюсь создать приложение в Swift на моем Ubuntu (Ubuntu 15.10 wily, Swift swift-3.0.1-RELEASE), используя Perfect библиотека.

Я хотел бы, чтобы функция вызывалась каждые X секунд. Для этого я использую класс Timer модуля Foundation:

class MyTimer {
    init() {
        var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(MyTimer.onTimer(timer:)), userInfo: nil, repeats: true)
    }
    @objc func onTimer(timer: Timer) {
        print("MyTimer.onTimer")
    }
}

Несмотря на то, что с этим кодом было найдено несколько решений, компиляция не удалась:

$> swift build
Compile Swift Module 'my-app' (7 sources)
/home/.../Sources/MyTimer.swift:8:16: error: method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C
    @objc func onTimer(timer: Timer) {

Еще одна ошибка компиляции, если я расширяю свой класс из NSObject или удаляю аргумент timer:

$> swift build
Compile Swift Module 'my-app' (7 sources)
/home/.../Sources/MyTimer.swift:6:83: error: '#selector' can only be used with the Objective-C runtime
    var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(MyTimer.onTimer), userInfo: nil, repeats: true)

Я попытался использовать другое объявление, в котором не используются селекторы:

class MyTimer {
    init() {
        print("MyTimer.init")
        var timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {
            timer in
            print("MyTimer.onTimer")
        }
    }
}

Компиляция работает, но моя вторая печать никогда не вызывается. Я также попытался вручную добавить свой таймер к текущему RunLoop:

class MyTimer {
    init() {
        print("MyTimer.init")
        var timer = Timer(timeInterval: 1, repeats: true) {
            timer in
            print("MyTimer.onTimer")
        }
        RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
        // timer.fire()
    }
}

Больше никогда не звонил (и timer.fire() вызывал мою функцию только один раз). И наконец:

class MyTimer {
    init() {
        print("MyTimer.init")
        let timer = Timer(timeInterval: 1, repeats: true) {
            timer in
            print("MyTimer.onTimer")
        }
        RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
        RunLoop.current.run(until: Date(timeIntervalSinceNow: 4.0))
    }
}

Мое сообщение "MyTimer.onTimer" печатается 5 раз, но мой сервер (с использованием библиотеки Perfect) запускается только в конце:

$> swift build && ./.build/debug/my-app 8400
Compile Swift Module 'my-app' (7 sources)
Linking ./.build/debug/my-app
MyTimer.init
MyTimer.onTimer
MyTimer.onTimer
MyTimer.onTimer
MyTimer.onTimer
MyTimer.onTimer
[INFO] Starting HTTP server  on 0.0.0.0:8181

Я уже не знаю, что попробовать. Это может быть проблема с библиотекой Perfect, но я не могу найти ничего, что могло бы решить мои проблемы. Возможно, я могу запустить новый поток и запустить в нем свой таймер, но это становится немного сложным?


person Aurelien Maigret    schedule 26.12.2016    source источник


Ответы (1)


Если вы используете Perfect серьезно, пожалуйста, не используйте материалы Foundation. Попробуйте Perfect Threading: http://www.perfect.org/docs/thread.html

import PerfectThread 
#if os(Linux)
import GlibC
#else
import Darwin
#endif

Threading.dispatch {
  sleep(10) // wait for 10 seconds
  doSomething()
}//end threading

это безопасно и просто
очень типичное кодирование на стороне сервера

person PerfectlyRock    schedule 26.12.2016
comment
Большое спасибо. Это потрясающе. :) - person Aurelien Maigret; 27.12.2016
comment
Я не уверен, о чем вы говорили. Вы можете использовать Threading.dispatch { forloop() или whileloop() } или, альтернативно, сделать function() { Threading.dispatch {} }, а затем for _ in 0 ... 10 { function() } - person PerfectlyRock; 01.02.2017
comment
Я попытался выполнить развертывание с помощью этого кода, и, видимо, нужно обновить import GlibC до import SwiftGlibc. Тогда это работало плавно. Пример этого я нашел в другом месте: github.com/PerfectlySoft/Perfect-NewRelic- Linux/фиксация/ - person agrippa; 04.08.2018