提问人:olha 提问时间:5/25/2021 更新时间:5/26/2021 访问量:270
我们可以在将 Objc 对象从 void* “桥接”到 UIKit 对象之前检查它是否被解除分配吗?
Can we check if an Objc object was deallocated before "bridging" it from void* to UIKit object?
问:
我正在使用 QTouchposeApplication 库(特别是来自分支的类)。TRTouchposeApplication
develop
分支中的一个执行路径发生了崩溃,作者在分支中修复了它们。但是,其中一个崩溃仍然存在。master
develop
假设我们有一个 -dictionary,它存储对象而不保留它们:CF
UITouch
// Dictionary of touches being displayed. Keys are UITouch pointers and values are UIView pointers that visually represent
// the touch on-screen. (A CFMutableDictionaryRef is used because NSDictionary requries its keys to conform to the
// NSCopying protocol and UITouch doesn't. We don't need to retain either the UITouch or UIView instances because UITouch
// objects are persistent throughout a multi-touch sequence, and the UIViews are retained by their superview.)
CFMutableDictionaryRef _touchDictionary;
我们这样添加到字典中:UITouch
CFDictionarySetValue(_touchDictionary, (__bridge const void *)(touch), (__bridge const void *)(someUIView));
然后在某个时候由系统发布(我在我的项目中使用 ARC)。
因此,当我们尝试“解开”触摸时,它会崩溃。我收到一条带有 Xcode Address Sanitizer 的消息:UITouch
-[UITouch retain]: message sent to deallocated instance
所以崩溃的原因是我们将 ARC 对象存储为 ,所以如果这个对象被解除分配,就会崩溃。void*
__bridge
我见过 , , , 但没有看到像 .__bridge
__bridge_transfer
__bridge_retained
bridge_TRY
为了给这个崩溃写一个补丁,我想知道:
- 在这种情况下,我们能否以某种方式“安全地桥接”,并得到一个结果,如果触摸被解除分配。
UITouch = nil
- 我们是否可以以某种方式订阅“UITouch”解除分配,以便我们在触摸对象被删除和指针无效之前删除相应的内容?
UITouch
CFDictionary
- 还有其他方法可以解决这个问题吗?
答:
在第 83 行中,您使用 cycle 检查每个字典值,但在第 91 行中,您更改了字典大小。因此,最好在第 77 行添加其他,这将是相等的,并在第 91 行中删除数据,并在第 95 行中设置。for
outputDictionary
_touchDictionary
outputDictionary
_touchDictionary = outputDictionary
这样会更安全
评论
如果需要在键或值处存储弱指针,则需要使用而不是字典NSMapTable
看着这段代码,我相信字典应该保留触摸和视图。内存管理的简单规则是“保留你关心的东西,当你不再关心时释放”。很少有理由依靠其他对象来为你保留东西。
“非保留”CFDictionaries 的优点是,它们允许您存储对保留和释放没有响应的内容(例如,错位的内存)。但通常,您应该使用标准回调对它们启用正常的内存管理。取而代之的是:
_touchDictionary = CFDictionaryCreateMutable(NULL, 10, NULL, NULL);
用:
_touchDictionary = CFDictionaryCreateMutable(NULL, 10,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
然后字典将为您保留其键和值。
在手势完成后,请小心按住 UITouch。文档禁止这样做:
触摸对象在整个多点触控序列中持续存在。您可以在处理多点触控序列时存储对触摸的引用,只要在序列结束时释放该引用即可。如果需要在多点触控序列之外存储有关触摸的信息,请从触摸中复制该信息。
但我不认为你一定做错了。崩溃发生在您移除触摸的点上,我假设这是在序列的末尾。
只是为了谈谈你的其他一些想法:
在这种情况下,我们能否以某种方式“安全地桥接”,并得到一个结果 UITouch = nil,如果触摸被解除分配。
是的,但这需要弱指针,这可能是一个太大的变化。Cy-4AH 的 NSMapTable 建议可以做到这一点,但您需要在整个代码中进行更改。
我们能否以某种方式订阅“UITouch”释放
是的,但不要。:D您可以附加一个具有自己的关联对象,当它附加到的对象被释放时,它将触发,然后您可以执行响应操作。但这对于IMO这个问题来说太过分了。如果需要示例,请参阅 PMKVObserverDeallocSpy。dealloc
评论
associated object
评论
CFDictionary
NSDictionary
NSDictionary