How does inheritance work in Objective-C? - ios

What is the difference between
NSArray *arr1 = [[NSMutableArray alloc] init];
NSDictionary *dict1 = [[NSMutableDictionary alloc] init];
and
NSMutableArray *arr2 = [[NSMutableArray alloc] init];
NSMutableDictionary *dict2 = [[NSMutableDictionary alloc] init];
I know both (arr1, dict1, arr2, dict2) are going to create NSMutableArray and NSMutableDictionary object respectively, arr1 and dict1 would have access to all the functions that could be accessed by arr2 and dict2.
My Question to you guys is:
What is the difference between arr1 and arr2 or dict1 or dict2? Why would any one make object like arr1 and dict1 when we could do same things by making objects like arr2 and dict2? Are there any benefits of initializing objects like arr1 and dict1 over arr2 and dict2? If none, what could be the use of initializing objects like this?

arr1 is a reference to NSArray which gets an instance of a specialization of NSArray assigned, that is NSMutableArray. (NSMutableArray class inherits from NSArray and adds some methods to modify the array)
The compiler will prevent you from modifying arr1. (However, in Obj-C you could still call the NSMutableArray methods on arr1 during runtime when the object actually is of type NSMutableArray, but that is a different topic and not a proper way of doing it. See below for a better way of modifying arr1 if it really is mutable.)
The same applies for dic1.
arr2 and dict2 on the contrary are references to NSMutableSomething. Therefore those methods that belong to the mutable classes but not to their immutable base class can be accessed in code.
Some addition: Later in your code you could assign (and cast) arr1 to arr2 and then access the methods of NSMutableArray. Before assigning and casting a reference to a base class to a reference to a specialzation, you should always check the current class by isKindOfClass: method of NSObject.
Sampe:
if ([arr1 isKindOfClass:[NSMutableArray class]]) {
arr2 = (NSMutableArray*) arr1;
// Do something with arr2 that requires its mutability.
}

Mutable types have some special privileges like runtime update/insert/delete object from collection.
But they must have to be initialise before use and they occupies more memory than immutable.
Where else immutable type collection can not be alter at runtime. They are static containers as and contains elements which can't be alter from collection.
Immutable does not need to be alloc init and they consume less memory than mutable.

In short NSArray is not flexible. You can't add or remove object into it. Same goes for NSDictionary. You can initialize but dynamic cast will occur and you will have in arr1 simply NSArray.

Difference is simple
1-Mutable classes are those which could be changed after initialization but other can't be changed using SetObject: or SetValue: etc.
2-Mutable classes dynamically create on heap other are created on stack.
I prefer immutable on mutable because if mutable is exposed then other can
change its data using setobject or setvalue and may be we don't know about it.
but if immutable is exposed then we can't change its data so data remain protected.

Related

How to add two array's objects as objects and keys to the third array in Objective C

