Anyone know what cause this crash:"[__NSArrayI replaceObjectAtIndex:withObject:]: unrecognized selector"? - objective-c

Recently I use NSTextTable draw table. I want change some attribute of selected block,so save selected paragraphs into dictionary. After I copy the block of paragraph, once I call method [NSTextTableBlock setBorderColor:], raise an error:
-[__NSArrayI replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x6000002442c0
I try many times, finally found a phenomenon, which is if I don't copy block, setBorderColor: is OK.
Anyone know relation of [NSTextTableBlock copy] and this error, why [NSTextTableBlock setBorderColor:] cause this error? I'm quite confuse about this error. Thanks in advance.

NSArray does not have the selector replaceObjectAtIndex:withObject: (so you can't call it). You are actually trying to modify an NSArray which can not be modified like that. You probably want NSMutableArray instead. You can create an NSMutableArray from an NSArray, call your method and then replace your reference to the original array like this:
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
[mutableArray replaceObjectAtIndex:index withObject:object];
array = mutableArray;//now the array has been "updated"

Related

Error trying to separate an array containing managed object context

Could anyone please tell me why I am getting this error and why this code isn't working?
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[__NSArrayI componentsSeparatedByString:]: unrecognized
selector sent to instance 0x109494750'
This is the code with problems:
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:nil];
NSString *dateString = [array valueForKey:#"dateString"];
NSArray *datesArray = [dateString componentsSeparatedByString:#","];//line with problems
When you call valueForKey: on array the result will be an NSArray containing the result of calling valueForKey: on each of it's elements.
So dateString is not actually a string it's an instance of NSArray, which does not respond to componentsSeparatedByString:. You need to index into the array to get the date you want before calling componentsSeparatedByString: on that
It's an indication that dateString isn't a string. When you call -valueForKey: on an array, it returns an array. Per the docs:
Returns an array containing the results of invoking valueForKey: using key on each of the array's objects.
So you're calling a string method on an array. It's not clear what you're trying to accomplish by calling -valueForKey:. Perhaps you meant -objectAtIndex:?

Sort NSMutableDictionary by NSNumber-type keys

I need to set source array with custom UITableVIewCells for UITableView. At start I am creating dynamically keys(NSNumber-indexes for cells, lot of options here) and adding them using
[dict1 setObject:cell forKey:[self returnCurrentIndex:nsnumberValue isCurrent:YES]];
to sort dictionary by indexes later.
Unexpectedly
NSArray *sortedKeysArray = [dict1 keysSortedByValueUsingSelector:#selector(compare:)];
causes exception
'-[PTDigitInputCell copyWithZone:]: unrecognized selector sent to
instance 0x6ecf710'
I understand that this method tryng to sort dictionary by values(custom tableView cell`s in my case) but not the keys(NSNumbers), and in Apple documentationI can't find method what will be sort by keys. Does it exist, or how can I solve this?
You have overthinked this. Just take all keys and then sort array:
NSArray *sortedKeysArray = [[dict1 allKeys] sortedArrayUsingSelector: #selector(compare:)];

"unrecognized selector sent to instance" exception error

I've read all the "unrecognized selector sent to instance" answers, but they don't seem to apply to my situation.
I've setting up a NSMutableDictionary like this...
NSMutableDictionary *ObjectDynamic = [NSDictionary dictionaryWithObjectsAndKeys:pObject, #"pFObject",tObject, #"tFObject",nil];
and then at some later point in the code I'm trying to add in another object/key, with this...
[ObjectDynamic setObject:mySprite forKey:#"pSObject"];
But I'm getting an exception on that line, with the...
-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance
Is it not possible to add in another key/value pair like that?
Edit
Simple mistake, I just was trying to make a NSDictionary rather than a NSMutableDictionary! Thanks for the answers anyway.
That's because you initialize an immutable NSDictionary that doesn't have a setObject:forKey: method. Initialize a mutable one instead:
NSMutableDictionary *ObjectDynamic = [NSMutableDictionary
dictionaryWithObjectsAndKeys:pObject, #"pFObject",tObject, #"tFObject",nil];
Since Xcode 4.4 you can also use the new dictionary literals to initialize immutable dictionaries very easily and then use mutableCopy.
NSMutableDictionary *objectDynamic = [#{#"pFObject" : pObject,
#"tFObject" : tObject} mutableCopy];
Note, that in Objective-C you should start variable names with lower case letters.
In order to be able to change the content of a dictionary, you need to make NSMutableDictionary, not an immutable NSDictionary:
NSMutableDictionary *ObjectDynamic = [NSMutableDictionary // <<== Here
dictionaryWithObjectsAndKeys:pObject, #"pFObject",tObject, #"tFObject",nil
];

NSMutableArray is empty after addObject

I want to add an object into an NSMutableArray:
NSLog(#"Object text: %#", object.text);
NSLog(#"Object: %#", object);
[appdelegate.objects addObject:object];
NSLog(#"Objects array size: %i", [appdelegate.objects count]);
This is the output:
Object text: This is the text
Object: <Object: 0x6e762c0>
Objects array size: 0
How is this possible, I add an object, on the next line, it is still empty. The NSMutableArray is not nil, because that would raise an exception.
Anybody a guess?
It would not raise an exception if it was nil. You can still message a nil object if it usually responds to that message. In this case, you'll just get 0. I think you're not allocating the array. Make sure you're doing this:
array = [[NSMutableArray alloc] init];
As a debugging tip, if you're unsure about the state of an object and want to make sure the object indeed exists and is ready to be used, use assert(appdelegate.objects); If the array is nil, your code will stop executing at this line. If it doesn't stop at this line, then you know the object exists in memory.
Your NSMutableArray is indeed almost certainly null. It won't raise an exception, because sending any message to nil in ObjC is a no-op and would behave as you're seeing, with a return value of zero or nil, etc.
Try logging that as well to double check.

What is the Difference b/w addObject:dictionary and addObject:[dictionary copy] to an NSMutableArray?

I'm trying to set some values to my NSMutableDictionary inside a loop and assigning the dictionary values to an NSMutableArray each time like below,
for(int i=0;i<=lastObj;i++){
[mutableDict setValue:[valuesArray objectAtIndex:i] forKey:#"Name"];
[mutableDict setValue:[uniqueArray objectAtIndex:i] forKey:#"SSN"];
//......then
**[mutableArray addObject:mutableDict];**/*not working perfectly all values s replaced by final mutableDict values (duplicate values)*/
but
**[mutableArray addObject:[mutableDict copy]];**/* Working Correctly !!! */
}
inside loop in each iteration new values is assigned to mutableDictionary and whenever i say just addObject my mutableArray is getting all duplicate values but whenever i say addObject:[mutableDict copy], array is getting correct unique values without any duplicates, i don't know what the difference the compiler feels when i say copy, can anybody tell me the difference in this.
Thanks in advance.
[mutableArray addObject:mutableDict];
keeps on adding mutableDict to mutableArray. adding the object doesnt create a new memory location, it points to the same memory. so when u set the values of mutableDict, it gets reflected in all added objects as they refer to same memory location.
copy creates a new memory location and adds the object removing the above scenario.
to avoid this u can add
for(int i=0;i<=lastObj;i++){
NSMutableDictionary * mutableDict = [NSMutableDictionary new]; //create new memory location
[mutableDict setValue:[valuesArray objectAtIndex:i] forKey:#"Name"];
[mutableDict setValue:[uniqueArray objectAtIndex:i] forKey:#"SSN"];
[mutableArray addObject:mutableDict];
[mutableDict release]; //release
}
hope this helps u. happy coding :)
Looking at your code block, its clear you are allocating mutableDict outside your for loop. Hence When you say below statement inside the for loop, basically you are passing the same object for addition to mutalbeArray.
[mutableArray addObject:mutableDict];
addObject doesnt allocate any memory for objects, but it uses the same object passed and just sends "retain" message to increase the reference count. Since you are passing the same object within the for loop, mutalbeArray would contain the references to same object.
In case of copy say,
[mutableArray addObject:[mutableDict copy]];
the copy message sent to mutableDict returns a new copy which is then passed addObject. Hence every iteration in the forloop passes a new object(due to copy) to addObject.
Also note these following
Copy creates a new object, it should be later released, but your code is not releasing it. This will lead to memory leak.
Copy creates immutable object, hence you should probably use mutableCopy instead if you want objects added to mutableArray to be modified.