如何正确使用OperationQueue?
How to use correctly OperationQueue?
此问题与此线程有关:
在我的 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 来管理单元格内的动画(参见 ),但我需要在用户关闭视图控制器时停止线程。这就是我使用 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.
如何避免这种崩溃?
您必须调用 UI
mainQueue
上的内容。
示例:
operation1.completionBlock = {
DispatchQueue.main.async {
cell.buttonsStackViewHeightConstraint.constant = CGFloat(HEIGHT_CONSTRAINT)
UIView.animate(withDuration: 0.3, animations: {
cell.contentView.layoutIfNeeded()
}, completion: nil)
}
}
此问题与此线程有关:
在我的 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 来管理单元格内的动画(参见
@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.
如何避免这种崩溃?
您必须调用 UI
mainQueue
上的内容。
示例:
operation1.completionBlock = {
DispatchQueue.main.async {
cell.buttonsStackViewHeightConstraint.constant = CGFloat(HEIGHT_CONSTRAINT)
UIView.animate(withDuration: 0.3, animations: {
cell.contentView.layoutIfNeeded()
}, completion: nil)
}
}