I am trying to add two arrays into the third array i.e one array's objects are values to the third array and other array's objects are keys to the third array and I am getting the output as null , Is this a right way to do.
NSArray *newcontactkeys,*newcontactvalues ;
NSMutableArray *autoSyncDataArray;
newcontactkeys=[self.resultDict objectForKey:#"keys"];
newcontactvalues=[self.resultDict objectForKey:#"values"];
[autoSyncDataArray setValue:[self.resultDict objectForKey:#"values"]
forKey:[self.resultDict objectForKey:#"Keys"]];
NSLog(#"autosyncArray is %#",autoSyncDataArray);
Output: autosyncArray is (null)
You are using an array, which is an indexed collection, but talking about keys, dictionaries are keyed collections.
NSDictionary has a class method to directly create a dictionary from two arrays, use this and your code becomes, updating to modern Obj-C syntax:
NSArray *newContactKeys = self.resultDict[#"keys"];
NSArray *newContactValues = self.resultDict[#"values"];
NSDictionary *autoSyncDataDict = [NSDictionary dictionaryWithObjects:newContactValues
forKeys:newContactsKeys];
HTH
You're not initialising your array.
NSMutableArray *autoSynchDataArray = [NSMutableArray new]
Also use addObject instead of set value:
[autoSyncDataArray addObject:[self.resultDict objectForKey:#"values"]
You cannot join/Manipulate multiple Array of type NSArray.
Create a NSMutableArray which allows reordering and manipulation of data in it. You can add any number of objects to it, rearrange it and delete it.
NSMutableArray *templateArray = [NSMutableArray new];
There are 2 issues:
Null issue: You are not initializing array. So you will have to use below statement:
NSMutableArray *autoSyncDataArray = [[NSMutableArray alloc] init];
Key/Value Pair: If you want to put keys and values in an array. It will not work like Dictionary. It will go into sequential form. If you are ok with sequential form then use:
[autoSyncDataArray addObject:[self.resultDict objectForKey:#"keys"]];
[autoSyncDataArray addObject:[self.resultDict objectForKey:#"values"]];
otherwise use:
NSMutableDictionary *autoSyncDataDict = [[NSMutableDictionary alloc] init];
[autoSyncDataArray setValue:[self.resultDict objectForKey:#"values"]
forKey:[self.resultDict objectForKey:#"Keys"]];

Magic command for extracting an array of names from an array of NSPropertyDescription objects

I have this array with a bunch of NSPropertyDescription objects. These objects have a property called name.
I want to extract an array containing just the names of all these objects.
Ok, I can do this:
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSPropertyDescription *property in anEntity) {
[array addObject:property.name];
}
but I know objective-c has a lot of magical commands to extract stuff from arrays of objects.
How do I do that using one of those magical commands?
thanks.
Key-Value Coding should do the trick:
NSArray *names = [arrayOfPropertyDescriptions valueForKey:#"name"];
For an array, valueForKey returns an array containing the results of invoking valueForKey: using the key on each of the array's objects.

How does this NSMutableArray alloc&init work?

I see a new kind of alloc&init NSMutableArray way in one project. It's like this A
NSMutableArray *array = [#[] mutableCopy]; and this works well, and i want to try whether its possible to use BNSMutableArray *array = [NSMutableArray mutableCopy]; it build succeeded, but got this error when used: +[NSMutableArray addObject:]: unrecognized selector sent to class 0x38bedc2c
Now i want to know how does A work? and why B is wrong? A is better than normal alloc&init?
Any help will be appreciated.
mutableCopy is an instance method declared in NSObject class. It is called on any instance to create a mutable copy of it.
In first case #[] will create an autoreleased NSArray instance on which calling mutableCopy will create NSMutableArray instance.
In second case calling mutableCopy on the class is incorrect because it is not meant to be called that way. This will get compiled but will cause exception at runtime.
Hope that helps!
In the first case, you're first initializing an empty NSArray instance; think of #[] as equivalent to [[NSArray alloc] init]. Therefore you're sending mutableCopy to a correct instance, so it works fine.
In the second case, you're sending the message to a class (as opposed to an instance of it), which doesn't make much sense, because the addObject message can only be sent to an instance, not the class itself.
#[] means an NSArray with no object. It returns an NSArray, and then its mutableCopy is copied to array.
+[NSMutableArray addObject:] is invalid as addObject is an instance method and you are trying to use it as class method.
Even NSMutableArray *array = [NSMutableArray mutableCopy]; is incorrect!!! As nothing is created, it is not been allocated and inited. If you log the array, it will only print the string NSMutableArray. Also you can't use array to addObject and other operations.
You should use NSMutableArray *array = [NSMutableArray array];
The first one is lazy typing.
You should avoid it.
It creates an empty NSArray from the array literal syntax and the creates a mutable copy.
That's saving a little typing by creating an unnecessary array.
You should just use
[NSMutableArray new]
Or
[[NSMutableArray alloc] init]
Or if possible because you know the initial capacity in advance
[[NSMutableArray alloc] initWithCapacity:someNSUIntegerValue]
Anything else above is laziness.
Only use mutableCopy when you are actually copying some content.

NSMutableArray addObject getting set to nil after release of object

I have declared an NSMutableArray *arrAllRecordsM and am trying to add NSMutableDictionary *dicRecordM to it using addObject. The dicRecordM gets added to arrAllRecordsM but on doing [dicRecordM removeAllObjects] it sets to nil in arrAllRecordsM. Below is the code, please help me fix it.
self.arrAllRecordsM = [NSMutableArray array];
self.dicRecordM = [NSMutableDictionary dictionary];
// Some Method
[self.dicRecordM setObject:#"Test" forKey:#"ADDRESS"];
[self.arrAllRecordsM addObject:self.dicRecordM];
// Value: Test
NSLog(#"Value: %#", [[self.arrAllRecordsM objectAtIndex:0] valueForKey:#"ADDRESS"]);
[self.dicRecordM removeAllObjects];
// Value: null
NSLog(#"Value: %#", [[self.arrAllRecordsM objectAtIndex:0] valueForKey:#"ADDRESS"]);
Adding an object to an NSMutableArray just stores a pointer (or "strong reference")
to the object into the array. Therefore
[self.arrAllRecordsM objectAtIndex:0]
and
self.dicRecordM
are two pointers to the same object. If your remove all key/value pairs from self.dicRecordM then [self.arrAllRecordsM objectAtIndex:0] still points to the same
(now empty) dictionary. That is the reason why
[[self.arrAllRecordsM objectAtIndex:0] valueForKey:#"ADDRESS"]
returns nil.
If you want an independent copy of the dictionary in the array, use
[self.arrAllRecordsM addObject:[self.dicRecordM copy]];
copy can be used on many classes, such as NSDictionary, NSArray and NSString
and their mutable variants, to get a "functionally independent object". Formally, it is available for all classes conforming to the NSCopying protocol.
This is expected behavior.
You removed all the objects from the dictionary by calling removeAllObjects, then tried to retrieve an object from it and rightfully getting nil, since it doesn't exist in the dictionay anymore (you removed it).
What's maybe unclear to you is that NSArray doesn't copy the element you add to it, instead it just holds a strong reference.
So both dicRecordM and arrAllRecordsM are holding a reference to the same object, hence any modification to it (in this case removeAllObjects) will affect the same dictionary.
Incidentally, you shouldn't use valueForKey: for accessing the dictionary's entries. Use objectForKey: or the shorter subscripted syntax. For instance
self.arrAllRecordsM[0][#"ADDRESS"]
You can read this answer Difference between objectForKey and valueForKey? as a reference, but the main problem is that valueForKey: can behave very differently from objectForKey: in case the key contains special KVC characters, such as # or ..

IOS: how to use NSMutableArray

In my code, I must to store an array inside another array:
What's the best way?
first:
NSArray *arrayTemp = myArray;
second:
NSMutableArray *arrayTemp = [[NSMutableArray alloc]init];
[arrayTemp addObjectsFromArray:myArray];
...instruction....
[arrayTemp release];
By doing arrayTemp = myArray, you declare arrayTemp as a new pointer to your existing array myArray. That's not a copy (if you put X in myArray[42], arrayTemp[42] will also be X).
The second variant looks like you're doing a copy of your array, but still the array's values are copied by reference (by pointer), when you seem to need a copy "by value".
What you should try is simply:
NSArray *arrayCopy = [myArray copy];
Beware: from a memory management point of view, this is equivalent to a retain or a alloc/init: you should release your arrayCopy after use.

Resources