Call to a method Apple documents as not to be called
ID |
objectivec.correctness.calling_prohibited_method |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Api Misuse |
Language |
Objective-C |
Description
Reports a call to one of the runtime and platform entry points Apple documents as unusable rather than merely discouraged - retainCount, -[UIDevice uniqueIdentifier], dispatch_get_current_queue, +[NSThread exit], -[NSUserDefaults synchronize], and objc_msgSend invoked without being cast to the callee’s own prototype. The correct cast form of objc_msgSend and identifierForVendor are not reported, and neither is a same-named method the code base defines for itself where the receiver makes that clear.
Rationale
Each of these returns an answer the platform cannot make true. retainCount reports a number the runtime is free to change for its own reasons, so any decision taken on it is wrong the moment autorelease pools or the optimiser are involved. uniqueIdentifier was removed outright and its use is grounds for App Store rejection. dispatch_get_current_queue was deprecated precisely because the value it returns invites the deadlock test it appears to support - a queue can target another queue, so "am I on this queue" is not answerable. +[NSThread exit] ends the thread where it stands, leaving locks held and stack objects unreleased. synchronize has been a no-op since defaults began writing on their own, so calling it only blocks the caller. Uncast objc_msgSend is a genuine ABI fault on arm64, where arguments and return values are passed differently per prototype and the variadic declaration marshals them wrongly.
The following code illustrates the pattern detected by this rule:
@implementation Diagnostics
- (NSUInteger)ownersOf:(id)object {
// FLAGGED: Call to a method Apple documents as not to be called
return [object retainCount];
}
- (id)view { return nil; }
- (void)setCancelled:(BOOL)cancelled { }
@end
Remediation
Reason about ownership from the code rather than from retainCount. Use -[UIDevice identifierForVendor] or a value you generate and store in the keychain. Replace dispatch_get_current_queue with a queue-specific key set through dispatch_queue_set_specific and read with dispatch_get_specific. Let a thread’s entry point return instead of calling +[NSThread exit], and cancel work through NSOperation cancel. Drop synchronize entirely. Cast objc_msgSend to a function pointer with the exact prototype of the method being sent before calling it.