Ios 在Swift中调用串行队列中的函数

Ios 在Swift中调用串行队列中的函数,ios,swift,queue,grand-central-dispatch,nsnotificationcenter,Ios,Swift,Queue,Grand Central Dispatch,Nsnotificationcenter,我通过观察NotificationCenter调用了一个函数: 然后是函数: @objc func observedPosition(_ notification: NSNotification) { if let data = notification.object as? Int { self.sendPosition(from: data) } 由于此函数可以在很短的时间内多次调用,因此我希望将其添加到队列中,并仅在前一个sendPosition完成后调用send

我通过观察NotificationCenter调用了一个函数:

然后是函数:

@objc func observedPosition(_ notification: NSNotification) {
   if let data = notification.object as? Int {
      self.sendPosition(from: data)
   }
由于此函数可以在很短的时间内多次调用,因此我希望将其添加到队列中,并仅在前一个sendPosition完成后调用sendPosition

我尝试过这样的方法,但不知道这是否正确:

@objc func observedPosition(_ notification: NSNotification) {
    let queue = DispatchQueue(label: queueLabel, attributes: [], targer: nil)
    queue.sync {
        if let data = notification.object as? Int {
            self.sendPosition(from: data)
        }
    }
}

这是正确的,只要您确保使用相同的队列调度所有sendPosition方法调用。例如,如果此队列是一个局部变量,则它将毫无用处。

Details Xcode版本10.3 10G8,Swift 5 主要特征 实现了自己的队列,该队列将逐个执行函数 所有操作都存储在数组中 线程安全 解决方案 用法示例 使用示例结果
我已经更新了代码,它是NotificationCenter调用的函数中的一个变量。实际上,我的问题应该是关于这个队列作为一个变量。@codddeer123因为它在你的帖子中,那个队列根本没有帮助。每个observedPosition:call将建立一个新的、独立的队列,该队列将立即执行该任务,而不考虑其他队列。您需要一个在所有observedPosition调用中共享的队列:好的,那么我是否应该将var queue放在这个函数之外,然后像我在文章中所做的那样调用queue.sync{}?@codddeer123最好让队列来,因为只有一个队列,您不会重新分配给它。现在,这个队列的确切位置取决于您的需求。observedPosition是否有必要确保sendPosition调用之间的独占性,或者所有sendPosition调用(无论调用方如何)是否都必须始终是独占的?因此,最好在sendPositionfrom的实现中强制执行这一点:。您可以获取现有的整个sendPosition主体,并将其包装在queue.sync调用中。您也可以以类似的方式将此队列用于您希望与sendPositionfrom互斥的所有其他调用:嗨,伙计,我遇到了错误在作用域中找不到类型“StackableOperationsCuncurentQueue”,您定义它了吗?@fam我刚刚检查了代码-它可以工作。请检查您是否复制了所有代码谢谢,我可以问这个问题吗?我有一个聊天屏幕+添加新消息聊天时有新消息工作完美,但有时当另一个VC出现在这个聊天屏幕上面,我得到一些布局问题,我想可能是聊天屏幕没有完全显示->得到这个错误,所以我想添加新消息到您定义的队列,并调用同步添加到聊天屏幕,你的解决方案行得通吗?非常感谢much@famfamfam没有任何代码,很难帮助您。我建议您创建一个新问题,并在那里共享一些代码。
@objc func observedPosition(_ notification: NSNotification) {
    let queue = DispatchQueue(label: queueLabel, attributes: [], targer: nil)
    queue.sync {
        if let data = notification.object as? Int {
            self.sendPosition(from: data)
        }
    }
}
// MARK: - StackableOperationsQueue performs functions from the stack one by one (serial performing)

class StackableOperationsQueue {
    private let semaphore = DispatchSemaphore(value: 1)
    private lazy var operations = [QueueOperation]()
    private lazy var isExecuting = false

    fileprivate func _append(operation: QueueOperation) {
        semaphore.wait()
        operations.append(operation)
        semaphore.signal()
        execute()
    }

    func append(operation: QueueOperation) { _append(operation: operation) }

    private func execute() {
        semaphore.wait()
        guard !operations.isEmpty, !isExecuting else { semaphore.signal(); return }
        let operation = operations.removeFirst()
        isExecuting = true
        semaphore.signal()
        operation.perform()
        semaphore.wait()
        isExecuting = false
        semaphore.signal()
        execute()
    }
}

// MARK: - StackableOperationsCuncurentQueue performs functions from the stack one by one (serial performing) but in cuncurent queue

class StackableOperationsCuncurentQueue: StackableOperationsQueue {
    private var queue: DispatchQueue
    init(queue: DispatchQueue) { self.queue = queue }
    override func append(operation: QueueOperation) {
        queue.async { [weak self] in self?._append(operation: operation) }
    }
}

// MARK: QueueOperation interface

protocol QueueOperation: class {
    var сlosure: (() -> Void)? { get }
    var actualityCheckingClosure: (() -> Bool)? { get }
    init (actualityCheckingClosure: (() -> Bool)?, serialClosure: (() -> Void)?)
    func perform()
}

extension QueueOperation {
    // MARK: - Can queue perform the operation `сlosure: (() -> Void)?` or not
    var isActual: Bool {
        guard   let actualityCheckingClosure = self.actualityCheckingClosure,
                self.сlosure != nil else { return false }
        return actualityCheckingClosure()
    }
    func perform() { if isActual { сlosure?() } }

    init (actualIifNotNill object: AnyObject?, serialClosure: (() -> Void)?) {
        self.init(actualityCheckingClosure: { return object != nil }, serialClosure: serialClosure)
    }
}

class SerialQueueOperation: QueueOperation {
    let сlosure: (() -> Void)?
    let actualityCheckingClosure: (() -> Bool)?
    required init (actualityCheckingClosure: (() -> Bool)?, serialClosure: (() -> Void)?) {
        self.actualityCheckingClosure = actualityCheckingClosure
        self.сlosure = serialClosure
    }
}
class TEST {

    private lazy var stackableOperationsQueue: StackableOperationsCuncurentQueue = {
        let queue = DispatchQueue(label: "custom_queue", qos: .background,
                                  attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
        return StackableOperationsCuncurentQueue(queue: queue)
    }()

    private func addOperationToQueue(closure: (() -> Void)?) {
        let operation = SerialQueueOperation(actualIifNotNill: self) { closure?() }
        stackableOperationsQueue.append(operation: operation)
        print("!!!! Function added ")
    }

    private func simpleFunc(index: Int) {
        print("Func \(index) started")
        sleep(UInt32(index+1));
        print("Func \(index) ended")
    }

    func run() {
        (0...3).forEach { index in
            addOperationToQueue { [weak self] in self?.simpleFunc(index: index) }
        }
    }
}

let test = TEST()
test.run()
//  qos: .background
!!!! Function added 
!!!! Function added 
!!!! Function added 
!!!! Function added 
Func 0 started
Func 0 ended
Func 1 started
Func 1 ended
Func 2 started
Func 2 ended
Func 3 started
Func 3 ended


//  qos: .userInitiated
!!!! Function added 
Func 0 started
!!!! Function added 
!!!! Function added 
!!!! Function added 
Func 0 ended
Func 1 started
Func 1 ended
Func 2 started
Func 2 ended
Func 3 started
Func 3 ended