Can I remove the #private generated by Core Data? - objective-c

What is the #private for in the file generated by Core Data below? I know what #private means in Objective-C, but there are not instance variables listed after it, so can't I just take it out?
//
// Event.h
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Event : NSManagedObject {
#private
}
#property (nonatomic, retain) NSDate * timestamp;
#end
//
// Event.m
//
#import "Event.h"
#implementation Event
#dynamic id;
#end

You can safely take it out, it won't change the semantics of your class. If you're not statisfied with what XCode generates for you (though it's a reasonable default), I'd suggest you take a look at https://github.com/rentzsch/mogenerator.

You can, but it doesn't hurt. If you generate the model again it will just put it back.

Xcode now defaults to generating classes with #private for instance variables, which you are supposed to declare in case you need them. You can safely remove that #private since, as you’ve already noticed, there are no instance variables. In fact, that class declaration is equivalent to
#interface Event : NSManagedObject
#property (nonatomic, retain) NSDate * timestamp;
#end

Related

Can I change the type of a property in a class extension?

I wish to expose a property with a generic type in a public header, and then change its type to a more specific one in a private header. I'm using Clang, but though I'm able to change its read/write property, it doesn't accept a different type. So far this is what I tried:
A common client would import BKSystem.h:
#interface BKSystem : NSObject
#property(nonatomic, readonly) id<XYZWorker> worker;
#end
While a client for testing has access to internals by importing BKSystem+Testing.h:
#import "BKSystem.h"
#interface BKConfigurableWorker : NSObject<XYZWorker>
#property(nonatomic) BKConfiguration *config;
#end
#pragma mark -
#interface BKSystem ()
// Attempts to change worker to be writable and with a more specific type.
#property(nonatomic, readwrite) BKConfigurableWorker *worker;
#end
But on a testing client this is what I get:
#import "BKSystem+Testing.h"
BKSystem *system = [[BKSystem alloc] init];
// I am able to write to this property.
system.worker = [[BKConfigurableWorker alloc] init];
// ERROR: Property 'config' not found on object of type 'id<XYZWorker>'
system.worker.config = [[BKConfiguration alloc] init];
To accomplish what you're trying to do, I'd use BKWorker as a subclass rather than a protocol. See my example header file below:
#interface BKConfiguration : NSObject
#end
#interface BKWorker : NSObject
#property (nonatomic, strong, readonly) BKConfiguration *config;
#end
#interface BKConfigurableWorker : BKWorker
#property (nonatomic, strong, readwrite) BKConfiguration *config;
#end
Notice that the same property is declared again in the configurable worker, but as readwrite rather than readonly.
This produces the following results when used in an implementation:
Notice how the configurable worker can be written to but the standard one can not.
Hope this helps.

Forward Declaration vs #import when subclassing

I have MyClassA which has a property of type MyClassB
//
// MyClassA.h
//
#interface MyClassA : NSObject
#property (strong, nonatomic, readonly) MyClassB *myClassB;
#end
MyClassB has a property myString.
//
// MyClassB.h
//
#interface MyClassB : NSObject
#property (copy, nonatomic, readonly) NSString *myString;
#end
I have MyClassC which needs to access myString in it's implementation.
Should I -
a) Forward Declare MyClassB in MyClassA.h and #import "MyClassB.h" in MyClassC.m
or
b) #import MyClassB.h in MyClassA.h
In general, you should forward declare with #class where possible in your header files. The only time you probably wouldn't want to do it is when you're inheriting from a super class or declaring protocol conformance, because the compiler needs to know what is going on in that class or protocol.
For this instance, I would use #class for all your property declarations in your header files, and #import MyClassB.h in your MyClassC.m file. That will allow MyClassC to know about all the properties on MyClassB.
Looking at this from a slightly different angle ... you need to decide if you want the world to really know about myClassB being a property of MyClassA. For example, if you may only want to advertise that myString that can be obtained through MyClassA. This insulates other classes from knowing the underlying implementation of myString. Unless you have a need to expose MyClassB you should hide it from the "rest of the world".
In this case you would change MyClassA.h as follows:
//
// MyClassA.h
//
#interface MyClassA : NSObject
#property (strong, nonatomic, readonly) NSString *myString;
#end
In MyClassA.m, you would do the following.
//
// MyClassA.m
//
#import "MyClassA.h"
#import "MyClassB.h"
#interface MyClassA()
#property (strong, nonatomic) MyClassB *myClassB;;
#end
#implementation MyClassA
// Other meaningful code omitted
- (NSString *)myString {
return self.myClassB.myString;
}
#end
Note that what I've done here is use an anonymous category to internally define property for myClassB.
The key thing here is whether or not it makes sense to not expose MyClassB to others. The main advantage of this approach is your code is more malleable. Let's say myString gets derived a different way. From a different class or different method altogether. The code which needs to consume myString is immunized.
If you need to expose MyClassB, then you can either use #class as recommended by Tyler above or #import MyClassB.h from MyClassA.h. Best practices prescribe forward declaring #class. But at times the convenience of not having to remember to import a lot of files within the implementation file can win out. It's your code-base, so you can pick which one works the best for you. I generally use a combination of the two.

