How to check whether it is possible to use a c Object lens with weak reference in ARC?

Apple mentions two methods for supportsWeakPointers , which is described in the release notes for ARC, but has never been mentioned in the real-world runtime and frameworks. It should also be noted that this method is actually ignored in practice. Another method is allowsWeakReference , which is not registered anywhere but declared in NSObject.h as follows.

 - (BOOL)allowsWeakReference NS_UNAVAILABLE; - (BOOL)retainWeakReference NS_UNAVAILABLE; 

Attempting to call allowsWeakReference at run time causes the program to crash with the next stack trace

 objc[17337]: Do not call -_isDeallocating. #0 0x00007fff9900f768 in _objc_trap () #1 0x00007fff9900f8aa in _objc_fatal () #2 0x00007fff9901bd90 in _objc_rootIsDeallocating () #3 0x00007fff97e92ce9 in -[NSObject _isDeallocating] () #4 0x00007fff97b5fad5 in -[NSObject(NSObject) allowsWeakReference] () #5 0x00007fff97dfe021 in -[NSObject performSelector:] () ... ... #11 0x00007fff97a5fd32 in __-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_1 () #12 0x00007fff97dafaaa in _CFXNotificationPost () #13 0x00007fff97a4bfe7 in -[NSNotificationCenter postNotificationName:object:userInfo:] () #14 0x00007fff8fa0460f in -[NSApplication _postDidFinishNotification] () #15 0x00007fff8fa04375 in -[NSApplication _sendFinishLaunchingNotification] () #16 0x00007fff8fa0303c in -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] () #17 0x00007fff8fa02d9d in -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] () #18 0x00007fff97df9591 in -[NSObject performSelector:withObject:withObject:] () #19 0x00007fff97a827eb in __-[NSAppleEventManager setEventHandler:andSelector:forEventClass:andEventID:]_block_invoke_1 () #20 0x00007fff97a81772 in -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] () #21 0x00007fff97a81600 in _NSAppleEventManagerGenericHandler () #22 0x00007fff96623c25 in aeDispatchAppleEvent () #23 0x00007fff96623b03 in dispatchEventAndSendReply () #24 0x00007fff966239f7 in aeProcessAppleEvent () #25 0x00007fff92101af9 in AEProcessAppleEvent () #26 0x00007fff8fa001a9 in _DPSNextEvent () #27 0x00007fff8f9ff861 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] () #28 0x00007fff8f9fc19d in -[NSApplication run] () #29 0x00007fff8fc7ab88 in NSApplicationMain () 

So, how can I check if an object supports the formation of a weak reference to it if none of the methods can be used?

+4
source share
1 answer

Ended up breaking it together. Works for what I need it.

 @implementation NSObject (MAWeakReference) static NSSet *weakRefUnavailableClasses = nil; + (void)load { // https://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html weakRefUnavailableClasses = [NSSet setWithObjects: // Classes that don't support zeroing-weak references @"NSATSTypesetter", @"NSColorSpace", @"NSFont", @"NSFontManager", @"NSFontPanel", @"NSImage", @"NSMenuView", @"NSParagraphStyle", @"NSSimpleHorizontalTypesetter", @"NSTableCellView", @"NSTextView", @"NSViewController", @"NSWindow", @"NSWindowController", // In addition @"NSHashTable", @"NSMapTable", @"NSPointerArray", // TODO: need to add all the classes in AV Foundation nil]; } - (BOOL)ma_supportsWeakPointers { if ([self respondsToSelector:@selector(supportsWeakPointers)]) return [[self performSelector:@selector(supportsWeakPointers)] boolValue]; // NOTE: Also test for overriden implementation of allowsWeakReference in NSObject subclass. // We must use a bit of hackery here because by default NSObject allowsWeakReference causes // assertion failure and program crash if it is not called by the runtime Method defaultMethod = class_getInstanceMethod([NSObject class], @selector(allowsWeakReference)); Method overridenMethod = class_getInstanceMethod([self class], @selector(allowsWeakReference)); if (overridenMethod != defaultMethod) return [[self performSelector:@selector(allowsWeakReference)] boolValue]; // Make sure we are not one of classes that do not support weak references according to docs for (NSString *className in weakRefUnavailableClasses) if ([self isKindOfClass:NSClassFromString(className)]) return NO; // Finally, all tests pass, by default objects support weak pointers return YES; } @end 
+1
source

Source: https://habr.com/ru/post/1396144/


All Articles