Unable to make a Core Data transient attribute private - objective-c

I have a Core Data entity Series with a transient attr indexCurrent. When outside classes access indexCurrent, I want them to send in an arg that can be used to check whether indexCurrent’s value needs to be updated before returning it. Therefore, I have declared indexCurrent as a private variable, and allow outside access to it only through that special method with an arg.
But although the compiler issues "method not found" warnings, it allows outside classes to call both indexCurrent and setindexCurrent:, and this faulty code executes with complete success.
Here is the Series interface:
#interface Series : NSManagedObject {
#private
NSNumber *indexCurrent;
}
indexCurrent is not propertized, is not declared as dynamic in the implementation file, and I have not written indexCurrent or setindexCurrent: accessors.
What am I doing wrong? How can I make indexCurrent private?

#dynamic doesn't cause any code to be generated. Core Data generates the code for property accessors whether or not you use #dynamic. #dynamic just informs the compiler that code will be generated, so it doesn't need to warn about missing methods. That's why you get warnings but no runtime errors.
The #private on the instance variable doesn't do much. The default is #protected, which means outside classes can't access it anyway, only the class itself and subclasses. In any case, the default Core Data accessors don't use instance variables.
I'm not sure how to do what you want.

Related

Accessing an Objective-C ivar from outside the class at runtime