NSObject subclass as a property

I want to use my class as a property in my project. The idea is that i have a class which contains all list ellements. The basic idea i show below in graph:
So i have a myContainerClass object, and i want to do in some other class:
#property (strong,nonatomic) MyContainerClass *obj;
and here i have error! I figure out that i can only use Foundations type as a #property. But Why? What is replacement for doing that (passing an object)?
No, you can use any class you like as a property
#property (nonatomic, strong) MyContainerClass* obj;
is perfectly legal provided that the compiler knows that MyContainerClass is a class. To do that in the header file, the best way is to use an #class forward declaration:
#class MyContainerClass;
#interface SomeOtherClass : NSObject
// method an property declarations
#property (nonatomic, strong) MyContainerClass* obj;
#end
And then include the header file in the implementation:
#import "MyContainerClass.h"
#implementation SomeOtherClass
#synthesize obj;
// other stuff
#end
What is the error you are getting? May be you are not importing MyContainerClass to where you want to use it.
#import "MyContainerClass.h"
Declare a category for an object that you want to add your property to:
#interface NSObject (MyContainerClassAdditions)
#property (nonatomic, strong) MyContainerClass *myContainerClass
#end
Then implement the setter and getter methods using objective c associated object trick:
#import <objc/runtime.h>
#implementation NSObject (MyContainerClassAdditions)
- (void)setMyContainerClass:(MyContainerClass *)myContainerClass {
objc_setAssociatedObject(self, "myContainerClass", myContainerClass, OBJC_ASSOCIATION_ASSIGN);
}
- (MyContainerClass *)myContainerClass {
return objc_getAssociatedObject(self, "myContainerClass");
}
#end

XCode: Unrecognized selector sent to instance

I am getting the following error:
"-[Order items]: unrecognized selector sent to instance 0x6b5f240"
I do have a class called Order, which looks like this:
Order.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class OrderItem;
#interface Order : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * orderID;
#property (nonatomic, retain) NSDate * date;
#property (nonatomic, retain) NSNumber * orderCode;
#property (nonatomic, retain) NSSet* items;
#end
Order.m
#import "Order.h"
#import "OrderItem.h"
#implementation Order
#dynamic orderID;
#dynamic date;
#dynamic orderCode;
#dynamic items;
...
It doesn't extend any sort of class which has an "items" method, if I'm reading that correctly?
Is there any other reason I would be getting such an error. To add to the madness, this project is copied directly from a previous project, with some minor edits. I've done text comparisons on every single class in both projects and there are no differences other than the cosmetic changes I've made.
#dynamic items tells the compiler that you will be providing the methods for items.
Since this was working in a previous project, it must have had the following method somewhere in the .m file:
- (NSSet *)items {
// Appropriate code
}
If you do not want to provide your own custom getter like this, then change #dynamic items to #synthesize items and the compiler will generate one for you.
For more details, see the Declared Properties section of The Objective-C Programming Language provided by Apple here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
EDIT
While everything above still applies to a normal object (and may still apply here), I just noticed that this is a subclass of NSManagedObject.
In your old data model there was probably a relationship called items and therefore the appropriate methods were provided by NSManagedObject and #dynamic was appropriate to prevent compiler warnings.
If in your new data model there is no relationship named items, then the methods will not be generated and it will cause the problem that you are getting here.

How to define and implement properties in protocol

I want to define one protocol with few properties and need to use those properties in another NSObject subclass. Please give me link or example code. I need that to work with 10.5.
Thanks
PLEASE CHECK THE FOLLOWING SAMPLE CODE
#protocol MyProtocol
#property (nonatomic, readonly) id someObject;
#property (nonatomic, getter=isAlive) BOOL alive;
#end
#import "MyProtocol.h"
#interface MyCustomClass : NSObject <MyProtocol>{
}
#end
#import "MyCustomClass.h"
#implementation MyCustomClass
#synthesize someObject,alive;
/*
- (id)someObject {
return nil;
}
- (BOOL)isAlive {
return YES;
}
- (void)setAlive:(BOOL)aBOOL {
}
*/
#end
**Added:
Compling code with x86_64 architecture works fine. But error if i'll change the architecture to i386, then i am getting following warnings:
MyCustomClass.m:13: error: synthesized property 'someObject' must either be named the same as a compatible ivar or must explicitly name an ivar
error: synthesized property 'alive' must either be named the same as a compatible ivar or must explicitly name an ivar
I just want to know why it is working in x86_64 with #synthesize and not in i386.**
#property just says to the compiler that the class is expected to define the methods to match that property.
#protocol MyProtocol
#property (nonatomic, readonly) id someObject;
#property (nonatomic, getter=isAlive) BOOL alive;
#end
Anything implementing that protocol will now need to have
- (id)someObject;
- (BOOL)isAlive;
- (void)setAlive:(BOOL)aBOOL;
I think the things you're dealing with are primarily side effects of the introduction of Objective-C 2.0. It lets you do things like declare properties without also defining instance vars. But (as you have discovered), it is only x86_64 and post-10.5 compatible.