How are these NSArray initialization methods different? [duplicate] - ios

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
NSArray initialization methods
What is the difference between initializing array with
NSArray * array = [NSArray array];
and
NSArray * array = #[];

The two expressions are generally equivalent.
Clang's documentation lists a caveat for object literals:
Objects created using the literal or boxed expression syntax are not guaranteed to be uniqued by the runtime, but nor are they guaranteed to be newly-allocated. As such, the result of performing direct comparisons against the location of an object literal (using ==, !=, <, <=, >, or >=) is not well-defined. This is usually a simple mistake in code that intended to call the isEqual: method (or the compare: method).
As the documentation states, the caveat listed above only occurs when using direct comparison operators between objects, which is almost always not the intended action anyway. This behavior shouldn't matter, so the two can almost always be used interchangeably.

The #[] is the shortcut for [NSArray array] in modern Objective C
Please check The_Basics_of_Modern_Objective-C for a better understanding.
In my knowledge when you use the #[] this will be equivalent to the corresponding Class methods. Means:
#[] = [NSArray array];
#[#"M",#"P"] = [NSArray arrayWithObjects:#"M",#"P",nil];

These both are similar.
[NSArray array] and #[] creates and returns an empty array.
#[] is an new feature added in Objective-C. It boxes several kind of objects, and gives you flexibility of shortcut notation.
When using Apple LLVM compiler 4.0 or later, arrays, dictionaries, and
numbers (NSArray, NSDictionary, NSNumber classes) can be created using
literal syntax instead of methods. Literal syntax uses the # symbol
combined with [], {}, (), to create the classes mentioned above,
respectively.
More references Here, Literals

Related

iOS - Why Does It Work When I Compare Two NSNumbers With "=="?

