[CFString release]: message sent to deallocated instance - ios

I've been struggling with a strange problem for two days now. I went through every related question on SO but none solved the issue. I'm working on Xcode5. I'm using ARC and CoreData.
On iOS7 (simulator):
`[CFString release]: message sent to deallocated instance`
Thread 1, Queue : com.apple.main-thread
0 0x03c7d3ba in __kill ()
1 0x03c7c4b8 in kill$UNIX2003 ()
2 0x0347a921 in ___forwarding___ ()
3 0x0347a4ee in _CF_forwarding_prep_0 ()
4 0x02b7b002 in -[NSConcreteAttributedString dealloc] ()
5 0x02f66692 in objc_object::sidetable_release(bool) ()
6 0x02f65e81 in objc_release ()
7 0x02f66ce7 in (anonymous namespace)::AutoreleasePoolPage::pop(void*) ()
8 0x00739bc4 in CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) ()
9 0x0345253e in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
10 0x0345248f in __CFRunLoopDoObservers ()
11 0x034303b4 in __CFRunLoopRun ()
12 0x0342fb33 in CFRunLoopRunSpecific ()
13 0x0342f94b in CFRunLoopRunInMode ()
14 0x04bd19d7 in GSEventRunModal ()
15 0x04bd17fe in GSEventRun ()
16 0x0196794b in UIApplicationMain ()
17 0x0000262d in main
The Zombies Instruments point to the second line where I set the cell's text labels:
cell.txtLabel.text = _reservationModule.newReservationText;
cell.subtitleTxtLabel.text = _reservationModule.newReservationSubtitle;
_reservationModule is a Core Data entity featuring the string properties. It's defined in the view controller as #property (nonatomic, strong) ReservationModule *reservationModule;
The Zombie history:
Event Type ∆ RefCt RefCt Timestamp Responsible Library Responsible Caller
Malloc/Retain/Release (4) 01:01.114.922 CoreData _prepareResultsFromResultSet
0 Malloc +1 1 01:01.114.922 CoreData _prepareResultsFromResultSet
1 Retain +1 2 01:01.116.184 CoreData -[_CDSnapshot mutableCopy]
2 Release -1 1 01:01.318.588 MyApp -[ReservationModuleChoice2ViewController configureSubtitleImageTableViewCell:atIndexPath:]
3 Release -1 0 01:05.004.359 CoreData -[_CDSnapshot dealloc]
4 Zombie -1 01:07.441.465 CoreData -[_CDSnapshot dealloc]
They've never occurred on Xcode 4.6.x though.
Any help is highly appreciated!
Thanks!

The answer is trivial and hasn't anything to do with retain counters...
I oversaw that it isn't allowed to name variables/properties starting with new with ARC enabled. This obviously resulted in an over release thus generating the error...
From Apple documentation: https://developer.apple.com/library/ios/releasenotes/objectivec/rn-transitioningtoarc/introduction/introduction.html
To allow interoperation with manual retain-release code, ARC imposes a
constraint on method naming:
You cannot give an accessor a name that begins with new. This in turn
means that you can’t, for example, declare a property whose name
begins with new unless you specify a different getter

Related

UIMenuController crashes on macOS Monterey

