When generating an NSManagedObject subclass xcode creates two extra files MyObject+CoreDataProperties.h & MyObject+CoreDataProperties.m to keep the CoreData stuff away from our own code.
This is nice but I noticed in a WWDC clip that they didn't have the +CoreDataProperties.m file in their example. So I tried removing these in my code and everything compiles and runs fine without them, they don't appear to be necessary at all.
Are they required in some way that I've overlooked, or if not, then why does xcode generate them at all?
The short answer:
No, it is not necessary.
The long answer:
Objective-C is a dynamic typing, late binding programming language. In a short form that means, that every type decision can be made at runtime instead of compile time and you can access properties of an and send messages to an object without knowing its type (class).
But it is not necessary for the Core Data framework and you as the user of Core Data and your model to know the type of an managed object for a entity type. It is even not necessary to have a specific type for an entity type. (I do not generate the classes very often and if I do, I do it manually.) Therefore in contrast to other programming languages these generated classes are not necessary to give the compiler a type.
However, the compiler wants to see at least every method at least one time to get the signature (parameter typing). Otherwise it would warn. Even it is possible to have working code like this …
NSManagedObject *person = …
NSString *firstName = [person firstName];
… for an entity type Person with a property firstName, the compiler will warn you, that he does not know anything about a method –firstName.
Instead you can type something like this:
NSManagedObject *person = …
NSString *firstName = [person valueForKey:#"firstName"];
(The compiler knows -valueForKey:, since this is a method declared in NSObject.)
Beside this you get benefits like code completion, check for typing errors and so on. But you do not need to use the code generation tool of Xcode. Simply declare such a class and at the properties at the interface. The accessors can be dynamically generated using #dynamic. (Personally I nearly never use the static code generation.)
Edit: Added the result of the discussion in the comments.
So having the interface (".h-file") of the category, the compiler knows enough to compile the whole code without warnings. This will work at runtime, if it is guaranteed – or checked at runtime – that a corresponding message can be dispatched. This makes sense in many situations from the very beginning of Objective-C, i. e. for forwarding and informal protocols. In the context of Core Data it is used to dynamically generate standard accessor methods. Everything works fine without any implementation.
However, one wants to have an implementation for some reasons, i. e. housekeeping on value changes. In such a case it is useful to have a stub implementation you can edit. But for standard behavior it is not necessary.
Related
I am writing a bridge from a language I am developing and ObjC.
There are several nice introspection C functions in the objective C runtime and I am able to retrieve arguments types for methods using method_getTypeEncoding.
The main problem is with object arguments which are returned as id (encoded as #) but what I would need is the real objc class name like NSString or NSNumber.
Is there a way to solve this issue without parsing the .h files?
Knowing something is an id allows you to know the size of the parameter, which is important when writing a scripting interface. Add another layer where you can dynamically verify assumptions using things like
[objectPassedIn isKindOfClass: [expectedType class]];
You want to be careful hardcoding things like, "Oh this is a string so look for __NSCFString" - because there's no way to know you'll get an instance of __NSCFString or another type. NSString is a class cluster - You could get any custom implementation back when using one.
The actual type of objects is not important to the Objective-C Runtime so you need to add your own layer. You might be able to get some useful info using Clang/llvm as a tool.
I've been wondering why Apple uses data types in Core Foundation that are typedef'd to a pointer type while in Cocoa they are not.
As an example, you would reference a UIColor object like UIColor * while a reference to a CGColor object would be CGColorRef? Or NSURL * and CFURLRef? Why not just always use CGColor * and CFURL *? Or conversely, why no UIColorRef or NSURLRef types, since you never access a UIColor or NSURL directly anyway?
Or for example, why is it id and not id *, since it is actually a pointer and can in fact be typecast to void *?
Specifically, is there some reason Apple had a habit of doing this in their older frameworks, but stopped doing it in Cocoa? Is it simply a matter of style?
What Matt said, but there is a bit more to it.
The typedefs in the C based APIs also allow the implementation details to be hidden. For example, you can have the following without ever defining the __CFURL structure in a public header.
typedef __CFURL *CFURLRef;
Objective-C has long had these kinds of features in the form of categories and, recently added, the ability to move instance variable declarations out of the header file. Expect that, over time, you will see all instance variables removed from the public header files in the SDK.
Note that the Cocoa frameworks long, long, pre-dated CoreFoundation.
As for why id is used instead of id *, that dates back to when Objective-C was first created in the early 1980s. Specifically, the notion of the language was that you would build "software integrated circuits" that could be "plugged together" like real ICs. The goal was to keep the C bits around as implementation details and, ideally, not exposed in your APIs.
As for why you end up with NSString * instead of NSString, that is largely exactly because of the C underpinnings of the language. I wrote a fairly detailed answer to a slightly different SO question that is relevant.
You'll probably also find this answer relevant, too.
The reason for NSURL* vs CFURLRef is pretty much that it's just coding style. Cocoa is an Objective-C API and the general style in Objective-C is to not have a typedef whereas Core Foundation is a C API and the general style of it is to use a typedef. It's pretty much down to coding style.
id vs id* - I am not entirely sure with that, but my guess is it's historical and they just wanted to have the base "object" to be without the *. I don't know for sure the history of that, though. But again it'll just be a style thing.
Assume that:
New Protocol is declared
Method in this protocol is marked #required
Class conforms to Protocol
Class does not implement the method mentioned in Protocol
At compile time, information about this method is known: i.e. that it is required and that this class and any other classes this class may may extend do not implement it.
Why in this case the compiler issues a warning and not an error?
Errors are only issued when the compiler cannot continue because something went terribly wrong.
When calling a method in Objective-C, the method lookup is done during runtime and not during compilation, which C++ does. In Objective-C a "message" is simply sent to the object, something like obj.executeCommand("Hey, can you execute function <name> for me?"). In C++ the object will be called directly, in a way like obj.<name>(). In the case of Objective-C the executeCommand() method is called, which exists. In C++'s case the function is called but it does not exist. These are methods that are linked on the compiler level, which means they both become memory addresses rather than names. executeCommand becomes 0x12345678 but it still uses the same message ("execute function <name>").
This is probably very confusing, but it's related to the way methods are implemented in different languages.
If you feel strongly about it, why not turn on -Werror?
I don't know the real answer but here is a use case that would go against it.
What if you implemented all of the protocol methods in a category???
Main interface declaration adopts the protocol however the protocol method implementation is in a category.
This is valid code but will show compile error if compiler was that strict !!
Objective-C is a dynamic language. The idea of what an implementation is, is different to a static language.
For the most part, it's in code that most of us implement inside the #implementation ... #end block.
But what if a method is not found? Then an object has a chance deal with it dynamically.
Imagine you have an interface for a sound effect player:
#protocol FX
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
#end
An implementation could have the files Beep.mp3, Siren.mp3, Honk.mp3 to play, but instead of implementing each of the methods, it could override -forwardInvocation: and parse the selector string, something like this pseudocode:
NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:#"play"]) {
NSString filename = fileNameFromSelector(selName);
[self playSoundFileNamed:filename];
}
This may seem contrived, but once you start using the dynamic features of the language, you will start finding more and more places where it makes sense. And by sense I mean, does this effort help in the long run?
In the above case, just add a -sound* method name to the interface, and drop in a appropriately named sound file. It just works.
Another example from personal experiments: how to deal with Core Data entities in a more natural way. I want to do this:
NSArray *people = [Person findAllWithNameLike:#"B%"];
instead of mucking about with predicates, fetch requests etc.
But I don't want to define every permutation of method in code.
How about if I wanted to build an XML builder? I would look at a dynamic approach. It has served Groovy Builders well (look at Groovy/Grails for examples).
One last example: I have a traits system where I can define behaviours in the form of groups of methods and have my objects assimilate this behaviour. So, while the compiler doesn't see an implementation for the interface my object conforms to, the implementation is injected into it from a trait class, using the Objective-C runtime. Why would I do this? I find many delegate methods are boiler plate, but at the same time, a single base class for each situation is not flexible enough. Instead of cut and paste from code samples, my 'samples' compile and run :) and any changes are reflected across all projects using the trait.
To really understand why all this is available to you, it is worth playing around with a Smalltalk environment (search Pharo or Squeak). This is where Objective-C has its roots.
And finally, to stop these warnings:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"
#implementation ... #end
#pragma clang diagnostic pop
Because there are times when there are bogus "required" methods in a poorly designed protocol.
They should have been optional but someone insisted they are "required".
Thusly making this a run time issue rather than a compile bug is very very wise.
What is better and why ?
What is better in such situations as the class init method and usual variables in a code ?
What is better and why ?
Explicit typing information is always better unless you just can't use it for some reason (see below).
It allows the compiler to much more stringently validate the code and will catch many errors at compile time that would otherwise cause your app to crash at runtime.
A long, long, time ago, everything in the APIs used id. This proved to be a complete pain in the butt; fragile and led to many crashes that would have been caught with specific types.
So, it was changed. (This was ~1994).
What is better in such situations as
the class init method and usual
variables in a code ?
For init, you have no choice but to use the generic (id) return type. Objective-C does not support either co-variant or contra-variant declarations, nor is there a mechanism for generalizing the declaration of init while also providing support for specific type checking.
Same goes for retain, objectAtIndex:, addObject: and many other methods that take or return one of many kinds of objects (or take 'em as arguments).
And, no, there is absolutely no performance difference whatsoever between id and, say, NSView*.
can you give an example when explicit
typing will cause a problem please?
If you wrote:
- (MyClass *) init;
And in a subclass:
- (MySubclass *) init;
You'd get compiler warnings out the wazoo most likely or you'd have to typecast out the wazoo.
On recent versions of clang (in Lion) you should actually not return id, and instead return instancetype. This is a keyword that is used in return types to specify that the type it returns is an instance of the class receiving the message. It is now the preferred return type for init methods on OS X Lion.
Explicit typing provides build-time protection, informing you of likely problems if you do things such as casting or performing operations on something that probably won't work.
Explicit typing also helps prevent non-obvious transfer of mistyped objects, something traveling through a path in your code you hadn't considered that turns out to be of an unexpected type. This kind of bug often doesn't become clear until the program has been tested a lot, more commonly after its release.
It's also helpful for future programmers (including your future self) trying to work with your code, making to more likely that they'll be able to tell at glance what an object is supposed to be. It makes code more "self-documenting" as a result.
Some things cannot have a meaningful type because no type actually applies. Other times you need to use id because you need to be able to accept any type of object. Cocoa Touch uses it, for example, when referring to the sender of a message because anything could have sent it; specifying an explicit type simply wouldn't work.
The vast majority of the time, though, an explicit type is to your advantage.
Use a type as specific as you can but not more so. Consider how you are using any particular variable, argument, or return type and set its type appropriately.
For example a UITableView's dataSource property is declared as id<UITableViewDataSource> because the table view only cares that its data source is some object which conforms to the UITableViewDataSource protocol. This allows the data source to be flexible enough for use with any specific class which implements the protocol but still allows the compiler to warn you if you attempt to assign an object which does not implement that protocol as the data source.
If you are too specific then your code becomes inflexible, accepting only specific implementations which are not strictly necessary (ie demanding a NSMutableString when you could really work with any NSString).
If you are too vague (typing everything as id for example) then you lose the ability to identify when you are sending unrecognized selectors to a particular instance and the compiler cannot identify any number of invalid statements.
For init methods follow the advice in The Objective-C Programming Language
The return type of an initializer method should be id.
The reason for this is that id gives an indication that the class is purposefully not considered—that the class is unspecified and subject to change, depending on context of invocation. For example, NSString provides a method initWithFormat:. When sent to an instance of NSMutableString (a subclass of NSString), however, the message returns an instance of NSMutableString, not NSString. (See also, though, the singleton example given in “Combining Allocation and Initialization.”)
I don't think there is a performance difference between both.
You can let id return type for init because you can cast the result of your init.
For exemple :
Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init];
Both work but you'll have to cast foo2 variable like that (Toto *)foo in order to access property or methods of your instance without creating a compiler warning. Even if it works fine...
I think some developers let id because they just pass there variable trough instance and don't use it. That kind of use allow to not import the .h
Regards,
KL94
In an existing project I have tried to introduce Core Data long after the project was created, so its model is already in place.
I have created the xcdatamodel and added my only class to it.
That class should act as a global storage for objects in my application.
The class properly implement NSManagedObject and I have verified it gets created and saved in context, also retrieved with a fetch result.
The way of saving data in this class is by means of NSMutableArray. But this is just not working. Here's a fragment of this class:
#interface WZMPersistentStore : NSManagedObject<NSCoding> {
NSMutableArray *persistentStorage;
}
#property(nonatomic,retain) NSMutableArray *persistentStorage;
-(void)add:(id)element;
-(void)remove:(id)element;
-(id)objectAtIndex:(NSUInteger)index;
-(NSUInteger)num;
#end
In the implementation I also override the initWithEntity like this:
- (id)initWithEntity:(NSEntityDescription*)entity insertIntoManagedObjectContext:(NSManagedObjectContext*)context {
NSLog(#"init with entity");
[super initWithEntity:entity insertIntoManagedObjectContext:context];
return [self init];
}
The init method only initialize the mutable array, and I can see from the log that it gets properly called by the app delegate when creating entity.
The add method just send message insertObject to persistentStorage.
The questions that come from this:
Am I doing "conceptually" right ? I
mean, is it correct to have instance
variable in managed object and
initialize like I did ?
when ns logging the size of the
persistentStorage I always get 0
even when logging a moment after the
addObject message (edit: that's not
true, I have verified again and I
correctly got 1 added).
The object stored in managed object
class trough persistentStorage are
normal class with attribute. Is
there something I need to do with
them ? I suppose not because I am
not getting any error at runtime.
No, that is not the "right" approach. You can perform initialization of instance variables in awakeFromFetch. Apple guidelines for NSManagedObject subclasses include the following:
You are also discouraged from
overriding
initWithEntity:insertIntoManagedObjectContext:,
dealloc, or finalize. Changing values
in the
initWithEntity:insertIntoManagedObjectContext:
method will not be noticed by the
context and if you are not careful,
those changes may not be saved. Most
initialization customization should be
performed in one of the awake…
methods. If you do override
initWithEntity:insertIntoManagedObjectContext:,
you must make sure you adhere to the
requirements set out in the method
description [...] (NSManagedObject Class Reference)
To really help, I'd need a deeper understanding of what you're trying to accomplish. Regardless, I strongly suggest combing through Apple's Core Data Programming Guide and sample code before proceeding.
I finally manage to solve this issue. Even if I am a newbie in objective-c, I think that introducing core data after the project is done, is not a good idea. Even if many claim it's easy. Unfortunately, all the people saying so, are showing as proof some really simple tutorial of one entity with one string attribute to change.
Instead for my project I ended up writing much code in addition to the existing one, plus some subclassing (NSManagedObject for example) which break the original model. This added code has also to be written carefully. Derived problem can be as simple as an attribute not saved, or dangerous as deleting wrong entities.
Infact, my problem was due to a wrong configuration in decode and encode method in the classes involved in the process of serialization.
For my questions:
-Point one still remain unanswered, because I am not yet confident in objective-c
-Point two, as I said the related object had some problem with encode/code.
-Point three, I was wrong, there's a lot of code to write, depending how complex is the relevant class.