Post

Replies

Boosts

Views

Activity

Reply to For the property modifiers of XIB controls, should we use strong or weak?
Our code is like this: @interface LLLineMoreView() <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> @property (strong, nonatomic) IBOutlet UIView *topLineView; @end Exception Category: mach Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000008 Crashed Thread: 0 CrashDoctor Diagnosis: Attempted to dereference garbage pointer 0x8. Thread 0 Crashed: 0 CoreFoundation 0x000000018bb3ea7c _CFXNotificationRegistrarAddObserver + [ : 368] 1 CoreFoundation 0x000000018bb3ea0c _CFXNotificationRegistrarAddObserver + [ : 256] 2 CoreFoundation 0x000000018bb3e890 CFXNotificationRegistrarAdd + [ : 576] 3 CoreFoundation 0x000000018bb3e070 _CFXNotificationRegisterObserver + [ : 248] 4 UIKitCore 0x000000018e3a39ac UILabelCommonInit + [ : 188] 5 UIKitCore 0x000000018e8133cc -[UILabel initWithCoder:] + [ : 212] 6 UIFoundation 0x000000019747aaa4 UINibDecoderDecodeObjectForValue + [ : 684] 7 UIFoundation 0x000000019747ac30 UINibDecoderDecodeObjectForValue + [ : 1080] 8 UIFoundation 0x000000019747a6f8 -[UINibDecoder decodeObjectForKey:] + [ : 308] 9 UIKitCore 0x000000018e6c6550 -[UIView initWithCoder:] + [ : 800] 10 UIFoundation 0x000000019747aaa4 UINibDecoderDecodeObjectForValue + [ : 684] 11 UIFoundation 0x000000019747ac30 UINibDecoderDecodeObjectForValue + [ : 1080] 12 UIFoundation 0x000000019747a6f8 -[UINibDecoder decodeObjectForKey:] + [ : 308] 13 UIKitCore 0x000000018e6c6550 -[UIView initWithCoder:] + [ : 800] 14 UIKitCore 0x000000018eccd94c -[UICollectionReusableView initWithCoder:] + [ : 68] 15 UIKitCore 0x000000018eccde3c -[UICollectionViewCell initWithCoder:] + [ : 68] 16 UIKitCore 0x000000018e6c9700 -[UIClassSwapper initWithCoder:] + [ : 1544] 17 UIFoundation 0x000000019747aaa4 UINibDecoderDecodeObjectForValue + [ : 684] 18 UIFoundation 0x000000019747a6f8 -[UINibDecoder decodeObjectForKey:] + [ : 308] 19 UIKitCore 0x000000018e6c6034 -[UIRuntimeConnection initWithCoder:] + [ : 92] 20 UIFoundation 0x000000019747aaa4 UINibDecoderDecodeObjectForValue + [ : 684] 21 UIFoundation 0x000000019747ac30 UINibDecoderDecodeObjectForValue + [ : 1080] 22 UIFoundation 0x000000019747a6f8 -[UINibDecoder decodeObjectForKey:] + [ : 308] 23 UIKitCore 0x000000018e6c9030 -[NSCoder(UIIBDependencyInjectionInternal) _decodeObjectsWithSourceSegueTemplate:creator:sender:forKey:] + [ : 292] 24 UIKitCore 0x000000018e76f1cc -[UINib instantiateWithOwner:options:] + [ : 768] 25 UIKitCore 0x000000018e5eda0c -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + [ : 984] 26 UIKitCore 0x000000018e5ed5b8 -[UICollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:] + [ : 84] 27 lbank-iOS-LBank 0x0000000102bf1270 -[LBKBtmLineMoreView collectionView:cellForItemAtIndexPath:] + [LBKBtmLineMoreView.m : 255] 28 UIKitCore 0x000000018e6678e4 __112-[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:]_block_invoke.394 + [ : 52] 29 UIKitCore 0x000000018e33c828 +[UIView(Animation) performWithoutAnimation:] + [ : 76] 30 UIKitCore 0x000000018e5ee9dc -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + [ : 1208] 31 UIKitCore 0x000000018e5ec178 -[UICollectionView _createVisibleViewsForSingleCategoryAttributes:limitCreation:fadeForBoundsChange:] + [ : 524] 32 UIKitCore 0x000000018e4bcbc8 -[UICollectionView _createVisibleViewsForAttributes:fadeForBoundsChange:notifyLayoutForVisibleCellsPass:] + [ : 300] 33 UIKitCore 0x000000018e4b8d9c -[UICollectionView _updateVisibleCellsNow:] + [ : 3092] 34 UIKitCore 0x000000018e652bc8 -[UICollectionView layoutSubviews] + [ : 288] 35 UIKitCore 0x000000018e34b814 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + [ : 2424] 36 QuartzCore 0x000000018d659498 CA::Layer::layout_if_needed(CA::Transaction*) + [ : 496] 37 QuartzCore 0x000000018d659024 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + [ : 148] 38 QuartzCore 0x000000018d6ae0c4 CA::Context::commit_transaction(CA::Transaction*, double, double*) + [ : 472] 39 QuartzCore 0x000000018d624d8c CA::Transaction::commit() + [ : 648] 40 UIKitCore 0x000000018e3b33f0 _UIApplicationFlushCATransaction + [ : 84] 41 UIKitCore 0x000000018e3b089c __setupUpdateSequence_block_invoke_2 + [ : 332] 42 UIKitCore 0x000000018e3b0710 _UIUpdateSequenceRun + [ : 84] 43 UIKitCore 0x000000018e3b3040 schedulerStepScheduledMainSection + [ : 172] 44 UIKitCore 0x000000018e3b0c5c runloopSourceCallback + [ : 92] 45 CoreFoundation 0x000000018bb64f4c CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + [ : 28]
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’25
Reply to For the property modifiers of XIB controls, should we use strong or weak?
以上内容翻译成中文: 标准答案是 “视情况而定”。如果没有更多关于你遇到的崩溃的背景信息,我无法确定哪种建议最适合你的需求,但任何情况下的正确选择都取决于对 ARC(自动引用计数)和 UIKit 视图组合基础原理的理解。Xcode 在拖出 Outlet 时默认使用 weak 修饰符,这暗示了一个不错的默认选择,但我们还是通过一些常见示例,从内存引用的角度来理解相关概念。 重要提示:在接下来的图示中,每一条实线箭头代表强引用,虚线箭头代表弱引用。这些图示仅为概念示意,并非旨在传达特定的系统实现细节。 最常见的情况是,在 Interface Builder 中设计视图时,子视图会被添加到父视图中。当通过实例化 XIB 在内存中创建该视图时,父视图的 subviews 数组会包含这个子视图,因此父视图对其持有强引用 —— 这是因为子视图通过加入 subviews 数组而存在于视图层级中。如果该子视图的 IBOutlet 属性是 weak 的(左图),那么父视图对这个子视图只有一个强内存引用。如果你所做的只是通过调整属性来定制子视图(比如设置标签的文本或颜色),那么这个子视图会一直存在于内存中,因为 subviews 数组对它持有强引用。在这种情况下,使用 weak 是没问题的。 如果这个被弱引用的视图存在这样的使用场景:有时会从视图层级中移除,之后又重新添加回来,会发生什么呢?当它从视图层级中被移除时,子视图和父视图之间的引用关系会被解除,因此没有任何对象对它持有强引用,子视图就会被销毁。或许这就是你遇到的情况,或者是过去苹果给你那个特定建议的原因。 子视图从视图层级移除后被销毁,这到底是好是坏呢?如果它是被弱引用的,这或许有助于降低应用的整体内存占用,因为当那些可能较大的视图层级不再需要时,就不会再占用内存。但如果这个子视图之后经常需要重新添加到视图层级中,或者实例化成本很高,那么重新创建它就会产生消耗,这种情况下,自己管理一个对它的强引用可能是更好的选择(图示右侧)。 需要注意的是,上面所说的内容专门针对来自 XIB 的视图。故事板(Storyboards)会引入视图控制器,因此需要考虑的因素更多 —— 因为在故事板中更容易意外创建强引用循环,所以 weak 通常是更合适的选择。我们来看第二个图示,理解故事板的不同之处: 左图中,我们有一个视图控制器,其 view 属性已设置,并且该视图控制器还直接持有一个对子视图的强引用。如果由于某种原因(比如收到内存压力通知),视图控制器需要将其 view 设为 nil,会发生什么呢?如右图所示,对嵌套子视图的强引用会意外导致整个视图层级被保留在内存中,这就违背了视图控制器为响应内存压力而移除其视图的初衷,显然是视图控制器实现中的一个 bug。因此,在故事板中,对 IBOutlet 视图属性使用 weak 修饰符通常是更好的默认选择,这样可以避免意外的引用循环。
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’25