简体   繁体   English

如何正确使用OperationQueue?

[英]How to use correctly OperationQueue?

This question is relative to this thread: how-to-set-the-height-of-a-cell-depending-on-a-uilabel-with-a-typewriter-effect 这个问题是关于这个线程的: 如何根据一个打字机效果来设置一个单元标签的高度

In my tableViewController, my cell contains UILabel with a typewriter effect managed with setTextWithTypeAnimation ; 在我的tableViewController中,我的单元格包含UILabel,它具有由setTextWithTypeAnimation管理的打字机效果;

func configureCell(tableView: UITableView, cell: ParagraphTableViewCell, atIndexPath indexPath: IndexPath) {

    let paragraph = paragraphArray[indexPath.row] as! Paragraph
    cell.paragraph = paragraph

        self.queue = OperationQueue()

        let operation1 = BlockOperation(block: {

            cell.dialogueLabel.setTextWithTypeAnimation(typedText: paragraph.dialogueLabel.text!, queue:self.queue, callBackAfterCharacterInsertion: {

                self.tableView.beginUpdates()
                self.tableView.endUpdates()
            })

        })


    operation1.completionBlock = {

    cell.buttonsStackViewHeightConstraint.constant = CGFloat(HEIGHT_CONSTRAINT)

    UIView.animate(withDuration: 0.3, animations: {
        cell.contentView.layoutIfNeeded()
    }, completion: nil)

    }

    queue.addOperation(operation1)

   }

My typewriter is inside a UILabel extension : 我的打字机在UILabel扩展中:

extension UILabel {

func setTextWithTypeAnimation(typedText: String, queue: OperationQueue, characterInterval: TimeInterval = 0.05, callBackAfterCharacterInsertion:(()->())?) {

    text = ""

    for (_, character) in typedText.characters.enumerated() {

        if queue.isSuspended {

            OperationQueue.main.isSuspended = true
            OperationQueue.main.cancelAllOperations()
            break;
        }

        OperationQueue.main.addOperation {

            self.text = self.text! + String(character)
            callBackAfterCharacterInsertion?()

        }

        Thread.sleep(forTimeInterval: characterInterval)
    }
}
}

First I used DispatchQueue to manage the animation inside a cell (see how-to-set-the-height-of-a-cell-depending-on-a-uilabel-with-a-typewriter-effect ), but I needed to stop the thread when user closes the view controller. 首先,我使用DispatchQueue来管理单元格内的动画(请参见如何设置具有一个打字机效果的uilabel的单元格高度 ),但是我需要当用户关闭视图控制器时,停止线程。 That's why I'm using OperationQueue (DispatchQueue cannot be stopped) 这就是为什么我使用OperationQueue(无法停止DispatchQueue)的原因

@IBAction func closeViewController(sender: AnyObject) {

    dismiss(animated: true, completion: nil)

        if self.queue != nil {

            self.queue.isSuspended = true
            self.queue.cancelAllOperations()
            self.queue = nil
    }
}

The issue is when completionBlock is called, the app crashes when I try to update a layout constraint. 问题是当调用completionBlock时,当我尝试更新布局约束时应用程序崩溃。

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread.

How can avoid this crash? 如何避免这种崩溃?

You must call UI stuff on the mainQueue . 必须mainQueue上调用UI内容。

Example: 例:

operation1.completionBlock = {
    DispatchQueue.main.async {
        cell.buttonsStackViewHeightConstraint.constant = CGFloat(HEIGHT_CONSTRAINT)

        UIView.animate(withDuration: 0.3, animations: {
            cell.contentView.layoutIfNeeded()
        }, completion: nil)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM