Return an object as readonly - objective-c

How would you return an object from a method, so it is read-only for the caller?
Please note that this isn't a property that can be simply set to read-only when it's getter is declared
i.e #property(nonatomic,retain,readonly) NSDate* pub_date;
For example:
-(SomeClass*)getObject
{
SomeClass* object = [[SomeClass alloc] init];
//Don't allow writing to 'object'
return object;
}
Thanks.

Short answer: there's no simple way of doing this.
Longer answer: Apple's framework defines a sort of standard for its collection classes where the immutable collection is the base class and the mutable collection is the inheriting class. So, for example, NSMutableArray inherits from NSArray. You can follow that standard, and have methods that return MyClass to clients while using MyMutableClass inside them. Technically the client can still send the mutating messages, of course, but IMHO that's not a big risk (after all, the client doesn't know your implementation details).
There are other, more complicated options - you can use pointer swizzling, or subclass and override all mutating methods, or simply copy the mutable class into an immutable counterpart (that's not complicated but may incur a performance hit). But for best results you should probably follow Apple's example.

It depends what the object is. If it has a mutable / immutable pair (like NSString/ NSMutableString) then your getter method can return the immutable version.
Otherwise, you can't control the behaviour of other objects - once you've returned an object, there is no control over it from the object that originally provided it.
If you are concerned that another object may alter an object returned from a getter, and thereby amend the property held within the original object, then you should return a copy of the object instead.
Example:
Object A has a mutable string property, object B asks for this mutable string, the getter directly returns the instance variable backing the property.
Object B then changes the string - the property of object A has also been amended because both objects have a pointer to the same mutable string.
In this case, you would return a copy of the object rather than the object itself. If your object is a custom one, you must implement the NSCopying protocol to allow this.
A further note - declaring a property as read only simply means that no setter accessor will be generated - i.e. objectA.property = newValue; will result in a compiler error.

Related

what is the getter method of a simple property called

I am trying to understand the methods generated when properties are used.
Say I have the following declaration
#property int myint;
Now I know I could access this variables as such (say d was my instance of the class)
d.myint = 12; //this is equivalent to [d setMyint:12];
NSLog(#"The value is %d",d.myint); // what method is generated ?
What is the getter method called ? I was under the impression it was called getMyint however that isnt available ? Any suggestions if I might be missing something here?
As stated in the other answers, the proerty declaration gives you a getter and a setter for that instance variable for free! The notation is that you can either get [self myInt]; or self.myInt;. Both calls are 100% equivalent, i.e. they will both call the method - (int)myInt. This method is not visible (or rather, it's not explicitly implemented, see below) by default, however, you can implement it to provide some custom logic (e.g. check for specific values, error handling or lazy instantiation). If you want to override it, put this in your .m file.
- (int)myInt {
NSLog(#"getter of my int called, current value %d", _myInt);
return _myInt;
}
I only want to add to the the previous answers that in Objective-C, you have the possibility to rename your getters and setters when declaring the property, like so:
#property (getter=getMyInt) int myInt;
you can call those in the exact same way that you would use your normale getter:
int myInt = [self getMyInt];
// or
int myInt = self.getMyInt; // (will work but is not recommended since the compiler will interpret this as calling the getter of a property named `getMyInt` and only when this one is not found will actually fall back to the custom getter (thx to #NikolaiRuhe again for pointing this out))
Update:
Agreeing with most of what #NikolaiRuhe stated in his comment, here is a clarification of my answer referring to the mentioned issues:
This is indeed a typo, of course the way to use the property getter is by either calling [self myInt] or using dot notation self.myInt, and not [self getMyInt]. These calls are however 100% equivalent since they both invoke the actual getter.
About the visibility, indeed I should have been more explicit here. In OOP terms, visibility is a concept that describes the accessibility of instance variables from the outside of a particular class. I meant it exactly in the way that #NikolaiRuhe suggested, i.e. that this method is not explicitly implemented (so, it's not visible in the code by default). Sorry about this misunderstanding!
I am actually not sure about this point. For me this didn't make much of a difference in the past, I don't insist on this point. So I'd well acknowledge that the act of explicitly implementing a getter is not actually an override but rather a replacement of the synthesized method.
After explicitly renaming the getter to getMyInt like I suggested above, I don't see anything "wrong" with calling self.getMyInt. Why would this be the wrong way to access the property?
The getter method would be:
[d myInt];
Per the Apple docs :
You access or set an object’s properties via accessor methods:
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:#"Johnny"]; By default, these accessor methods are synthesized automatically for you by the compiler, so you
don’t need to do anything other than declare the property using
#property in the class interface.
The synthesized methods follow specific naming conventions:
The method used to access the value (the getter method) has the same
name as the property. The getter method for a property called
firstName will also be called firstName.
The method used to set the value (the setter method) starts with the
word “set” and then uses the capitalized property name. The setter
method for a property called firstName will be called setFirstName:.
The syntax of getter method would be-
-(int)myint{
return myInt;
}
It will return myInt property of the receiver if this message i.e. d in your case.
If you are creating a property in objective-c, it creates 3 things for you.
an instance variable which you can access by using an underscore before the property name. Ex: _myint
a getter method which you can call directly by using the property name. Ex: [self myint]; / self.myint, this will actually call - (int)myint {} method.
a setter method which you can call by using a 'set' keyword before it. Ex: [self setMyint:12]; / self.myint = 12, this will actually call - (void)setMyint:(int)myint {} method.
Source
So when you write d.myint = 12; this is equivalent to writing [d setMyint:12];
And when you write NSLog(#"The value is %d",d.myint); this is equivalent to writing NSLog(#"The value is %d",[d myint]);
Custom Getters and Setters
Credits
You can also give custom names to your property Getters and Setters. This is how it is done
#property (getter=getMyInt, setter=setMyIntWithInt) int myint;
Ex:
[d setMyIntWithInt:12]; //This will set the instance variable to 12.
NSLog(#"The value is %d",[d getMyInt]);
Also, you can override these methods in your implementation(.m) file for error handling or lazy instantiation.

Checking if object exist in object array without looping

I would like to check if my NSMutableArray contains my custom object. But if I understand correct contains functions searches for the same object in array (placed at the same memory point)
if(![objectArray containsObject:objToCheck])
{
[objectArray addObject:objToCheck];
}
I know that objectArray has identical object with identical variable values compared to objToCheck, yet such if always returns false. Is there a way to check this without writing custom loop and comparing objects by their parameters?
Override the [NSObject isEqual:] method (actually it's part of the NSObject protocol) of your custom object and check whatever instance variables make sense to you for an object to be considered equal.
Here's an Apple Cocoa Competency article on the subject.
You might try creating a temporary NSSet from your array and testing against that for membership.

Why use #property for NSArrays in iOS

why would you use #property with NSArray?
The reason for my question is because I was under the impression that #properties were mainly used to take advantage of the getter and setter you get for free when you use #property, but when you assign an NSArray to a property you know you will never use the getter and setter to access the objects in the array, why use properties on this case. Does this have to do with ARC, in other words is this considered a better memory management practice?
You use a property to get or set the whole array. You also use the property to access individual elements of the array.
Using a property with an array has nothing to do with ARC or MRC. Properties are a way to encapsulate data. That's it.
If you don't wish to provide access to the whole array then don't use a property. Add method(s) to set/get individual elements of the internal array if that is appropriate.
Along with what already said by other answers, I usually like to copy my array for security purposes.
If you're accepting an NSArray by the client, she could potentially provide you a NSMutableArray instance. If that's the case and you want to ensure that the array you're working with doesn't change unexpectedly, you'd better copy it as opposed to retain it.
Properties come in handy in this case since you can declare
#property (nonatomic, copy) NSArray * myArray;
and be sure that you're the only owner of that array after you assigned it.
I typically use this strategy for any class with mutable subclasses, such as NSString, NSArray, NSSet and so on, whenever I care about the ownership of the data.
The downside of this strategy is of course memory efficiency, but in the end engineering is the art of intelligent compromise.
To use the array outside of a single method or class. ClassA.array = ClassB.array; or to simply read from the array in a different method of the same class since the array will dealloc immediately after execution.
but when you assign an NSArray to a property you know you will never
use the getter and setter to access the objects in the array, why use
properties on this case.
For the same reasons that you use properties for other objects:
accessors: The accessors are for the array itself, not objects in the array. It's not uncommon to get or set an entire array at once:
NSArray *kids = frank.children; // get the array
mary.children = #[#"Nick", #"Sam", #"Susan"]; // set the array
abstraction: Using properties instead of accessing the underlying array directly makes it easier to change the implementation later, should that become necessary.
KVC compliance: You get it for free with properties. With collections like arrays, KVC gives you a lot of power. You can use collection operators like #avg and #max as well as indexed accessors:
int employees = [accounting countOfEmployees]; // same as [accounting.employees count]
Employee *thirdEmployee = [engineering objectInEmployeesAtIndex:2]; // same as [engineering.employees objectAtIndex:2]

What's the difference between KVC and Properties?

So, I've already read up on the documentation which notes
Objective-C 2.0’s dot syntax and key-value coding are orthogonal technologies. You can use key-value coding whether or not you use the dot syntax, and you can use the dot syntax whether or not you use KVC. Both, though, make use of a “dot syntax.” In the case of key-value coding, the syntax is used to delimit elements in a key path. It is important to remember that when you access a property using the dot syntax, you invoke the receiver’s standard accessor methods.
It then provided an example that supposedly showed the difference between the two. However, I still don't get, what's the difference between KVC and property accessor methods? Aren't they the same? And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?
However, I still don't get, what's the difference between KVC and property accessor methods?
KVC is a way to call property accessor methods, or otherwise access a property.
What do I mean by “otherwise access”? For KVC purposes, an instance variable with no accessor methods counts as an informal property. It'll get or set the value of the instance variable directly if no matching accessor pair can be found. (Yes, this is not worth using in modern code. Always declare an #property for anything you intend to access elsewhere, and, inversely, don't use KVC to access anything that isn't a public property.)
Property accessor methods are what KVC will call if they exist (preferred, both by KVC and by every sane programmer, over direct ivar access). An accessor may get or set an instance variable, as synthesized accessors do, or access some other storage.
Accessors are implementation, properties are interface, and KVC is one way to use them.
And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?
A key path is a string, whereas a property-access expression is an expression. The compiler evaluates a property-access expression and translates it into one or more Objective-C messages, whereas a key path is evaluated by KVC at run time.
So, when you use a key path:
[someObject setValue:theValue forKeyPath:#"foo.bar.baz"];
You know it's a key path because (1) it's a string, as indicated in this case by the string-literal syntax #"…", and (2) you're passing the key-path string to setValue:forKeyPath: for it to evaluate.
Using a key path is using KVC to access the named properties. It will send any relevant accessor messages on your behalf.
When you use a property-access expression:
someObject.foo.bar.baz = theValue;
You know it's a property access expression because you are not identifying the properties with a string. You are accessing them (sending the accessor messages) yourself, in your own code.
There isn't much reason to use KVC in any form; when you know the property at authorship/compile time, it's best to have an #property declared and to access the property yourself, whether with property-access expressions or message expressions ([[[someObject foo] bar] setBaz:theValue]). The time to use KVC is when you don't know what property you want to access until run time, which is pretty rare. It's mainly a building-block technology behind KVO, Cocoa Bindings, parts of Core Animation, etc.
Mostly, you'll only want to access properties yourself.
Key value coding allows you to set and get the value of properties through code using the string name of the property. For example, if I had a property named foo which is of type NSString:
[self setValue:#"mystring" forKey:#"foo"];
// read the value by key
NSString *s = [self valueForKey:#"foo"];
Dot syntax is compile syntax sugar. As a personal preference (as some don't agree - fine) I don't use dot syntax but I still use KVC:
[myObj setFoo: #"someString"]
equals:
myObj.foo = #"someString";
They are orthogonal, different concepts but both dealing with how you interact with properties
Finally, you mention property syntax. Yet another orthogonal concept but related to dealing with properties.
With objective-c, convention is important. Follow them. Properties are the name of the property for the get and set[Name] for the assignment:
- (NSString*)foo
{
return _foo; // defined as (NSString*)_foo in header
}
- (void) setFoo: (NSString*)foo
{
if (foo == _foo)
return;
NSString* curr = _foo;
_foo = [foo retain];
[curr release];
}
Now, who wants to write something like that every time. So, enter #property syntax:
In header:
#property (retain) NSString *foo;
Then in .m:
#synthesize foo;
That's the equivalent of the hand written property accessors. It's compiler syntax sugar which expands the property code based on how you attribute the properties.
Docs:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

Why do some objects not need to be initialized before use in objective-c?

Why do some objects not need to be initialized before use in objective-c?
For example why is this NSDate *today = [NSDate date]; legal?
They are initialized within the date method. This is a common way to create autoreleased objects in Objective-C. Allocators of that form are called convenience allocators.
To learn more about that, read the "Factory Methods" paragraph in Apple's Cocoa Core Competencies document about Object Creation: http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ObjectCreation.html
To create convenience allocator for you own classes, implement a class method, named after your class (without prefix). e.g.:
#implementation MYThing
...
+ (id)thing
{
return [[[MYThing alloc] init] autorelease];
}
...
#end
today is initialized (and autoreleased) inside the static date call.
You only need to called an init… method on objects you have allocated by calling alloc. alloc only reserves space needed for the object, creating a an unitialized object.
An uninitialized object have all instance variables set to zero, nil, or equivalent for the type. Except for the retain count that is set to 1.
All other methods that return an object are guaranteed to return a fully initialized object. alloc is the exception.
You must never call an init… method on an object that is already initialized. Simple rule on thumb is to use a 1-to-1 relation between alloc-init…, thats it.
Two parts.
First, as others have mentioned, a method can initialise and then autorelease an object before returning it. That's part of what's happening here.
The other part is how it's defined. Note how most Objective C definitions begin with a -? The one you mention does not. The signature looks like this:
+ (NSDate*) date;
That is, it's a class method and applies to the class as a whole rather than to an instance of that class.