Couldn't I just pass an copied string to an Core Data property? - iphone

The docs say:
The default implementation does not
copy attribute values. If the
attribute value may be mutable and
implements the NSCopying protocol (as
is the case with NSString, for
example), you can copy the value in a
custom accessor to help preserve
encapsulation (for example, in the
case where an instance of
NSMutableString is passed as a value).
So instead of getting into trouble and inconvenience with overwriting accessors in my NSManagedObject subclass, couldn't I simply do something like this?
myManagedObject.firstName = [[firstNameMutableStr copy] autorelease];
This would have the exact same effect, or not? The dynamic implementation would retain that anyways ... so.... why not the easy way?

It's an open question whether having to remember to copy the mutable string every where in code you set the attribute is "the easy way."
With a custom accessor, you just write the copy once then forget about. It copies automatically from that point on.
Just imagine that in thousands of lines of code you forgot to copy just once and developed a subtle bug because that one attribute of the managed object sporadically changed because some other totally unrelated code subsequently changed the mutable string you held only by reference.
I could tell you some stories of weekends lost to debugging because someone took "the easy way."

Related

Objective C convention: When to use For and when to use With

According to the Apple guideline , seems it is confusing, e.g. for method viewWithTag
In Java, I would have a method called
getViewByTag // Java version, equivalent to viewWithTag in Obj-C
But I also found there are some method like objectForKey, so why not just use objectWithKey instead?
getObjectByKey or just get // Java version, equivalent to objectForKey,
// but why not objectWithKey? Or not viewForKey above?
I actually think it is much simpler than what most answers think. I think it has less to do with complex programming language specifics, and has more to do with the uniqueness of the object in question.
When you say viewWithTag:, you are asking the UIView for any view that has that tag. There might be several. The UIView will return one of 'em.
However, objectForKey: (to me) sounds like there should be a single object (or nil) associated with that key. So, the key kinda exists and is bound (tightly coupled) to a single object.
EDIT:
There is an answer mentioning the existence of "by", which further implies how the convention has nothing to do with programming language complexities. It's just natural English.
NSString's stringByAppendingString:, for example, uses by, only because the function is written with a the verb appending. You can't say withAppending, that's bad English.
From my observation
While setting/getting the objects, you use WITH.
e.g. For setting of NSMutableArray object
- (id)initWithCapacity:(NSUInteger)numItems
While setting/getting the properties for objects, you use FOR.
e.g.For setting value for property of type NSMutableDictionary
- (void)setValue:(id)value forKey:(NSString *)key
Hope this helps in clearing your doubt
It seems like with is used for properties that directly belongs to an object. A UIView has a tag property so viewWithTag:14 could be rephrased as "Find the view whose tag property is 14".
When you put an object in a dictionary, associated to a key, this key is not necessarily part of the object itself. objectForKey:#"foo" is a way to say "Look for an object that's linked to the key "foo".
The Apple guidelines do not make any such claims as to when to use for or with. The point of the coding convention is to indicate what the types of the arguments may be and to write method signatures which are natural sounding.
The reason for the for or with in the method name is to identify the type or purpose of the first parameter to the method, which helps it read better.
Apple itself uses several conventions but that is the basic purpose, there is no concrete right or wrong just try to identify the first parameter of the method in the method name with either for or with.
And as for Apple conventions - get(whatever) is not even part of the actual conventions, so you could ask when do I use get or not.
Read this http://cocoadevcentral.com/articles/000082.php
also dont forget (by) NSURL urlByAppendingPathComponent etc - get a feel for it and you wont go wrong
You use "with" whenever the parameter is owned or to be owned, or will be a relatively permanent attribute by the object to the left of the "with" word.
initWithCapacity / arrayWithCapacity - the capacity will be an attribute of the container object being called and will be relatively permanent (until you add objects to it beyond the initial capacity)
viewWithTag – return a view "having" the specified "tag" attribute.
Whereas you use "for" to denote a looser association between the "desired" object and a "token" object that you use to get to it.
- objectForKey / attributeForValue – usually the "object" does not own the key.
- documentForWindow – the window is owned by the window controller and not the document. Furthermore there could be more than one window for each document.
But for looser associations of multiple
objects of the same type within a single method call, it's customary that you use something like:
doSomethingForFoo:withThisOtherFoo:havingYetAnotherFoo:
So the order for such complex call is:
for
with
having

