UITableViewCell通过UINib初始化为何出现崩溃?
问题描述
我通过UINib创建UITableViewCell并将其添加到contentView中,本地调试和TestFlight测试阶段都没出现报错,但Crashlytics后台显示有大量崩溃,崩溃调用栈如下:
0x102d20 std::__1::vector<unsigned char, geo::StdAllocator<unsigned char, ggl::Allocator> >::__append(unsigned long) + 208 1 VectorKit 0x102ce0 std::__1::vector<unsigned char, geo::StdAllocator<unsigned char, ggl::Allocator> >::__append(unsigned long) + 144 2 VectorKit 0x10b7cc ggl::BufferData::BufferData(unsigned long, ggl::BufferType, ggl::BufferChange, ggl::BufferUsage, unsigned long) + 196 3 VectorKit 0x200e38 6 VectorKit 0x61eb8 md::MapEngine::updateForConfigurationAndMode() + 1376 7 VectorKit 0xada9c md::MapEngine::MapEngine(float, float, float, bool, VKMapViewPurpose, std::__1::shared_ptr<md::TaskContext> const&, VKMapPurpose, std::__1::unique_ptr<md::AnimationManager, std::__1::default_delete<md::AnimationManager> >, geo::linear_map<md::MapEngineSetting, long long, std::__1::equal_to<md::MapEngineSetting>, std::__1::allocator<std::__1::pair<md::MapEngineSetting, long long> >, std::__1::vector<std::__1::pair<md::MapEngineSetting, long long>, std::__1::allocator<std::__1::pair<md::MapEngineSetting, long long> > > > const&, unsigned long long, GEOApplicationAuditToken*) + 13772 8 VectorKit 0x1070d8 md::MapEngine::interactiveMapEngine(float, bool, VKMapViewPurpose, geo::linear_map<md::MapEngineSetting, long long, std::__1::equal_to<md::MapEngineSetting>, std::__1::allocator<std::__1::pair<md::MapEngineSetting, long long> >, std::__1::vector<std::__1::pair<md::MapEngineSetting, long long>, std::__1::allocator<std::__1::pair<md::MapEngineSetting, long long> > > > const&, unsigned long long, GEOApplicationAuditToken*) + 152 9 VectorKit 0x2619fc -[VKMapView initShouldRasterize:inBackground:contentScale:auditToken:mapViewPurpose:allowsAntialiasing:] + 936 10 MapKit 0x141570 -[MKBasicMapView initWithFrame:andGlobe:shouldRasterize:allowsAntialiasing:] + 388 11 MapKit 0x75094 -[MKMapView _commonInitFromIB:gestureRecognizerHostView:locationManager:showsAttribution:showsAppleLogo:allowsAntialiasing:] + 1668 12 MapKit 0x7606c -[MKMapView initWithCoder:] + 252 13 UIFoundation 0x63588 UINibDecoderDecodeObjectForValue + 704 14 UIFoundation 0x637b4 UINibDecoderDecodeObjectForValue + 1260 15 UIFoundation 0x3a58 -[UINibDecoder decodeObjectForKey:] + 324 16 UIKitCore 0x45cac8 -[UIView initWithCoder:] + 976 17 UIFoundation 0x63588 UINibDecoderDecodeObjectForValue + 704 18 UIFoundation 0x637b4 UINibDecoderDecodeObjectForValue + 1260 19 UIFoundation 0x3a58 -[UINibDecoder decodeObjectForKey:] + 324 20 UIKitCore 0x45cac8 -[UIView initWithCoder:] + 976 21 UIKitCore 0x20310 -[UITableViewCellContentView initWithCoder:] + 48 22 UIFoundation 0x63588 UINibDecoderDecodeObjectForValue + 704 23 UIFoundation 0x637b4 UINibDecoderDecodeObjectForValue + 1260 24 UIFoundation 0x3a58 -[UINibDecoder decodeObjectForKey:] + 324 25 UIKitCore 0x45cac8 -[UIView initWithCoder:] + 976 26 UIKitCore 0xddd54 -[UITableViewCell initWithCoder:] + 100 27 0x20b8c8 init + 45 (LocationFieldTableViewCell.swift:45) 28 0x20ad98 init + 4341656984 (<compiler-generated>:4341656984) 29 UIKitCore 0x414d3c -[UIClassSwapper initWithCoder:] + 2120 30 UIFoundation 0x63588 UINibDecoderDecodeObjectForValue + 704 31 UIFoundation 0x3a58 -[UINibDecoder decodeObjectForKey:] + 324 32 UIKitCore 0x592ba8 -[UIRuntimeConnection initWithCoder:] + 132 33 UIFoundation 0x63588 UINibDecoderDecodeObjectForValue + 704 34 UIFoundation 0x637b4 UINibDecoderDecodeObjectForValue + 1260 35 UIFoundation 0x3a58 -[UINibDecoder decodeObjectForKey:] + 324 36 UIKitCore 0x595468 -[NSCoder(UIIBDependencyInjectionInternal) _decodeObjectsWithSourceSegueTemplate:creator:sender:forKey:] + 492 37 UIKitCore 0x5343e4 -[UINib instantiateWithOwner:options:] + 1052 38 0x209168 instanceFromNib + 74 (LocationFieldTableViewCell.swift:74)
崩溃原因分析
从调用栈能看出,崩溃根源是MKMapView通过nib解码初始化时,VectorKit内部的内存分配失败,最终触发了std::__1::vector::__append的崩溃。问题出在你的LocationFieldTableViewCell从nib实例化的流程中,涉及MKMapView的xib加载逻辑。
解决方法
1. 改用代码创建MKMapView(推荐)
直接放弃在nib里拖放MKMapView,改成在Cell的awakeFromNib或者初始化方法里用代码创建,手动添加约束:
override func awakeFromNib() { super.awakeFromNib() // 代码创建MapView let mapView = MKMapView(frame: .zero) mapView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(mapView) // 设置约束 NSLayoutConstraint.activate([ mapView.topAnchor.constraint(equalTo: contentView.topAnchor), mapView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), mapView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), mapView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) ]) }
2. 确保Cell在主线程初始化
检查instanceFromNib方法,必须保证nib实例化操作在主线程执行,添加线程校验:
static func instanceFromNib() -> LocationFieldTableViewCell { // 强制校验主线程,非主线程直接触发断言提醒 assert(Thread.isMainThread, "UITableViewCell必须在主线程初始化") let nib = UINib(nibName: "LocationFieldTableViewCell", bundle: nil) return nib.instantiate(withOwner: nil, options: nil).first as! LocationFieldTableViewCell }
3. 调整MKMapView的xib配置(如果必须保留nib)
如果一定要在nib里用MKMapView,尝试关闭一些可能导致渲染压力的选项:
- 关闭
Allows Antialiasing属性 - 暂时关闭
Shows User Location(如果开启的话) - 检查MapView的约束是否存在冲突或不合理的布局
4. 适配特定系统版本
如果崩溃集中在某几个iOS版本,查一下苹果官方文档,确认对应版本的MapKit有没有已知bug,针对性做版本适配。
内容的提问来源于stack exchange,提问作者OMANSAK
相关产品推荐
相关产品推荐