I know this idea completely breaks encapsulation, but say I have the following class extension:
#interface MyClass () {
int reallyImportantIvar;
}
// ...
#end
Normally, the class behaves like it should inside the Objective-C layer - sending and receiving messages, etc. However there is one ('public') subroutine where I need the best possible performance and very low latency, so I would prefer to use a C method. Of course, if I do, I can no longer access reallyImportantIvar, which is the key to my performance-critical task.
It seems I have two options:
Make the instance variable a static variable instead.
Directly access the instance variable through the Objective-C runtime.
My question is: is Option 2 even possible, and if so, what is its overhead? (E.g. Am I still looking at an O(n) algorithm to look up a class's instance variables anyway?)
Actually, if the definition of the C function is within the #implementation block of the class, then it can access private ivars on that class via the usual object->someIvar notation. So while you can use the runtime to access this, I don't think you need to. Just implement the function within the #implementation block of the class in question, and you should be just fine.
Another alternative is to declare the ivar as #package or #public. Then code outside your class's implementation that can #include that class extension can use the ivar.
#public allows any code to do so. #package limits the scope to the same binary as the class's implementation, which is usually appropriate when writing a shared library.
The Objective-C runtime includes the object_getInstanceVariable() function. I believe that's what you're looking for. I haven't checked in detail, but I don't believe there is any big difference between accessing it that way and the normal way.

Will the compiler auto-synthesize an ivar for a property declared in a category?

Before so-called "Modern Objective-C", when creating a new property in category, we needed to implement setter and getter methods. Now, we don't have to do #synthesize; the compiler will automatically create the methods and an instance variable.
But normally, we cannot add instance variables to a category, so what happens if we add a new property in a category with modern Objective-C? Does the compiler create an ivar for us?
You can declare a property in a category, which is equivalent to declaring the getter and (if readwrite) setter selectors.
The compiler will not automatically synthesize the getter and setter methods in your category implementation. If you don't explicitly define them in the category implementation, the compiler will issue a warning. You can use #dynamic in the category implementation to suppress the warning. You cannot use #synthesize in the category implementation; the compiler will issue an error if you try.
The compiler will not add an instance variable for a property declared in a category. You cannot explicitly add instance variables in a category, and you can't trick the compiler into doing it using a property.
I tested my claims using Xcode 4.5.1 targetting iOS 6.0.
Actually I don't know when we were able to add property in categories.
From Apple Docs:
A category allows you to add methods to an existing class—even to one for which you do not have the source.
and
Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main #implementation block for the corresponding class. Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension.
and this method is used to add storage to an object without modifying the class declaration (in case you couldn't modify or don't have access to source codes of class)
Associative references, available starting in OS X v10.6, simulate the addition of object instance variables to an existing class. Using associative references, you can add storage to an object without modifying the class declaration. This may be useful if you do not have access to the source code for the class, or if for binary-compatibility reasons you cannot alter the layout of the object.
So your question for me seems to be incorrect.
Source: Apple Docs - The Objective-C Programming Language
As others have said, the way to do this is with Associative References. They are implemented much like CALayer's value / key-pair paradigm.. in that basically.. you can "associate" anything, with any "property", or "thing"…
So in your category header… if all you want to do is read a value…
#property (readonly) NSString *uniqueID;
and then write your getter…
- (NSString*) uniqueID { return #"You're not special"; }
But say.. you can't just come up with the value from within your getter.. and you need storage for either an external setter… or the class' own implementation to use… you HAVE to write a setter like...
- (void) setUniqueID:(NSString*)uId
It need not be public, necessarily… but this is where the "magic" happens.
…
[self setAssociatedValue:uId forKey:#"yourInternalStorageName"
policy:OBJC_ASSOCIATION_RETAIN_NONATOMIC];
I realized after looking at this, that I'm using some "personal categories" to help ease the setting and getting etc. of these values.. so I've posted them to this gist, as they are VERY useful.. and include such little gems as…
- (id) associatedValueForKey:(NSString*)key
orSetTo:(id)anObject
policy:(objc_AssociationPolicy) policy;
The secret to "getting it" is the "policy" portion.. These values…
OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403
capture the same "personality" traits as are expressed when describing your properties in a "normal" declaration. You must tell the compiler how to "store" your values with those same rules, and you'll be good to go.

When to use instance variables and when to use properties

When using Objective-C properties can you stop creating instance variables altogether or do explicit instance variables (not the ones synthesized by the properties) still serve a purpose where properties would be inappropriate?
can you stop creating instance variables altogether
No, you can't (in a sense). What you can do is stop declaring them if you have properties. If you synthesize a property and you haven't declared the instvar, it will get declared for you, so you are creating an instance variable, just not explicitly.
do they still serve a purpose where properties would be inappropriate?
It used to be the advice to create properties for everything because having synthesized properties does almost all of the retains and releases for you. However, with ARC that reason for using properties to wrap the memory management has gone away. The advice now (for ARC) is, I believe, use properties to declare your external interface, but use direct instance variables where the variable is part of the object's internal state.
That's a good reason to adopt ARC: properties revert to their true purpose only of being part of the class's API and it's no longer necessary to use them as a hacky way to hide memory management work.
Edit
One more thing: you can now declare instance variables in the #implementation so there is now no need to leak any implementation details in the #interface. i.e.
#implementation MyClass
{
NSString* myString;
}
// method definitions
#end
And I'm pretty sure it works in categories too. - see comment below
I recommend declaring everything as properties and avoiding manual ivars altogether. There is no real upside to manually creating ivars. Declare public properties in your header #interface, declare private properties in a private class extension in your .m file.
To some of JeremyP's points, internal use of accessors still has significant value under ARC, even though memory management is no longer a significant concern. It ensures that KVO works properly, subclasses better, supports custom setters (particularly for things like NSTimer), supports custom getters (such as for lazy instantiation), etc. It is exceedingly error-prone to have a mix of accessors and ivars. It's far too easy to forget which you need to access in which way. Consistency is the hallmark of good ObjC.
If you absolutely must declare an ivar for some reason, then you should do it in the #implementation block as JeremyP notes.
UPDATE (Oct-2013):
Apple's guidance (From Programming with Objective-C: Encapsulating Data):
Most Properties Are Backed by Instance Variables
In general, you should use accessor methods or dot syntax for property access even if you’re accessing an object’s properties from within its own implementation, in which case you should use self:
...
The exception to this rule is when writing initialization, deallocation or custom accessor methods, as described later in this section.
This question was addressed before here
When you use synthesize the instance variables are handled and instantiated for you. If you're using Lion with the new version of XCode also take a look at the various properties in ARC in Transitioning to ARC
you can always access properties from outside. So if you want a variable only to be read from inside a class you still have to declare a iVar. Also accessing a public ivar with object->ivar is slightly faster than using a method-call.

Minutia on Objective-C Categories and Extensions

I learned something new while trying to figure out why my readwrite property declared in a private Category wasn't generating a setter. It was because my Category was named:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSArray* myProperty;
#end
Changing it to:
// .m
#interface MyClass ()
#property (readwrite, copy) NSArray* myProperty;
#end
and my setter is synthesized. I now know that Class Extension is not just another name for an anonymous Category. Leaving a Category unnamed causes it to morph into a different beast: one that now gives compile-time method implementation enforcement and allows you to add ivars. I now understand the general philosophies underlying each of these: Categories are generally used to add methods to any class at runtime, and Class Extensions are generally used to enforce private API implementation and add ivars. I accept this.
But there are trifles that confuse me. First, at a hight level: Why differentiate like this? These concepts seem like similar ideas that can't decide if they are the same, or different concepts. If they are the same, I would expect the exact same things to be possible using a Category with no name as is with a named Category (which they are not). If they are different, (which they are) I would expect a greater syntactical disparity between the two. It seems odd to say, "Oh, by the way, to implement a Class Extension, just write a Category, but leave out the name. It magically changes."
Second, on the topic of compile time enforcement: If you can't add properties in a named Category, why does doing so convince the compiler that you did just that? To clarify, I'll illustrate with my example. I can declare a readonly property in the header file:
// .h
#interface MyClass : NSObject
#property (readonly, copy) NSString* myString;
#end
Now, I want to head over to the implementation file and give myself private readwrite access to the property. If I do it correctly:
// .m
#interface MyClass ()
#property (readwrite, copy) NSString* myString;
#end
I get a warning when I don't synthesize, and when I do, I can set the property and everything is peachy. But, frustratingly, if I happen to be slightly misguided about the difference between Category and Class Extension and I try:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSString* myString;
#end
The compiler is completely pacified into thinking that the property is readwrite. I get no warning, and not even the nice compile error "Object cannot be set - either readonly property or no setter found" upon setting myString that I would had I not declared the readwrite property in the Category. I just get the "Does not respond to selector" exception at runtime. If adding ivars and properties is not supported by (named) Categories, is it too much to ask that the compiler play by the same rules? Am I missing some grand design philosophy?
Class extensions were added in Objective-C 2.0 to solve two specific problems:
Allow an object to have a "private" interface that is checked by the compiler.
Allow publicly-readable, privately-writable properties.
Private Interface
Before Objective-C 2.0, if a developer wanted to have a set of methods in Objective-C, they often declared a "Private" category in the class's implementation file:
#interface MyClass (Private)
- (id)awesomePrivateMethod;
#end
However, these private methods were often mixed into the class's #implementation block (not a separate #implementation block for the Private category). And why not? These aren't really extensions to the class; they just make up for the lack of public/private restrictions in Objective-C categories.
The problem is that Objective-C compilers assume that methods declared in a category will be implemented elsewhere, so they don't check to make sure the methods are implemented. Thus, a developer could declare awesomePrivateMethod but fail to implement it, and the compiler wouldn't warn them of the problem. That is the problem you noticed: in a category, you can declare a property (or a method) but fail to get a warning if you never actually implement it -- that's because the compiler expects it to be implemented "somewhere" (most likely, in another compilation unit independent of this one).
Enter class extensions. Methods declared in a class extension are assumed to be implemented in the main #implementation block; if they're not, the compiler will issue a warning.
Publicly-Readable, Privately-Writeable Properties
It is often beneficial to implement an immutable data structure -- that is, one in which outside code can't use a setter to modify the object's state. However, it can still be nice to have a writable property for internal use. Class extensions allow that: in the public interface, a developer can declare a property to be read-only, but then declare it to be writable in the class extension. To outside code, the property will be read-only, but a setter can be used internally.
So Why Can't I Declare a Writable Property in a Category?
Categories cannot add instance variables. A setter often requires some sort of backing storage. It was decided that allowing a category to declare a property that likely required a backing store was A Bad Thing™. Hence, a category cannot declare a writable property.
They Look Similar, But Are Different
The confusion lies in the idea that a class extension is just an "unnamed category". The syntax is similar and implies this idea; I imagine it was just chosen because it was familiar to Objective-C programmers and, in some ways, class extensions are like categories. They are alike in that both features allow you to add methods (and properties) to an existing class, but they serve different purposes and thus allow different behaviors.
You're confused by the syntactic similarity. A class extension is not just an unnamed category. A class extension is a way to make part of your interface private and part public — both are treated as part of the class's interface declaration. Being part of the class's interface, an extension must be defined as part of the class.
A category, on the other hand, is a way of adding methods to an existing class at runtime. This could be, for example, in a separate bundle that is only loaded on Thursdays.
For most of Objective-C's history, it was impossible to add instance variables to a class at runtime, when categories are loaded. This has been worked around very recently in the new runtime, but the language still shows the scars of its fragile base classes. One of these is that the language doesn't support categories adding instance variables. You'll have to write out the getters and setters yourself, old-school style.
Instance variables in categories are somewhat tricky, too. Since they aren't necessarily present when the instance is created and the initializer may not know anything about them, initializing them is a problem that doesn't exist with normal instance variables.
You can add a property in a category, you just can't synthesize it. If you use a category, you will not get a compile warning because it expects the setter to be implemented in the category.
Just a little clarification about the REASON for the different behavior of unnamed categories (now known as Class Extensions) and normal (named) categories.
The thing is very simple. You can have MANY categories extending the same class, loaded at runtime, without the compiler and linker ever knowing. (consider the many beautiful extensions people wrote to NSObject, that add it functionality post-hoc).
Now Objective-C has no concept of NAME SPACE. Therefore, having iVars defined in a named category could create a symbol clash in runtime. If two different categories would be able to define the same
#interface myObject (extensionA) {
NSString *myPrivateName;
}
#end
#interface myObject (extensionB) {
NSString *myPrivateName;
}
#end
then at the very least, there will be memory overrun at runtime.
In contradiction, Class extensions have NO NAME, and thus there can be only ONE. That's why you can define iVars there. They are assured to be unique.
As for the compiler errors and warnings related to categories and class extensions + ivars and property definitions, I have to agree they are not so helpful, and I spent too much time trying to understand why things compile or not, and how they work (if they work) after they compile.