When to use #property? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why should I use #properties?
When to use properties in objective C?
I have been programming in objective-c for a little over a year now, and I always felt like it was a convention to use #property and #synthesize. But what purpose do they really serve ? Are they solely there to be communicated between classes ? So, for instance, if I use an NSMutableDictionary only in the scope of the class where it was declared, an omission is O.K. ?
Another question:
If I set the property of an NSMutableDictionary, it is retained, right ? So, in my class I don't have to call alloc() and init(), do I ?
What are the rules to use properties ?
But what purpose do they really serve?
Access control to iVars and abstraction between representation and underlying data.
Are they solely there to be communicated between classes?
No, they are for when you want to control access to iVars instead of accessing them directly or when you could in the future change underlying data structures but wish to keep the current representation.
So, for instance, if I use an NSMutableDictionary only in the scope of the class where it was declared, an omission is O.K.?
It depends. Do you want to have controlled access to the iVar? Would it be possible for your code to change so the dictionary is fetched and not a direct iVar. Usually, the answer is yes.
If I set the property of an NSMutableDictionary, it is retained, right?
Depends on how you declare the property.
So, in my class I don't have to call alloc() and init(), do I?
You have sloppy wording here. I think you are asking if you still need to construct an instance of a property. Yes, you will need to construct an instance of a property in some way. There are lots of ways of doing this.
NOTE: the convention for talking about methods is use their signature. Instead of alloc(), you would use -alloc.
What are the rules to use properties?
This you will need to read the doc for.
Like in another languages, when we want to make our variable global or public we use public access modifier. In objective c when we want access our another class variable in other class, we use #property and #synthesize them. Basically #synthesize is way by which compiler create a setter and getter methods for that variable. You can manually create them but not use #synthesize.
By creating object of that class you can access your property variable in other class.
By using retain, you clear that is take place memory and not exist until that container class not goes dispose or released.
Properties simply make your life easier.
Nowadays use properties as much as you can in terms of memory management, code-style and timesaving.
What do #propertys do?
They can create getter and setter methods (depends on given parameters).
Normally you declare instance variables in the header file (like in c++).
Now you simply let that be and instead of that declare the properties you want for instance variables.
Properties can get multiple arguments.
For normal objective-c objects, where you need a pointer (*) you would write.
#property (nonatomic,retain,...)
When you #synthesize it it creates a getter and a setter.
The setter automatically does stuff like releasing your old object, that your variable hold and retaining the new one.
So you don't have to do that manually (which should be quite often the case). Thats important.
You also can give it arguments (readonly,readwrite) to decide if to set a setter or not.
You can even declare a #property in the header file readonly and override that in your implementation file with a extension (a category with no name).
To dive deeper into this, read the apple developer manuals, which are quite effective.
Hope that helps a bit.
Shure it is the tip of the iceberg, but it's mostly everything you need.

Regarding self. in viewDidUnload [duplicate]

