Swift - 从回调内部编辑UITextView崩溃应用程序

时间:2014-07-29 02:20:32

标签: swift uitextview

我有以下代码生成HTTP请求,然后将结果输出到UITextView:

@IBOutlet var echoLog: UITextView!

@IBAction func sendEcho(sender: AnyObject) {
    let callback = { (textString: String) -> Void in
        self.echoLog.text = textString // App crashes here :(
    }
    HTTPRequest("http://localhost/echo", ["echo": "Echo!"], callback)
}

但是,当我致电sendEcho时,应用程序因此错误而崩溃:

2014-07-28 20:58:22.218 AppName[10463:144343] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation_Sim/UIFoundation-364/UIFoundation/TextSystem/NSLayoutManager_Private.m:1547
2014-07-28 20:58:22.231 AppName[10463:144343] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
*** First throw call stack:
(
    0   CoreFoundation                      0x00496ca6 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x01df08bf objc_exception_throw + 44
    2   CoreFoundation                      0x00496b3a +[NSException raise:format:arguments:] + 138
    3   Foundation                          0x00904d2e -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 102
    4   UIFoundation                        0x03344072 -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 418
    5   UIFoundation                        0x03343d6e -[NSLayoutManager(NSPrivate) _recalculateUsageForTextContainerAtIndex:] + 2017
    6   UIFoundation                        0x0337da43 -[NSLayoutManager textStorage:edited:range:changeInLength:invalidatedRange:] + 871
    7   UIFoundation                        0x0337db53 -[NSLayoutManager processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:] + 85
    8   UIFoundation                        0x033a7a7b -[NSTextStorage _notifyEdited:range:changeInLength:invalidatedRange:] + 153
    9   UIFoundation                        0x033a759a -[NSTextStorage processEditing] + 458
    10  UIFoundation                        0x033a7124 -[NSTextStorage endEditing] + 80
    11  UIFoundation                        0x033a71af -[NSTextStorage coordinateEditing:] + 67
    12  UIKit                               0x014938ae -[UITextView setAttributedText:] + 250
    13  UIKit                               0x01499745 -[UITextView setText:] + 149
    14  AppName                            0x00036216 _TFFC8AppName19FirstViewController8sendEchoFS0_FPSs9AnyObject_T_U_FOS_9JSONValueT_ + 1350
    15  AppName                            0x0003525a _TPA__TFFC8AppName19FirstViewController8sendEchoFS0_FPSs9AnyObject_T_U_FOS_9JSONValueT_ + 106
    16  AppName                            0x0001de86 _TFF8AppName11HTTPRequestFTSSGVSs10DictionarySSPSs9AnyObject__FOS_9JSONValueT__T_U_FTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError__T_ + 1350
    17  AppName                            0x0001d0a4 _TPA__TFF8AppName11HTTPRequestFTSSGVSs10DictionarySSPSs9AnyObject__FOS_9JSONValueT__T_U_FTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError__T_ + 100
    18  AppName                            0x0001e289 _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT__ + 41
    19  AppName                            0x0001d15a _TPA__TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT__ + 90
    20  AppName                            0x0001e2d7 _TTRXFo_iTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError___iT__XFo_oGSQS__oGSQS0__oGSQS1___dT__ + 55
    21  AppName                            0x0001d224 _TPA__TTRXFo_iTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError___iT__XFo_oGSQS__oGSQS0__oGSQS1___dT__ + 100
    22  AppName                            0x0001e36e _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFdCb_dGSQS__dGSQS0__dGSQS1___dT__ + 142
    23  CFNetwork                           0x02c36158 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 181
    24  Foundation                          0x0092da35 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    25  Foundation                          0x00854635 -[NSBlockOperation main] + 99
    26  Foundation                          0x00833a97 -[__NSOperationInternal _start:] + 700
    27  Foundation                          0x008337c9 -[NSOperation start] + 83
    28  Foundation                          0x00833613 __NSOQSchedule_f + 237
    29  libdispatch.dylib                   0x022ef3ff _dispatch_client_callout + 14
    30  libdispatch.dylib                   0x022d8578 _dispatch_queue_drain + 1424
    31  libdispatch.dylib                   0x022d7f90 _dispatch_queue_invoke + 142
    32  libdispatch.dylib                   0x022d9e06 _dispatch_root_queue_drain + 312
    33  libdispatch.dylib                   0x022dae67 _dispatch_worker_thread2 + 45
    34  libsystem_pthread.dylib             0x0263fdab _pthread_wqthread + 336
    35  libsystem_pthread.dylib             0x02643cce start_wqthread + 30
)
    libc++abi.dylib: terminating with uncaught exception of type NSException

提前致谢!

2 个答案:

答案 0 :(得分:9)

看起来你的问题是你不在主线上,在追踪的第二行。

由于HTTPRequest异步处理数据的性质,您可能仍在后台运行代码......这很好。毕竟说完了之后,你只需要进入主线程。

以下是如何修复它......

@IBAction func sendEcho(sender: AnyObject)
{
    let callback = {(textString: String) in 
        dispatch_sync(dispatch_get_main_queue())
        {
            self.echoLog.text = textString //Yay!
        }
    }
    HTTPRequest("http://localhost/echo", ["echo": "Echo!"], callback)
}

提醒时间只应在mainThread上执行UI更新。仅仅因为这样做会为这件事提供高优先级。通常,当您尝试在后台线程上执行UI更新时,您将看到执行代码与查看结果之间的延迟。在这种情况下,断言失败(我喜欢)。如果您不知道自己是否在主线程上,可以通过执行返回bool的NSThread.isMainThread()来查看它。

警告如果您在调用dispatch_sync(dispatch_get_main_queue()) {...}时已经在主线程上,您的应用会冻结,所以请确保您知道自己的线程是什么......

答案 1 :(得分:0)

Apple只允许您修改主事件循环上的UI组件。似乎HTTPRequest正在后台线程上运行回调,因此您必须在主线程上显式运行更改:

let callback = { (textString: String) -> Void in
    dispatch_async(dispatch_get_main_queue(), {
        self.echoLog.text = textString
    })
}