[MyClass initWithCoder:]: unrecognized selector sent to instance - On iOS16 - ios16

I am using the [NSKeyedUnarchiver unarchiveObjectWithData:result] methode for unarchiving NSData in my objective c bases app.
NSMutableArray *array = (NSMutableArray *)[NSKeyedUnarchiver unarchiveObjectWithData:result];
This is working pretty fine upto iOS15. But since iOS16 I am getting a crash that [MyClass initWithCoder:]: unrecognized selector sent to instance 0x281069760.
In iOS16 code is working fine when I am using an array of NSDictionary or any system types like NSString. But I am adding my own custom class objects to the array and it makes the issue. (More intersting fact is that issue is only in real devices, not in simulators.)
I can see that unarchiveObjectWithData methos is depricated. So as suggested in xcode, now I have tried
NSError *err;
#try {
NSMutableArray *array = (NSMutableArray *)[NSKeyedUnarchiver unarchivedObjectOfClass:[NSMutableArray class] fromData:result error:&err];
}
#catch (NSException *exception) {
NSLog(#"Exception %#", exception.reason);
}
Now I am getting nil value for my array and the err is err = 0x0000000281ff1020 domain: nil - code: 4864
There were no issues before I updated my iPad to iPadOS 16. Any help is appreciated.
I have added the source code for this issue in this repo

Related

Objective-C : appending a NSString to NSException reason

