Я только что загрузил последнюю версию XCode (7.1 beta) и начал играть с iOS9.
У меня было приложение, прекрасно работающее без ошибок в iOS8, но теперь я получаю следующую ошибку от переопределения метода drawRect в классе UITableViewCell:
"Это приложение изменяет механизм автозапуска из фонового потока, что может привести к повреждению двигателя и странным сбоям. Это приведет к исключению в будущей версии".
здесь обратная трассировка:
Stack:(
0 CoreFoundation 0x000000010a749f65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000109dcfdeb objc_exception_throw + 48
2 CoreFoundation 0x000000010a749e9d +[NSException raise:format:] + 205
3 Foundation 0x0000000109b442e5 _AssertAutolayoutOnMainThreadOnly + 79
4 Foundation 0x00000001099a4ece -[NSISEngine withBehaviors:performModifications:] + 31
5 UIKit 0x000000010b9d425b -[UIView(AdditionalLayoutSupport) _withAutomaticEngineOptimizationDisabledIfEngineExists:] + 58
6 UIKit 0x000000010b9d4d9e -[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded] + 254
7 UIKit 0x000000010b702760 -[UITableViewCellContentView updateConstraintsIfNeeded] + 185
8 UIKit 0x000000010b9d5ab3 -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeeded] + 272
9 UIKit 0x000000010b1e6274 -[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 159
10 UIKit 0x000000010b1f5d84 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710
11 QuartzCore 0x000000010ae1059a -[CALayer layoutSublayers] + 146
12 QuartzCore 0x000000010ae04e70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
13 QuartzCore 0x000000010ae04cee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
14 QuartzCore 0x000000010adf9475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
15 QuartzCore 0x000000010ae26c0a _ZN2CA11Transaction6commitEv + 486
16 QuartzCore 0x000000010ae2737c _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
17 CoreFoundation 0x000000010a675967 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
18 CoreFoundation 0x000000010a6758d7 __CFRunLoopDoObservers + 391
19 CoreFoundation 0x000000010a66ae4c CFRunLoopRunSpecific + 524
20 CoreFoundation 0x000000010a71e011 CFRunLoopRun + 97
21 SDWebImage 0x000000010971773c -[SDWebImageDownloaderOperation start] + 1868
22 Foundation 0x0000000109961e47 __NSOQSchedule_f + 194
23 libdispatch.dylib 0x000000010d93849b _dispatch_client_callout + 8
24 libdispatch.dylib 0x000000010d91e8ec _dispatch_queue_drain + 2215
25 libdispatch.dylib 0x000000010d91de0d _dispatch_queue_invoke + 601
26 libdispatch.dylib 0x000000010d920a56 _dispatch_root_queue_drain + 1420
27 libdispatch.dylib 0x000000010d9204c5 _dispatch_worker_thread3 + 111
28 libsystem_pthread.dylib 0x000000010dc80a9d _pthread_wqthread + 729
29 libsystem_pthread.dylib 0x000000010dc7e3dd start_wqthread + 13
)
Вот метод drawRect:
override func drawRect(rect: CGRect) {
super.drawRect(rect)
let cellRect = rect
// Values
let buttonBoxX = CELL_MARGIN + CELL_MARGIN/2
let buttonBoxY = cellRect.height - buttonBoxHeight
let buttonBoxWidth = rect.width - CELL_MARGIN * 3
// Set Button Box
let buttonBoxRect = CGRectMake(buttonBoxX, buttonBoxY, buttonBoxWidth, buttonBoxHeight )
let buttonBox = UIBezierPath(roundedRect: buttonBoxRect, byRoundingCorners: [.BottomRight, .BottomLeft], cornerRadii: CGSize(width: CORNER_RADIUS, height: CORNER_RADIUS)) // Create the path
UIColor.whiteColor().setFill() // Set the Fill to be white
buttonBox.fill()
}
Мое понимание (см. этот вопрос) заключается в том, что сложные вычисления и т.д. должны выполняться в фоновом потоке и обновлении пользовательского интерфейса в основном потоке, потому что пользовательский интерфейс не является надежным потоком.
Однако, если я использую следующее:
override func drawRect(rect: CGRect) {
super.drawRect(rect)
let cellRect = rect
// Values
let buttonBoxX = CELL_MARGIN + CELL_MARGIN/2
let buttonBoxY = cellRect.height - buttonBoxHeight
let buttonBoxWidth = rect.width - CELL_MARGIN * 3
// Set Button Box
let buttonBoxRect = CGRectMake(buttonBoxX, buttonBoxY, buttonBoxWidth, buttonBoxHeight )
let buttonBox = UIBezierPath(roundedRect: buttonBoxRect, byRoundingCorners: [.BottomRight, .BottomLeft], cornerRadii: CGSize(width: CORNER_RADIUS, height: CORNER_RADIUS)) // Create the path
UIColor.whiteColor().setFill() // Set the Fill to be white
dispatch_async(dispatch_get_main_queue(), {
buttonBox.fill()
})
}
Теперь я получаю ошибку CGContext...
<Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextAddPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextDrawPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextAddPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextDrawPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
<Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Любые предложения?
РЕШЕНИЕ: ОК. вот сделка. Я загружал изображение в UIImageView асинхронно, но не "рисовал" его в пользовательском интерфейсе в основном потоке, а в фоновом потоке. Более того; Я вызывал setNeedsDisplay в UITableViewCell после добавления изображения в пользовательский интерфейс, тем самым снова вызвав метод drawRect... но на этот раз в фоновом потоке.