ios - 如何正确使用OperationQueue?

标签 ios swift autolayout grand-central-dispatch nsoperationqueue

此问题与此线程相关:how-to-set-the-height-of-a-cell-depending-on-a-uilabel-with-a-typewriter-effect

在我的 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)

   }

我的打字机位于 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)
    }
}
}

首先,我使用 DispatchQueue 来管理单元格内的动画(请参阅 how-to-set-the-height-of-a-cell-depending-on-a-uilabel-with-a-typewriter-effect ),但是当用户关闭 View Controller 时我需要停止线程。这就是我使用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
    }
}

问题是当调用completionBlock时,当我尝试更新布局约束时应用程序崩溃。

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

如何避免这种崩溃?

最佳答案

必须调用mainQueue上的UI内容。

示例:

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

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

关于ios - 如何正确使用OperationQueue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44922577/

相关文章:

ios - 'UILabel ?' does not have a member named ' 文本'

ios - 是否可以实现在 UILabel 的文本属性更改时执行的 IBAction?

ios - 以编程方式将 UIView 添加到 UITableView 的底部

ios 7 自定义呈现和关闭过渡

ios - 调用函数后如何导航到不同的内容页面

ios - 快速功能完成

objective-c - systemLayoutSizeFittingSize :UILayoutFittingCompressedSize doesn't compress

cocoa - 我怎样才能得到窗口的contentView到 "hug"它的 subview

ios - 在当前位置蓝点之上覆盖透明 PNG

ios - 与 Swift StreamVideo SDK 命名冲突