In my app, I accidentally used "==" when comparing two NSNumber objects like so:
NSNumber *number1;
NSNumber *number2;
Later on, after these objects' int values were set, I accidentally did this:
if (number1 == number2) {
NSLog(#"THEY'RE EQUAL");
}
And, confusingly, it worked! I could have sworn I was taught to do it this way:
if (number1.intValue == number2.intValue) {
NSLog(#"THEY'RE EQUAL");
}
How did using "==" between the two NSNumber objects work, and why? Does that mean it's okay to compare them that way, or was it just a fluke and this is generally not guaranteed to work every time? It really confused me :(
It's not a fluke.
It's due to the tagged pointers feature of the Objective-C runtime while using an ARM64 CPU.
In Mac OS X 10.7, Apple introduced tagged pointers. Tagged pointers allow certain classes with small amounts of per-instance data to be stored entirely within the pointer. This can eliminate the need for memory allocations for many uses of classes like NSNumber, and can make for a good performance boost.[…] on ARM64, the Objective-C runtime includes tagged pointers, with all of the same benefits they've brought to the Mac
Source
That is possibly a fluke.
From NSHipster :
Two objects may be equal or equivalent to one another, if they share a common set of observable properties. Yet, those two objects may still be thought to be distinct, each with their own identity. In programming, an object’s identity is tied to its memory address.
Its possible that your statement evaluated to YES because number1 and number2 were pointing to the same object. This would not work if they had the same value but were two different objects.
The obvious reason NSNumber variables would point to the same would be that you explicitly assigned one to the other, like so:
number1 = number2;
But there's one other thing. From this answer :
This is likely either a compiler optimisation or an implementation detail: as NSNumber is immutable there's no need for them be separate instances. probably an implementation optimisation thinking about it. Likely numberWithInt returns a singleton when called subsequently with the same integer.
But anyways, its safest to use isEqualToNumber:, as there is no telling what other "things" are lurking in the depths of code that may or may not cause it to evaluate YES
From RyPress :
While it’s possible to directly compare NSNumber pointers, the isEqualToNumber: method is a much more robust way to check for equality. It guarantees that two values will compare equal, even if they are stored in different objects.
There two concepts of equality at work here:
Object identity: Comparing that two pointers point to the same objects
Value equality: That the contents of two objects are equal.
In this case, you want value equality. In your code you declare two pointers to NSNumber objects:
NSNumber *number1;
NSNumber *number2;
But at no point show assignment of a value to them. This means the contents of the pointers can be anything, and quite by chance you have two pointers pointing to the memory locations (not necessarily the same ones) where (number1.intValue == number2.intValue) happens to be true.
You can expect the behaviour to change in unstable ways - for instance as soon as you add any more code.
Of course you can compare two NSNumber* with ==. This will tell you whether the pointers are equal. Of course if the pointers are equal then the values must be the same. The values can be the same without the pointers being equal.
Now you need to be aware that MaxOS X and iOS do some significant optimisations to save storage, especially in 64 bit code. Many NSNumbers representing the same integer value will actually be the same pointer.
NSNumber* value1 = [[NSNumber alloc] initWithInteger:1];
NSNumber* value2 = [[NSNumber alloc] initWithInteger:1];
These will be the same pointers. In 64 bit, many others will be the same pointers. There are only ever two NSNumber objects with boolean values. There is only ever one empty NSArray object, and only one [NSNull null] object.
Don't let that lull you into any wrong assumptions. If you want to see if two NSNumbers have the same value, use isEqualToNumber: You may say "if (number1 == number2 || [number1 isEqualToNumber:number2])"; that's fine (didn't check if I got the names right).

When would you use NSNumber literal to create encapsulated character values?

I'm just going through Apple's iOS development tutorial at the moment and reading the chapter on the Foundation framework and value objects.
Just on the NSNumber class, it says:
You can even use NSNumber literals to create encapsulated Boolean and
character values.
NSNumber *myBoolValue = #YES; NSNumber *myCharValue = #'V';
I'm just wondering, when, or why, or in what scenario, might you want to use NSNumber for a character value rather than using NSString, say?
An NSNumber is useful for encapsulating primitive values to be inserted into Objective-C collection classes such as NSArray, NSSet, NSDictionary, etc.
Image a scenario where you would want to iterate over each character in an ASCII string and extract a unique set of vowels used. You can evaluate each character and add it to an NSMutableSet. To do so, you would need to encapsulate each character in an NSNumber as NSMutableSet expects an Objective-C object. This is just one example, but the concept applies to many situations where primitives need to be added into a collection.
Well, one case is where you're using KVC to set a value for a key, and the property type is char:
[object setValue:#'a' forKey:someCharPropertyName];
You can use NSNumber with characters to return its ASCII Code, so V would return 86.
I don't think many people use it that much, but you could probably use it for character validation. I think it just one of those things where Apple went, yeah, lets put that in for the heck of it.
It's really not used for much else. The #YES and #NO is the same as YES and NO, so its kinda inelegant in some places.

How is comparing operator '==' for NSObject [duplicate]

This question already has answers here:
Should you use 'isEqual' or '=='?
(2 answers)
Closed 8 years ago.
How is comparing operator '==' for NSObject?
Method -isEqual: works fine for me, but when I'm using -isEqual I need to check if objects exists. With '==' I don't need to check this but where I can find documentation for it?
From Apple documentation:
Returns a Boolean value that indicates whether the receiver and a
given object are equal. (required) This method defines what it means
for instances to be equal. For example, a container object might
define two containers as equal if their corresponding objects all
respond YES to an isEqual: request. See the NSData, NSDictionary,
NSArray, and NSString class specifications for examples of the use of
this method. If two objects are equal, they must have the same hash
value. This last point is particularly important if you define
isEqual: in a subclass and intend to put instances of that subclass
into a collection. Make sure you also define hash in your subclass.
if you do like this
if([obj1 isEqual:obj2])
and obj1, or obj2 is nil then you will get NO. (if this is what you meant by your question)
- Now
if(obj1 == obj2)
This is a pointer comparison. Pointers
The == operator tests whether the two expressions are the same pointer to the same object. Cocoa calls this relation “identical”
To test whether two objects are equal, you would send one of them an isEqual:

NSArray objectAtIndex: shorthand [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there some literal dictionary or array syntax in Objective-C?
I have recently noticed that something strange seems to work in objective-c.
When I have an array,
NSArray *myArray = #[#"1", #"b", #"3", #"d"];
I can normally access the second element by,
NSString *element = [myArray objectAtIndex:1]; // second element
however I seem to now also be able to access it via.
NSString *element = myArray[1];
Does anyone know if this is now a defined behaviour and therefore safe to use, or should I avoid it? Thanks to anyone who can help!!
This syntax was added in Clang 3.3 : Objective C Literals. Essentially, the compiler converts expressions of the type objCObj[idx] to the expression [objCObj objectAtIndexedSubscript:idx]. It also works for dictionaries, and you're free to adopt it for your own objects.
As such, you're perfectly safe using it, assuming you'll be using a modern version of Objective C and suitably updated Objective C compiler (i.e. Clang).
this is a new feature of objective-c and avaiable since xCode 4.5
its safe to use this syntax, you can even give your own classes support for this.
Ya, it's safe to use these syntax.
Those syntax are part of Modern Objective-C.
You can check this article for more options: ObjectiveCLiterals
It's a perfectly valid code for the latest version of the LLVM compiler.
So far, it's invalid for other compilers (e.g. GCC).
Whether you should avoid it or not - well, it's a matter of taste. There are several big discussions about it on the internet since the indexing behaves slightly different (a whole different method is used to implement it).
There are also discussions whether to use the expression literals or not since there are ocassions when they are making the code less readable (e.g. they are written like literals but they actually are autoreleased objects). Note that everything is done using literals can be done using simple macros.

Obj-c for..in loop with NSArray ordering? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does fast enumeration in Objective-C guarantee the order of iteration?
Just a quick question that was proving problematic to google:
When fast-iterating over an NSArray like so:
for (NSObject *obj in array) {}
Is the order well-defined? In my tests it seems to be, but I wasn't able to find a guarantee anywhere...
Thanks!
From the Fast Enumeration section of The Objective-C Programming Language:
For collections or enumerators that have a well-defined order—such as an NSArray or an NSEnumerator instance derived from an array—the enumeration proceeds in that order, so simply counting iterations gives you the proper index into the collection if you need it.
Yes, it does.
The documentation says NSArray and its subclasses «manage ordered collections of objects».
This is the guarantee you are looking for.
Note this is not the case with NSDictionary, for instance.

Resources