I am working on some API (Crittercism) to report handled exceptions in the client to server.
The client API takesNSException as the input parameter. I have to add some application context info string(NSString) also to theNSException before calling the API.
How I can do it using Objective-C.
NSString* appContextString;
NSString *test = #"test";
unichar a;
int index = 5;
#try {
a = [test characterAtIndex:index];
}
#catch (NSException *exception) {
// add app context to exception before reporting to Crittercism.
[Crittercism logHandledException:exception];
}
I have to append appContextString to exception.
You could build a new NSException object from attributes of the old one, but that seems very messy. As you are just logging the handled exception, I would simply log the "app context" before that:
#try {
a = [test characterAtIndex:index];
}
#catch (NSException *exception) {
NSString *appContext = #"...";
[Crittercism leaveBreadcrumb:appContext];
[Crittercism logHandledException:exception];
}
You have to copy it. This can be done easily. An instance of NSExeption has three important properties:
name
reason
user info
When copying it, you can add a string to the user info dictionary:
NSMutableDictionary *userInfo = [exception.userInfo mutableCopy];
userInfo[#"YourPrivateKey"] = contextString;
NSException *extendedException = [NSException exceptionWithName:exception.name reason:exception.reason userInfo:userInfo];
I think as a caveat that you will lose the call stack. You can read that and put it in the user info dictionary, too. I do it a similar way on Objective-Cloud.
userInfo[#"CallStackSymbols2] = exception.callStackSymbols;
Analogous with call stack return addresses.
I do not think that this is very nice, because the call stack becomes a part of the exceptions's user info instead of the exception itself. For me this is no caveat, because I sent the exception as JSON, therefore the call stack as JSON object. I cannot say, whether this is a problem for you.

How to catch exceptions occur because of not conforming to NSCoding protocol in Objective-c?

I am getting an exception from my published application which is:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x19a8a170'
and happens because of:
#property(nonatomic,retain)NSMutableDictionary *settings;
settingsData = [NSKeyedArchiver archivedDataWithRootObject:self.settings];
As this is a remote report, I cannot debug or find out the problematic object that was added to NSMutableDictionary without conforming to NSCoding protocol. Because of this reason, I am trying to find that object when an exception occurs. Remove it from the array and log it to learn what it is.
So, I use the following block:
NSData* settingsData = nil;
#try {
settingsData = [NSKeyedArchiver archivedDataWithRootObject:self.settings];
}
#catch (NSException *exception) {
for (id key in self.settings) {
id value = [self.settings objectForKey:key];
if(![value respondsToSelector:#selector(encodeWithCoder:)]){}
}
}
#finally {
}
However, this exception is never catched on device and simulator. (tested on iOS7 and iOS8).
I don't want to test parameters if there are no exceptions every single time...
I don't want to test values while setting them to dictionary. (As already added ones will also create problem too)
Is there a way to catch this kind of exception?

Weird crash using Restkit MainQueueManagedObjectContext - EXC_BAD_ACCESS

Sometimes when I call saveToPersistent on the RestKit MainQueueManagedObjectContext I get the following error and the app crashes.
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[UIBarButtonItem controllerWillChangeContent:]: unrecognized selector sent to instance 0x21e70300 with userInfo (null)
[UIBarButtonItem controllerWillChangeContent:]: unrecognized selector sent to instance 0x21e70300 with userInfo (null)
It seems that there are some kind of threading problem.
I save the context via a method like so:
- (BOOL)saveMainContext
{
__block BOOL contextSaved = NO;
[[[[CoreDataManager sharedInstance] objectStore] mainQueueManagedObjectContext] performBlockAndWait:^{
NSError *error = nil;
if ([[[[CoreDataManager sharedInstance] objectStore] mainQueueManagedObjectContext] saveToPersistentStore:&error]) {
contextSaved = YES;
}
}];
return contextSaved;
}
It crashes on the saveToPersistent method with EXC_BAD_ACCESS.
How can I fix this and what could be the reason for my NSFetchresultscontroller calling a method on a UIBarButtonItem?
Your saveMainContext method should only be called from the main thread and should simply be implemented as:
- (BOOL)saveMainContext
{
NSError *error = nil;
if ([[[[CoreDataManager sharedInstance] objectStore] mainQueueManagedObjectContext] saveToPersistentStore:&error]) {
contextSaved = YES;
} else {
NSLog(#"Save error: %#", error);
}
return contextSaved;
}
Calling an instance of UIBarButtonItem suggests that you have a memory management issue in that something which is observing the context save is not removing itself before it is deallocated. Check all of your observers.

Unrecognized selector when deleting a NSManagedObject

I'd like to delete a core data object by fetched the object first, so
in FetchObject.m
- (void) actionDelete {
AModel *aModel = [[aModel alloc] init];
AObj *aObj = [aModel readDataWithAttributeName:#"keyword" attributeValue:#"value"];
[aModel deleteObject:aObj];
}
aObj did fetch and obtain.
in AModel.m
- (void)deleteObject:(AObj *)aObj
{
[appDelegate.managedObjectContext delete:aObj];
NSError *error;
if (![appDelegate.managedObjectContext save:&error]) {
NSLog(#"Error: %#", [error description]);
}
}
But, when I test it, here came out an error
-[NSManagedObjectContext delete:]: unrecognized selector sent to instance 0xa43ece0
After searching the solution a bit, seems like the target has been release before deleteObject.
Is there any way to solve the problem?
The following code is causing the issue:
[appDelegate.managedObjectContext delete:aObj];
Replace it with:
[appDelegate.managedObjectContext deleteObject:aObj];
NSManagedObjectContext doesn't have a delete method, it only has a deleteObject method.
- (void)deleteObject:(NSManagedObject *)object
Parameters
object
A managed object.
Discussion
When changes are committed, object will be removed from the uniquing
tables. If object has not yet been saved to a persistent store, it is
simply removed from the receiver.

GKAchievement reportAchievements:withCompletionHandler: crash

Everyone once in a while I will get crash reports for my App (via crittercism) with the following NSInvalidArgumentException crash:
+[GKAchievement reportAchievements:withCompletionHandler:]: unrecognized selector sent to class 0x3f940a84
The code looks like this:
NSMutableArray *achivementArray = [NSMutableArray arrayWithCapacity:20];
for (NSString *achievementID in achievementsToUpload) // achievementsToUpload is a NSSet
{
GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier:achievementID];
if (achievement)
{
...
[achivementArray addObject:achievement];
}
}
[GKAchievement reportAchievements:achivementArray withCompletionHandler:^(NSError *error)
{
if (error != nil)
{
NSLog(#"Error sending achievement: %#", error.localizedDescription);
}
}];
If the error is indeed inside reportAchievements:withCompletionHandler:, as far as I can see, the source of the error can come from two places: 1) achivementArray is not an NSArray or 2) error is not really an NSError.
In the case of #1, I create the array a few lines above the call and in case #2, I doubt the OS is sending back a non-NSError object.
Any ideas?
Header looks like:
+ (void)reportAchievements:(NSArray *)achievements withCompletionHandler:(void(^)(NSError *error))completionHandler __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);
So the issue may be in base sdk that you are using. This method is available starting from iOS 6.0.
Hope it will be helpful

Resources