This question already has answers here:
When should I use the “self” keyword?
(6 answers)
Closed 9 years ago.
I have an attendant question to iPhone: Why do I need self.<> in viewDidUnload?
Since there is a difference between using self.instance and instance, when is only instance actually used? Just setting the reference to nil seems quite useless? Why is the option there?
Generally, you'll find a lot of useful information here: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html%23//apple_ref/doc/uid/TP40004447-SW4
For the rest of this answer, I'll assume that you are referring to properties automatically synthesised with the #synthesize directive in your .m files.
Executive summary
When you use the form self.property, retain/release is automatically taken care of for you. When you use the form instanceVariable without the self prefix, you're on your own with retain/release.
Longer explanation
When you omit the "self." part, what you really are doing is that you access the automatically generated underlying ivar which the compiler has given the same name as you have given to the property.
If you don't want the compiler to generate ivars of the same name, then you can use an extended form of the #synthesize directive, like this:
#synthesize myvariable=__myvariable;
That way, you will ask the compiler to create an underlying ivar called __myvariable instead of the default myvariable.
Using this extended form, you would refer to either self.myvariable (as a property) or __myvariable (as an instance variable), which can be handy to visually distinguish the two types of access.
With that in place, we can get to the substance of the matter.
When you use self.myvariable, you implicitly call the accessor methods (possibly synthesised for convenience), like this:
self.myvariable = #"Some string";
is equal to
[self setMyvariable: #"Some string"];
or, in the case of a right hand use of the property
myLocalVar = self.myvariable;
is equal to:
myLocalVar = [self myvariable];
The examples above use the accessor names recommended by Apple.
On the other hand, when you use the instance variable directly, you just assign the variables directly without going through the accessors.
Now, one huge advantage of using the accessors on the iPhone is that the automatically synthesised accessors also take care of the retain/release messages, so you don't have to worry about that - or waste code lines handling this somewhat tedious stuff.
Since there is no need to worry about retain/release when you are just reading a property, you could argue that you only need to use the property syntax (with self.) on the left side of an assignment, so whether you want to use the self.-syntax on the right hand side of an assignment is partly a matter of style.
Personally, I have developed a style where I try not to refer to automatically synthesised ivars, unless I have specified them in the #synthesize directive. Otherwise Apple might one day change the way an unspecified #synthesize directive works, and my builds would break. But that is just a personal precaution of mine.
There is one exception to all this, as stated in the docs linked at the top of this answer - and that is that you should not use accessors to the class' own instance variables in the init* methods. One the Mac, you shouldn't use them in the dealloc methods, either, but this is one point where Apple's coding recommendations differ between the two platforms.
Ok, this was a long answer to just say, read the docs, but I hope it clarifies things a little. Memory management in reference counted environments is not trivial, so don't despair if it isn't clear at first.
PS: And if you think this the sort of worries that others should solve for you, log a bug with Apple to ask for garbage collection on iOS. It works nicely on 64-bit OS X.

Reflection in Objective-C (iPhone)

I want to populate [MyClass class] from a JSON string.
I use json-framework to get the NSDictionary, and it's dead easy to instantiate and setValue: forKey:... on my data object.
But for more complex data objects with classes as members of MyClass,
ie:
MyOtherClass *classNoTwo
I tried with
Class test = object_getClass(myClass.classNoTwo);
id foo = [[test alloc] init];
But foo is nil/null. The only way I found to get around it is to in my init method of MyClass is to alloc memory for it, and later replace it.
I would also like to know how to get rid of the myClass.classNoTo reference, as I am not supposed to know all the properties in my general parser.
Please don't just tell me to read the documentation, because I've done that, and I can't figure it out.
Thanks in advance
Try calling class_getProperty() to access a property of a particular name and then property_getAttributes() on the property returned by the first function. This will return a string that encodes the property's attributes, including the type. The format of the string is explained in Property Type Strings in the documentation.
Finally, when you have derived the type of the property, use NSClassFromString() to instantiate an object.
Also see the docs for the two functions mentioned for more details.
I have written a very simple dependency injection container called Factory. I do not get your question entirely, but the problems we solve look similar. Take a look at my sources, they are very simple and should get you started. You might be interested especially in the ClassAnalyzer class. It’s just a hack, but you should be able to get what you want from there.

Create a copy of a NSObject

How do I take a NSObject that I have set all the attributes of and then copy that into another block of memory that an array can use so I can re use the original one?
In short, you don't.
If you want to put the object in an array and then create a new object, do exactly that; addObject: to the array and alloc/init a new one.
If you are asking how you copy an object into, say, a random malloc() block somewhere -- say, in the middle of an array -- then that is a very different issue. It can technically be done, but basically no one does so as the frameworks and runtime aren't designed for that.
Without knowing more about your specific needs, it is impossible to go into more detail.
Making a copy of an object is done by sending it the copy message. This only works on instances of classes that implement the NSCopying protocol.
Read Implementing Copy for a good overview. Then read Implementing NSCopying Considered Harmful for some more background info.