My iOS app uses UIMenuController to show the Copy/Paste context menu. When I launch the app on macOS 12.0 and control-click (right click) with the mouse or the trackpad, the app crashes upon showing the menu with this crash log:
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: title)'
Last Exception Backtrace:
0 CoreFoundation 0x1be758118 __exceptionPreprocess + 220
1 libobjc.A.dylib 0x1be4a9808 objc_exception_throw + 60
2 CoreFoundation 0x1be828464 -[__NSCFString characterAtIndex:].cold.1 + 0
3 CoreFoundation 0x1be835270 -[__NSDictionaryM setObject:forKey:].cold.3 + 0
4 CoreFoundation 0x1be691590 -[__NSDictionaryM setObject:forKey:] + 904
5 UIKitCore 0x1e5b85998 -[_UIMenuBarItem properties] + 124
6 UIKitMacHelper 0x1d3bc7058 UINSNSMenuItemFromUINSMenuItem + 96
7 UIKitMacHelper 0x1d3bc6d60 _insertUINSMenuItemsIntoNSMenu + 844
8 UIKitMacHelper 0x1d3bc67c0 UINSNSMenuFromUINSMenu + 152
9 UIKitMacHelper 0x1d3bc6690 -[UINSMenuController _createNSMenu:forContextMenu:] + 92
10 UIKitMacHelper 0x1d3c3505c -[UINSMenuController _prepareToShowContextMenu:activityItemsConfiguration:] + 144
11 UIKitMacHelper 0x1d3c349c0 -[UINSMenuController showContextMenu:inWindow:atLocationInWindow:activityItemsConfiguration:] + 312
12 libdispatch.dylib 0x1be44ce60 _dispatch_call_block_and_release + 32
13 libdispatch.dylib 0x1be44ebac _dispatch_client_callout + 20
14 libdispatch.dylib 0x1be45d0ac _dispatch_main_queue_callback_4CF + 944
15 CoreFoundation 0x1be719e60 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
I tried the same with several iOS apps from other developers and all of them crash on macOS when I right-click with the mouse.
Has anyone found a workaround?
It's possible to fix this by swizzling the properties method on the private _UIMenuBarItem class. Obviously this comes with the usual disclaimer that this might get you rejected by Apple (but in practice that doesn't seem to cause rejections that often).
Here's the fix: The basic idea is to wrap the original method call in a #try/#catch block. The crash happens because the original implementation sometimes tries to insert a nil value for the title key into an NSDictionary. This workaround catches that exception and then returns a dummy dictionary to satisfy the caller.
UIMenuBarItemMontereyCrashFix.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// Helper class to apply a fix to prevent a crash on macOS Monterey when a user right-clicks in a text field
#interface UIMenuBarItemMontereyCrashFix : NSObject
/// Apply the crash fix. It will only be applied the first time it's called, subsequent calls are no-ops.
/// It will only have an effect when called on macOS Monterey or later.
+ (void)applyCrashFixIfNeeded;
#end
NS_ASSUME_NONNULL_END
UIMenuBarItemMontereyCrashFix.m
#import "UIMenuBarItemMontereyCrashFix.h"
#import <objc/runtime.h>
static BOOL hasCrashFixBeenApplied = NO;
#implementation UIMenuBarItemMontereyCrashFix
/// Apply the crash fix. It will only be applied the first time it's called, subsequent calls are no-ops.
+ (void)applyCrashFixIfNeeded
{
if (#available(macOS 12.0, *)) {} else {
// Bail if we are not running on Monterey
return;
}
if (!hasCrashFixBeenApplied) {
Class UnderscoreUIMenuBarItem = NSClassFromString(#"_UIMenuBarItem");
SEL selector = sel_getUid("properties");
Method method = class_getInstanceMethod(UnderscoreUIMenuBarItem, selector);
IMP original = method_getImplementation(method);
// The crash happens because in some instances the original implementation
// tries to insert `nil` as a value for the key `title` into a dictionary.
// This is how the fix works:
// We wrap the original implementation call in a #try/#catch block. When the
// exception happens, we catch it, and then return a dummy dictionary to
// satisfy the caller. The dummy has `isEnabled` set to NO, and `isHidden` set
// to YES.
IMP override = imp_implementationWithBlock(^id(id me) {
#try {
id res = ((id (*)(id))original)(me);
return res;
}
#catch(NSException *exception) {
return #{
#"allowsAutomaticKeyEquivalentLocalization" : #0,
#"allowsAutomaticKeyEquivalentMirroring" : #0,
#"defaultCommand" : #0,
#"identifier":#"com.apple.menu.application",
#"imageAlwaysVisible" : #0,
#"isAlternate" : #0,
#"isEnabled" : #0,
#"isHidden" : #1,
#"isSeparatorItem" : #0,
#"keyEquivalent" : #"",
#"keyEquivalentModifiers" : #0,
#"remainsVisibleWhenDisabled" : #0,
#"state" : #0,
#"title" : #""
};
}
});
method_setImplementation(method, override);
hasCrashFixBeenApplied = YES;
}
}
#end
Remember to add UIMenuBarItemMontereyCrashFix.h to your bridging header so you can call it from Swift. Then simply call UIMenuBarItemMontereyCrashFix.applyIfNeeded() somewhere during your app's startup sequence (for example in your AppDelegate).

Run-time crash BridgeFromObjectiveC when format date string to Foundation.Date

