pickerview didSelect 随机崩溃:__cfrunloop_is_calling_out_to_a_source1_perform1_function
random crash on pickerview didSelect : __cfrunloop_is_calling_out_to_a_source1_perform1_function
我收到了以下崩溃报告,但我不明白 issue.Line 487 指向检查委托中的 pickerView 是否为特定变量。
Crashed: com.apple.main-thread
0 App 0x1001c5208 specialized NewCorrectiveVC.pickerView(UIPickerView, didSelectRow : Int, inComponent : Int) -> () (NewCorrectiveVC.swift:487)
1 App 0x1001c2028 @objc NewCorrectiveVC.pickerView(UIPickerView, didSelectRow : Int, inComponent : Int) -> () (NewCorrectiveVC.swift)
2 UIKit 0x197a83154 -[UIPickerView _sendSelectionChangedForComponent:notify:] + 116
3 UIKit 0x197a8338c -[UIPickerView _sendSelectionChangedFromTable:notify:] + 344
4 UIKit 0x197fb0424 -[UIPickerTableView _scrollingFinished] + 188
5 UIKit 0x197fb05fc -[UIPickerTableView scrollViewDidEndDecelerating:] + 28
6 UIKit 0x197b216ac -[UIScrollView(UIScrollViewInternal) _scrollViewDidEndDeceleratingForDelegate] + 132
7 UIKit 0x1979b6db0 -[UIScrollView(UIScrollViewInternal) _stopScrollDecelerationNotify:] + 332
8 UIKit 0x1979b68ec -[UIScrollView _smoothScrollWithUpdateTime:] + 2356
9 QuartzCore 0x194bc01bc CA::Display::DisplayLinkItem::dispatch(unsigned long long) + 44
10 QuartzCore 0x194bc0068 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 444
11 IOKit 0x191c27138 IODispatchCalloutFromCFMessage + 372
12 CoreFoundation 0x19195056c __CFMachPortPerform + 180
13 CoreFoundation 0x191968934 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
14 CoreFoundation 0x1919680e8 __CFRunLoopDoSource1 + 436
15 CoreFoundation 0x191965bcc __CFRunLoopRun + 1840
16 CoreFoundation 0x191894048 CFRunLoopRunSpecific + 444
17 GraphicsServices 0x19331a198 GSEventRunModal + 180
18 UIKit 0x1978792fc -[UIApplication _run] + 684
19 UIKit 0x197874034 UIApplicationMain + 208
20 App 0x100173d04 main (AppDelegate.swift:22)
21 libdispatch.dylib 0x1908785b8 (Missing)
代码:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
if pickerView == assignedTo
{
if employees.count > 0 {
selectedEmp = employees[row].employeeId
}
}
else if pickerView == category \this is line 487
{
if categories.count > 0 {
selectedCat = categories[row].wocategoryId
}
}
}
编辑:
不确定以下内容是否相关,但我确实有观察者链接到我的 pickerViews:
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressed))
assignedTo.addGestureRecognizer(longPressRecognizer)
let catLongPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.catLongPressed))
category.addGestureRecognizer(catLongPressRecognizer)
self.hideKeyboardWhenTappedAround()
self.scroll.keyboardDismissMode = .interactive
仅供参考:
public func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
我怀疑问题出在对 ==
.
的调用中
if pickerView == assignedTo
这不是你的意思。这会强制调用 ==
函数并尝试评估这两个对象之间的相等性。如果其中之一是 nil
就会崩溃。
pickerView
永远不应该是 nil
,但我遇到过 UIKit 为永远不应该是 nil
的参数发送 nil
的情况。 (如果在后台线程上调用 UIKit 方法,尤其会发生这种情况。请务必小心不要这样做,但也可能由于 UIKit 错误而发生。)
如果视图尚未加载,assignedTo
可以是 nil
。从理论上讲,在这种情况下你永远不应该得到这个调用,但同样,在存在错误的情况下也是可能的,最常见的原因是在主线程之外调用 UIKit 方法(任何 UIKit 方法;它并不总是与这个特定的选择器视图),但 UIKit 有时有它自己的错误。
无论如何,你的意思不是"is pickerView equal to assignedTo."你的意思是"is pickerView exactly the same thing as assignedTo."那是===
:
if pickerView === assignedTo
===
进行指针比较,因此即使面对无效 nil
它也是安全的。
请记住,这几乎肯定与竞争条件有关。当您在调试器中 运行 它不容易重现这一事实并不意味着什么。它可能在 10k 次尝试中发生一次,仅在 Release 中发生,仅在 iPhone 6 上发生。这就是竞争条件的本质。
我收到了以下崩溃报告,但我不明白 issue.Line 487 指向检查委托中的 pickerView 是否为特定变量。
Crashed: com.apple.main-thread
0 App 0x1001c5208 specialized NewCorrectiveVC.pickerView(UIPickerView, didSelectRow : Int, inComponent : Int) -> () (NewCorrectiveVC.swift:487)
1 App 0x1001c2028 @objc NewCorrectiveVC.pickerView(UIPickerView, didSelectRow : Int, inComponent : Int) -> () (NewCorrectiveVC.swift)
2 UIKit 0x197a83154 -[UIPickerView _sendSelectionChangedForComponent:notify:] + 116
3 UIKit 0x197a8338c -[UIPickerView _sendSelectionChangedFromTable:notify:] + 344
4 UIKit 0x197fb0424 -[UIPickerTableView _scrollingFinished] + 188
5 UIKit 0x197fb05fc -[UIPickerTableView scrollViewDidEndDecelerating:] + 28
6 UIKit 0x197b216ac -[UIScrollView(UIScrollViewInternal) _scrollViewDidEndDeceleratingForDelegate] + 132
7 UIKit 0x1979b6db0 -[UIScrollView(UIScrollViewInternal) _stopScrollDecelerationNotify:] + 332
8 UIKit 0x1979b68ec -[UIScrollView _smoothScrollWithUpdateTime:] + 2356
9 QuartzCore 0x194bc01bc CA::Display::DisplayLinkItem::dispatch(unsigned long long) + 44
10 QuartzCore 0x194bc0068 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 444
11 IOKit 0x191c27138 IODispatchCalloutFromCFMessage + 372
12 CoreFoundation 0x19195056c __CFMachPortPerform + 180
13 CoreFoundation 0x191968934 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
14 CoreFoundation 0x1919680e8 __CFRunLoopDoSource1 + 436
15 CoreFoundation 0x191965bcc __CFRunLoopRun + 1840
16 CoreFoundation 0x191894048 CFRunLoopRunSpecific + 444
17 GraphicsServices 0x19331a198 GSEventRunModal + 180
18 UIKit 0x1978792fc -[UIApplication _run] + 684
19 UIKit 0x197874034 UIApplicationMain + 208
20 App 0x100173d04 main (AppDelegate.swift:22)
21 libdispatch.dylib 0x1908785b8 (Missing)
代码:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
if pickerView == assignedTo
{
if employees.count > 0 {
selectedEmp = employees[row].employeeId
}
}
else if pickerView == category \this is line 487
{
if categories.count > 0 {
selectedCat = categories[row].wocategoryId
}
}
}
编辑:
不确定以下内容是否相关,但我确实有观察者链接到我的 pickerViews:
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressed))
assignedTo.addGestureRecognizer(longPressRecognizer)
let catLongPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.catLongPressed))
category.addGestureRecognizer(catLongPressRecognizer)
self.hideKeyboardWhenTappedAround()
self.scroll.keyboardDismissMode = .interactive
仅供参考:
public func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
我怀疑问题出在对 ==
.
if pickerView == assignedTo
这不是你的意思。这会强制调用 ==
函数并尝试评估这两个对象之间的相等性。如果其中之一是 nil
就会崩溃。
pickerView
永远不应该是 nil
,但我遇到过 UIKit 为永远不应该是 nil
的参数发送 nil
的情况。 (如果在后台线程上调用 UIKit 方法,尤其会发生这种情况。请务必小心不要这样做,但也可能由于 UIKit 错误而发生。)
assignedTo
可以是 nil
。从理论上讲,在这种情况下你永远不应该得到这个调用,但同样,在存在错误的情况下也是可能的,最常见的原因是在主线程之外调用 UIKit 方法(任何 UIKit 方法;它并不总是与这个特定的选择器视图),但 UIKit 有时有它自己的错误。
无论如何,你的意思不是"is pickerView equal to assignedTo."你的意思是"is pickerView exactly the same thing as assignedTo."那是===
:
if pickerView === assignedTo
===
进行指针比较,因此即使面对无效 nil
它也是安全的。
请记住,这几乎肯定与竞争条件有关。当您在调试器中 运行 它不容易重现这一事实并不意味着什么。它可能在 10k 次尝试中发生一次,仅在 Release 中发生,仅在 iPhone 6 上发生。这就是竞争条件的本质。