Quirk with Core Data, protocols, and readwrite vs. readonly property declarations

I'm running into an odd quirk involving Core Data, a declared protocol, and perhaps the LLVM 1.5 compiler. Here's the situation.
I have a Core Data model that among others has two classes, IPContainer and IPEvent, with IPContainer being the parent entity of IPEvent. Each entity has a custom class in the project for it, created using mogenerator. mogenerator generates an additional subclass that just contains the modeled property declarations, so the class hierarchy is actually IPEvent > _IPEvent > IPContainer > _IPContainer > NSManagedObject. The IPContainer entity has an attribute named 'id', which is declared as #property(nonatomic, retain) NSNumber* id; in _IPContainer.h. _IPContainer.m has #dynamic id; in the implementation, to tell Core Data to generate the accessors at runtime
I also have a protocol IPGridViewGroup declared in my project which defines several properties, one of which is that same 'id' property. However, a setter is not necessary for classes implementing this protocol, so the property in the protocol is declared as #property(readonly) NSNumber* id; The IPEvent class declares that it conforms to the IPGridViewGroup protocol.
This worked fine using the Clang/LLVM 1.0.x compiler (whichever version shipped with Xcode 3.2.2), but upon upgrading to Xcode 3.2.3 and Clang/LLVM 1.5, a whole bunch of things changed. First, I get the following warning when compiling the IPEvent class:
/Volumes/Ratbert/Users/bwebster/Projects/UberProject/iPhotoLibraryManager/IPGridViewGroup.h:19:31: warning: property 'id' requires method 'id' to be defined - use #synthesize, #dynamic or provide a method implementation
Then, when I actually run the program, this gets printed out in the console:
Property 'id' is marked readonly on class 'IPEvent'. Cannot generate a setter method for it.
Followed shortly by:
-[IPEvent setId:]: unrecognized selector sent to instance 0x200483900
I also tried redeclaring the property on the IPEvent class, but that just gave me a different compiler warning, and the same behavior at runtime:
/Volumes/Ratbert/Users/bwebster/Projects/UberProject/iPhotoLibraryManager/IPManagedObject/IPEvent.h:14:40: warning: property 'id' 'retain' attribute does not match the property inherited from 'IPGridViewGroup'
Now, the only thing that's changed here is the compiler, so the catalyst for the change is clear, but what I don't know is whether this could be considered a bug in the new version of the compiler, or if the old version of the compiler was actually behaving incorrectly, and the new version now reveals that it's my own code that's buggy.
So among the questions I have here are:
It seems like it should be OK to have a class conform to a protocol with a readonly property, but provide readwrite access for the property in its own implementation, is that correct? The quirk here though is that the readwrite property is actually declared in the superclass of the class that conforms to the protocol.
I'm assuming that console message is being printed out somewhere in the bowels of Core Data. This is odd though, because IPEvent itself doesn't declare the 'id' property explicity, except by conforming to the IPGridViewGroup protocol. However, if this is the case, then I would think a compiler error would come up, since it would effectively being overriding a readwrite property (declared in the _IPContainer superclass) with a readonly version of the same property, which AFAIK is normally not allowed.
If this is a compiler bug, then fine, I can work around it in a couple different ways for now. If the compiler is doing the right thing here though, then I'm at a loss to come up with a way to organize all this so I don't get any compiler warnings or runtime errors.
Edit: so, the workaround is to redeclare the property again on the IPEvent class, but I'm still puzzled as to why the two versions of the compiler act differently. It's also unclear how exactly properties declared on a protocol are supposed to interact with those declared on a class.
If I declare a readonly property in the class (rather than the protocol) overriding a readwrite property, I get the message "warning: attribute 'readonly' of property 'longitude' restricts attribute 'readwrite' of property inherited from '_IPEvent'". It seems like if declaring it in the protocol has the same effect, a similar warning should come up from the compiler.
Intuitively though, I would think that since IPEvent already implements the necessary getter for the property, that should count as "conforming to the protocol", even if it happens to also implement a setter for the property.
Now, the only thing that's changed
here is the compiler, so the catalyst
for the change is clear, but what I
don't know is whether this could be
considered a bug in the new version of
the compiler, or if the old version of
the compiler was actually behaving
incorrectly, and the new version now
reveals that it's my own code that's
buggy.
The newer compiler has noticed that you have two separate definitions for the accessors for the same instance variable of the same class. Of course, the linker should complain.
The old compiler should have kicked this back. The #property declaration is an implicit method declaration whether it occurs in a class or a protocol. When you have both a class and a protocol define a property with the same name, you end up with two sets of method declarations for one class. This is obviously going to cause problems somewhere along the line.
The differences between the two compilers could be something trivial such as the order of the #import statements in source or even the modification dates on the source files.
You're obviously getting a collision because the IPContainer class has two dynamic method definitions, one generates just a setter and the other a setter and a getter. How should the compiler know which one to use? You've just told it that you want a readonly readwrite property. Worse, since this is a dynamic property, there is no telling what will actually be generated at runtime.
1 It seems like it should be OK to
have a class conform to a protocol
with a readonly property, but provide
readwrite access for the property in
its own implementation, is that
correct?
Define "OK". Will the compiler accept it? Probably. After all, in a readonly property in the protocol you've defined a getter method but in the class you've also defined a setter method. Since a protocol doesn't restrict what additional methods an implementing class can have, the setter method can be added just like you could add any other unrelated method.
However, this is obviously very, very dangerous, especially in the case of NSManagedObject subclasses. The managed object context has very firm expectations about what it expects to find in the classes it works with.
2 This is odd though, because IPEvent
itself doesn't declare the 'id'
property explicity, except by
conforming to the IPGridViewGroup
protocol.
If the property is required by the protocol, it is explicitly declaring it by adopting the protocol.
3 If this is a compiler bug, then
fine, I can work around it in a couple
different ways for now. If the
compiler is doing the right thing here
though, then I'm at a loss to come up
with a way to organize all this so I
don't get any compiler warnings or
runtime errors.
The simplest solution is (1) Don't define protocols that overlap class properties. Doing so defeats the entire purpose of having a protocol anyway. (2) Make the protocol property readwrite so the compiler and the runtime are not confused.
Intuitively though, I would think that
since IPEvent already implements the
necessary getter for the property,
that should count as "conforming to
the protocol", even if it happens to
also implement a setter for the
property.
You could probably get away with it if your weren't using dynamic properties. With a dynamic property the complier has to generate a message to the runtime explaining what accessors to generate on the fly. What's it supposed to say in this case? "Generate a method that conforms to the readonly protocol but by the way make it readwrite at the same time?"
No wonder the compiler is complaining. If it was a dog, it would be wetting itself in confusion.
I think you need to seriously rethink your design. What possible benefit can you gain from such a non-standard, risky design? Getting compiler errors is the best case scenario. In the worst case, the runtime gets confused with unpredictable results.
In short, (with apologies to Shakespeare) "...the fault lies not in the complier but with ourselves."
Let's try and break this down a bit. If I understand correctly:
IPEvent is a class which inherits _IPEvent and implements IPGridViewGroup.
IPGridViewGroup has a readonly property id.
_IPEvent inherits the readwrite property id from _IPContainer.
Assuming those assumptions are correct (and please tell me if I'm wrong) then IPEvent has inherited two different id properties, one of which is readonly and one of which is not.
Did you try redefining the id property in IPEvent with the explicit readwrite modifier?
ex:
#property (nonatomic, retain, readwrite) NSNumber *id;
Hopefully then the compiler will get the hint and generate a setter.
#property(readonly) NSNumber* id
Looks incorrect. Core Data docs say you should use nonatomic (since you can't use threading here), and you should also be retaining id since it's an object, not assigning it (the default).
If a subclass needs to access an ivar of a superclass it needs to declare its property and use #dynamic to tell the compiler to be quiet. It does not look like you are doing that.
It could also be connected with this bug I found that varies between compilers:
http://openradar.appspot.com/8027473 Compiler forgets superclass ivar exists if a prop without an ivar is declared
It is also possible that id has a special meaning in Core Data and you should use a different name.