We've got kind of a weird bug in our app that only one user encounters so far (out of thousands) and I can't figure it out how to solve this, so maybe you can help me further.
It's about the following crash (run-time):
#0. Crashed: com.apple.main-thread
0 libswiftFoundation.dylib 0x10e51ec _TZFV10Foundation4Date36_unconditionallyBridgeFromObjectiveCfGSqCSo6NSDate_S0_ + 68
1 XXX 0x14d804 specialized static Loader._save(NSDictionary, Double, moc : NSManagedObjectContext) -> () (Loader.swift:149)
2 XXX 0x14d804 specialized static Loader._save(NSDictionary, Double, moc : NSManagedObjectContext) -> () (Loader.swift:149)
3 XXX 0x14286c static Loader.(registerUser(NSManagedObjectContext) -> ()).(closure #1) (Loader.swift)
4 Alamofire 0x5aea58 specialized DataRequest.(response<A where ...> (queue : DispatchQueue?, responseSerializer : A, completionHandler : (DataResponse<A.SerializedObject>) -> ()) -> Self).(closure #1).(closure #1) (ResponseSerialization.swift)
5 libdispatch.dylib 0x1b911797 _dispatch_call_block_and_release + 10
6 libdispatch.dylib 0x1b911783 _dispatch_client_callout + 22
7 libdispatch.dylib 0x1b915d05 _dispatch_main_queue_callback_4CF + 902
8 CoreFoundation 0x1c1ffd69 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
9 CoreFoundation 0x1c1fde19 __CFRunLoopRun + 848
10 CoreFoundation 0x1c1510ef CFRunLoopRunSpecific + 470
11 CoreFoundation 0x1c150f11 CFRunLoopRunInMode + 104
12 GraphicsServices 0x1d8fbb41 GSEventRunModal + 80
13 UIKit 0x214d5e83 UIApplicationMain + 150
14 XXX 0xb7b1c main (AppDelegate.swift:26)
15 libdyld.dylib 0x1b93e4eb start + 2
Line 149 of Loader.swift is:
let createDate : Foundation.Date = dateFormatter.date(from: eventCreated)!
It looks like it's an internal problem inside libswiftFoundation.dylib.
I've researched a lot about this problem and the only thing I could find on this was from Apple:
Some Objective-C methods in the SDKs may incorrectly annotate or assume a type to be nonnull rather than nullable. A type that Swift treats as a struct, such as NSURL (Foundation.URL) or NSDate (Foundation.Date), results in a run-time crash in a method with a name like bridgeFromObjectiveC; in other cases, it can lead to crashes or undefined behavior in user code. If you identify such a method, please file a report at bugreport.apple.com. As a workaround, add a trampoline function in Objective-C with the correct nullability annotations. For example, the following function will allow you to call FileManager'senumerator(at:includingPropertiesForKeys:options:errorHandler:) method with an error handler that accepts nil URLs:
https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html (under known issues)
With an example that looks like this:
static inline NSDirectoryEnumerator<NSURL *> * _Nullable
fileManagerEnumeratorAtURL(NSFileManager *fileManager, NSURL * _Nonnull url, NSArray<NSURLResourceKey> * _Nullable keys, NSDirectoryEnumerationOptions options, BOOL (^ _Nullable errorHandler)(NSURL * _Nullable errorURL, NSError * _Nonnull error)) {
return [fileManager enumeratorAtURL:url includingPropertiesForKeys:keys options:options errorHandler:^(NSURL * _Nonnull errorURL, NSError * _Nonnull error) {
return errorHandler(errorURL, error);
}];
}
I've already submitted a bug report for this issue, but still haven't got a response from Apple (after 7 days). I think this could fix the problem, but I'm not sure on how to port the given trampoline function (example) to a valid/working NSDate/DateFormatter version. Does someone know more about this problem and/or got it solved?

Watch app starts with error clientIdentifier for interfaceControllerID not found

I'm having a smartwatch app on watchos2. The app always worked but now when it starts I immediately get this error:
Lop_WatchKit_Extension[17535:7854201] *********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:447E0002 not found
I found some topics here on stackoverflow but nothing solved the problem.
In my case, this was due to a retain cycle in one InterfaceController of mine.
If you get the logs similar to:
[default] -[SPRemoteInterface
_interfaceControllerClientIDForControllerID:]:0000: ComF: clientIdentifier for interfaceControllerID:XXXXXXXX not found
&/or...
[default] _SendRecordedValues:000: ComF:<-Plugin controller ID
XXXXXXXX has no client identifier
First, figure out which InterfaceController has the controller ID XXXXXXXX.
Have this in awake(withContext:)
override func awake(withContext context: Any?) {
//...
if let id = self.value(forKey: "_viewControllerID") as? NSString {
let strClassDescription = String(describing: self)
print("\(strClassDescription) has the Interface Controller ID \(id)")
}
//...
}
This logs:
[Target.Classname: 0xYYYYYYYY] has the Interface Controller ID
XXXXXXXX
Once you identify the InterfaceController causing these logs, you can continue to debug.
It could be different in your case but in mine I had created a retain cycle with self in one of my closures within which took awhile to locate but I eventually broke the retain cycle with a [weak self] capture.
Basically, the error logs appear when an InterfaceController is trying to execute some code but it has already been released.
What I already had:
DispatchQueue.main.async {
self.doSomethingThatDoesSomethingAsync()
}
What I fixed:
DispatchQueue.main.async { [weak self] in
self?.doSomethingThatDoesSomethingAsync()
}
If you use didSet on any IBOutlets it will also throw this error in the logs.
class MyInterfaceController: WKInterfaceController {
#IBOutlet var myLabel: WKInterfaceLabel! {
didSet {
myLabel.setTitle("Test")
}
}
How #nickromano sad, it's happens when you use didSet with IBOutlets. Cause it's calls before awake(withContext context: Any?)
We can suppress this error if wrap it in DispatchQueue.main.async
#IBOutlet var statusLabel: WKInterfaceLabel! {
didSet {
DispatchQueue.main.async {
self.statusLabel.setHidden(true)
}
}
This has happened to me a few times and more times than not, it is because of a timer that is still firing in a just-previously dismissed WKInterfaceController that I did not catch.
Best thing to do aside from comparing ID's like in #staticVoidMan's answer is to read the call stack. In my case I was able to identify that the old timer was still firing based off these hints:
8 Foundation 0x00007fff214be867 __NSFireTimer + 67
9 CoreFoundation 0x00007fff207a8e3f __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
10 CoreFoundation 0x00007fff207a8912 __CFRunLoopDoTimer + 926
Here is the original call stack (for reference):
<MyApp.InterfaceController: 0x7fb3e4d2d020> has the Interface Controller ID 1EB00002
2021-05-26 14:44:06.632758-0600 MyApp WatchKit Extension[73392:3546879] [default] -[SPRemoteInterface _interfaceControllerClientIDForControllerID:]:2464: ComF: clientIdentifier for interfaceControllerID:1EB00007 not found. callStack:(
0 WatchKit 0x00007fff38d1a268 -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] + 220
1 WatchKit 0x00007fff38d1bfff __54+[SPRemoteInterface setController:key:property:value:]_block_invoke + 340
2 WatchKit 0x00007fff38d12323 spUtils_dispatchAsyncToMainThread + 30
3 WatchKit 0x00007fff38d1be60 +[SPRemoteInterface setController:key:property:value:] + 179
4 WatchKit 0x00007fff38d057af -[WKInterfaceObject _sendValueChanged:forProperty:] + 706
5 WatchKit 0x00007fff38d2a5f8 -[WKInterfaceObject _setImage:forProperty:] + 50
6 MyApp WatchKit Extension 0x000000010955531d $s26MyApp_WatchKit_Extension25ActivityIndicatorDelegateC06handleE5TimeryyF + 813
7 MyApp WatchKit Extension 0x000000010955537a $s26MyApp_WatchKit_Extension25ActivityIndicatorDelegateC06handleE5TimeryyFTo + 42
8 Foundation 0x00007fff214be867 __NSFireTimer + 67
9 CoreFoundation 0x00007fff207a8e3f __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
10 CoreFoundation 0x00007fff207a8912 __CFRunLoopDoTimer + 926
11 CoreFoundation 0x00007fff207a7ec5 __CFRunLoopDoTimers + 265
12 CoreFoundation 0x00007fff207a2546 __CFRunLoopRun + 1949
13 CoreFoundation 0x00007fff207a18be CFRunLoopRunSpecific + 567
14 GraphicsServices 0x00007fff25b49fd3 GSEventRunModal + 139
15 UIKitCore 0x00007fff43290f24 -[UIApplication _run] + 917
16 UIKitCore 0x00007fff43295c0b UIApplicationMain + 101
17 WatchKit 0x00007fff38d0de65 WKExtensionMain + 800
18 libdyld.dylib 0x00007fff20202db5 start + 1
19 ??? 0x0000000000000001 0x0 + 1
)
Have you changed the name of your module? If this is the case then you have to go through your storyboard and update it manually for all the Interfaces you have.
Edit with steps to fix:
Go to the storyboard and for each interface open the Identity inspector, then delete what's in Module and press enter, the new module should get auto-filled.

NewRelic crash with infinite recursion

iOS frequently crashes with infinite recursion with following stack:
#7801 0x01c96241 in _writeJSONValue ()
#7802 0x01c9a660 in ___writeJSONArray_block_invoke ()
#7803 0x04bbad86 in __53-[__NSArrayM enumerateObjectsWithOptions:usingBlock:]_block_invoke ()
#7804 0x04bbac92 in -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] ()
#7805 0x04b37ca5 in -[NSArray enumerateObjectsUsingBlock:] ()
....
#7822 0x04bbac92 in -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] ()
#7823 0x04b37ca5 in -[NSArray enumerateObjectsUsingBlock:] ()
#7824 0x01c9a571 in _writeJSONArray ()
#7825 0x01c96241 in _writeJSONValue ()
#7826 0x01c95f9d in -[_NSJSONWriter dataWithRootObject:options:error:] ()
#7827 0x01c98b57 in +[NSJSONSerialization dataWithJSONObject:options:error:] ()
#7828 0x001a7ec8 in ptrIntPtrParamHandler at /Users/jenkins/workspace/iOS v3 Agent -
EDIT, please look to the screen NewRelic generates the error, not mine code
This looks like an old bug with the agent (pre-v3.252). An update to the latest version of New Relic should fix this.

UIScrollView crashes if setContentOffset is called with animation

My application creates instances of a custom subclass of UIView and adds those instances placed horizontally adjacent to each other. When a new instance of my UIView class is created, I can add it to the UIScrollView and reset the contentsize. I then call
[UIScrollView setContentOffset:(some point) animated:NO].
This works just fine.
The issue is when I call the above mentioned method with animation, i.e.
[UIScrollView setContentOffset:(some point) animated:YES]
, the application crashes.
The call stack looks like this:
> #0 0x3145b870 in ___forwarding___ ()
> #1 0x313b6650 in _CF_forwarding_prep_0 ()
> #2 0x317d84a2 in -[UIAnimator stopAnimation:] ()
> #3 0x317d84a2 in -[UIAnimator stopAnimation:] ()
> #4 0x317d7f0e in -[UIAnimator(Static) _advance:withTimestamp:] ()
> #5 0x317d7e00 in -[UIAnimator(Static) _LCDHeartbeatCallback:] ()
> #6 0x3531d86e in CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) ()
> #7 0x3531d7c4 in CA::Display::IOMFBDisplayLink::callback(__IOMobileFramebuffer*,
> unsigned long long, unsigned long long, unsigned long long, void*) ()
> #8 0x33a56000 in IOMobileFramebufferVsyncNotifyFunc ()
> #9 0x36e3c60c in IODispatchCalloutFromCFMessage ()
> #10 0x31422f12 in __CFMachPortPerform ()
> #11 0x3142d522 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
> #12 0x3142d4c4 in __CFRunLoopDoSource1 ()
> #13 0x3142c312 in __CFRunLoopRun ()
> #14 0x313af4a4 in CFRunLoopRunSpecific ()
> #15 0x313af36c in CFRunLoopRunInMode ()
> #16 0x32888438 in GSEventRunModal ()
> #17 0x316b4cd4 in UIApplicationMain ()
When I enable Zombies, the application output produces:
*** -[__NSArrayM removeObject:]: message sent to deallocated instance 0x113dbb10
Additional Info: UIScrollView's delegate is never set. I am using ARC.
I found my issue.
I was calling the method that called setContentOffset from a background thread.
BackgroundThread --> My random processing method --> Setup new UIView and add it to UIScrollView --> Call setContentOffset with animations
The above flow causes the crash. When I called the same processing method from the main thread, it worked just fine.
Apparently iOS does not like animations called from a background thread.
One of the views in the scrollView is getting released. Probably you "jump" over it when you turn animation off - when its on, the system tries to get a series of "snapshots" of the changes, and when it tries to access the one view boom down you go. So you can enable Zombies and find out exactly what type of object is getting the message, and in the debugger you can probably "po" that object.
Another way to do it would be to write our own test animation, move the contentOffset say 20 pixels at a time in a loop with no animation, and watch to see when it crashes (it surely will)!

Resources