I have two classes, Entity, and EntityHandler.
EntityHandler has a method, AddEntity. This method adds the Entity to an NSMutableArray.
Entity has a method called subscribe. It assigns a reference to EntityHandler to a variable for later usage.
Upon the inclusion of both header files in each other the project breaks. For example,
-(void) addEntity: (Entity *) mob;
returns the error
Expected a type
How can I fix this?
You're looking to employ forward declarations for your ObjC types, in order to break the cyclic header dependency.
It would look something like:
// EntityHandler.h
#class Entity; // << the forward declaration. not #import.
#interface EntityHandler : NSObject
-(void) addEntity:(Entity *) mob;
#end
This tells the compiler that there is an ObjC class named Entity.
Then you #import when you need more than a typename (likely in EntityHandler.m).
Related
Here below the definitions of two classes (Foo and Bar) and two respective subclasses (SubFoo and SubBar). Foo is a kind of a dummy class and Bar has a method that takes a Foo instance as a parameter:
#interface Foo
#end
#interface SubFoo : Foo
#end
#interface Bar
- (void)doSthWithFoo:(Foo *)aFoo;
#end
#interface SubBar : Bar
// other methods
#end
Implementations are skipped but consider them being straightforward.
Only then in the implementation of SubBar there is this twist:
#implementation SubBar
- (void)doSthWithFoo:(SubFoo *)aFoo
{
// Do stuff with object of type *SubFoo*
}
// other methods
#end
In the subclass, doSthWithFoo: is overridden and the parameter type is changed to SubFoo – in place of Foo, as in the parent class. This is intentionally done so, as SubBar can only work with SubFoo's so to speak.
This compiles fine, runs fine and does not produce any warnings – kind of surprisingly I must admit. But somehow it doesn't feel very right, even though IMO it's a relatively clean way of doing things..
I am aware that a parameter of type id could be passed instead, but then I'd lose type checking (for Foo) from within Xcode. I am also aware that the same could be accomplished by assigning to id and then to the specific type or by checking and casting – although I haven't tried those options.
Is this a "legitimate" way of doing things? Are there any other alternatives?
What did I do here? Can method parameters be typeless?
In a recent project which works fine, the App is in the store already - no issues so far, I did the following in a .h file:
#property (strong, nonatomic) NSManagedObject *myPerson;
- (HKPersonPicker*) initWithPerson:person;
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate;
I meant to do it this way but did not:
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person;
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person delegate:(id <HKPersonPickerDelegate>)delegate;
The corresponding part of the .m file:
- (HKPersonPicker*) initWithPerson:person
{
self = [super init];
if(self){
self.myPerson = person;
}
return (self);
}
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate
{
self = [self initWithPerson:person];
if(self){
self.delegate = delegate;
}
return (self);
}
As you can see I did not do anything special with this person object, just assigned it to the property myPerson. As I did not call any of the object's methods or accessed its data, the compiler did not need to know anything about that object. But what is it from the compiler's point of ivew? Type id? Just something? Is there any default type?
As you see, I do not have any real problem. I am just curious. Hope this question does not break any SO rule.
With C the default type is int, but with Objective-C it's id.
Missing type declarations in methods default to id. IIRC, you can see a fair number of methods without return types in Apple's runtime library.
There is no definitive problem with what you are doing, but its not really kosher at the same time. You should still have a type declaration for the sake of clarity, and maintaining good and consistent Cocoa-like code styling.
So it should really be like:
- (GSPersonPicker*) initWithPerson:(id)person;
And you should really change the property declaration:
#property (strong, nonatomic) id *myPerson;
If that is not changed, then your code is confusing. You KNOW the type that will be coming in. So let the compiler help you with meaningful warnings/errors by using types. You should also probably be using the type 'HKPerson' or whatever you have named your entity, so the compiler doesn't think its ok for you to pass in an 'HKPlace' (they will both be of type 'id' and 'NSManagedObject', which does you no favors)
More importantly, you should not be using the dynamic type (id) unless you have a reason. The compiler is there to help you. Errors and warnings are your friend, they tell you that you messed up, not the computer. When you use 'id', the compiler just goes, Oh, anything can go in here!!! And it will not detect an error where you sent that method a type that will break everything.
Now lets say that you are going to use polymorphism. IE, Lets declare a generic protocol for multiple classes to adhere to, which defines our person:
#protocol GSPerson
-(NSUInteger)age;
#end
So now lets define a couple classes, and have them subscribe to the protocol (the GSPerson thats between carrots markdown is killing me atm lol):
#import "GSPerson.h"
#interface GSSpecialPerson <GSPerson>
// code
#end
#import "GSPerson.h"
#interface GSWeirdPerson <GSPerson>
// code
#end
Then lets redefine our method signature to adhere to the protocol:
- (GSPersonPicker*) initWithPerson:(id<GSPerson>)person;
And our property declaration:
#property (strong, nonatomic) id <GSPerson> *myPerson;
Now the compiler knows that anything i pass into that method should conform to the GSPerson protocol I defined above (ie they need a method that returns the persons age). If i try to pass anything else in, it will throw compiler warnings, WHICH IS GOOD.
Even better, it will throw warnings on your polymorphic classes if they are missing their required methods.
I'm trying to cast a Class object to a certain protocol, which defines class methods (+) that that class implements.
I know how to do this with (id< protocol>), as outlined in this question, but I can't seem to figure out the right way for Class objects.
The basic scenario is as follows.
I have a protocol:
#protocol Protocol <NSObject>
+ (id)classMethod:(id)arg;
#end
I then have a function which accepts a Class object, which it knows sometimes conforms to the protocol based on another argument (this is obviously very simplified):
- (id)someMethodWithClass:(Class)cls andUseArg:(BOOL)arg
{
id instance;
if (arg != nil) {
instance = [(Class<Protocol>)cls classMethod:arg];
}
}
Now I don't get any warnings on this, and it looks right to me. (I'm not going to see any errors in any case, because I can guarantee that if arg != nil then the class conforms.)
However, I'm not getting autocompletion in Xcode, which makes me wonder if this is the right way to do it. Any thoughts? (Note that I am not interested in instance being id< Protocol>.)
If you want to determine whether cls conforms to a particular protocol (and assuming that classMethod: is a required class method of that protocol), you can simply:
- (id)someMethodWithClass:(Class)cls andUseArg:(BOOL)arg
{
id instance;
if ([cls conformsToProtocol:#protocol(Protocol)]) {
instance = [cls classMethod:arg];
}
return instance;
}
Alternatively, just see if it responds to a particular class method selector:
- (id)someMethodWithClass:(Class)cls andUseArg:(BOOL)arg
{
id instance;
if ([cls respondsToSelector:#selector(classMethod:)]) {
instance = [cls classMethod:arg];
}
return instance;
}
The question is 11 years old and there is nothing wrong with the Rob's answer, but I find it unfortunate that the centrepiece part of it (whether type-casting a Class object with a protocol is a correct syntax) never got proper attention.
First of all static typing in Objective-C is very artificial thing, and it exists solely for the compiler to emit a warning (not even an error). Let's start with what Class objects really is - if you take a look at the documentation, you will find that the Class type is actually an alias for objc_class * type:
typedef struct objc_class *Class;
You can find definition of objc_class type in the source codes of Apple's objc runtime library:
// inherits objc_object with some adjustments
struct objc_class : objc_object { ... }
As you can see, objc_class is just an extension to a objc_object. Any Objective-C class is in fact instance of this objc_object. E.g. here is how NSObject or id aliases look like:
// "translation" of an Objective-C class declaration
typedef struct objc_object NSObject;
// the same for `id` type but with the pointer type included
typedef struct objc_object *id;
It means that "static typing" doesn't exist in Objective-C, the "typing" of an instance happens via introspection of a given instance (different kind of meta-information objc_object stores). It makes all Objective-C classes compatible with each other (first - because it's a pointer, second - because it's a pointer to the same structure). E.g. you can write code like this:
Class obj = [NSObject new];
..and it will happily compile.
However this purely dynamic nature of the language makes it very error-prone, exposing all kinds of mistakes a programmer can make. In order to avoid that clang in fact does compile time checking of the specified types, but it purely relies on the programmer to provide correct data for a type of an instance, and if the types are incompatible from Objective-C perspective, the compiler can emit a warning for you. This works for instance objects, but unfortunately there is no syntax in Objective-C to type a class object other than with the Class alias. It means that for the compiler all such objects are indistinguishable during compile time.
And all of this is true for protocols typing. Here I mean that when you add a protocol conformance token to a variable type (id<TDWLoadable> var) you merely ask the compiler to check whether the assigned to the variable object conforms to the given protocol:
#protocol TDWLoadable
+ (void)classMethod;
- (void)instanceMethod;
#end
#interface TDWObject : NSObject
#end
// Initializing '__strong id<TDWLoadable>' with an expression of incompatible type 'TDWObject *'
id<TDWLoadable> loadable = [TDWObject new];
For a class object, however, the same check is just ignored, because Class objects cannot be typed:
Class<TDWLoadable> loadable = [[TDWObject new] class];
This behavior is described in the Type Checking section of Protocols part in The Objective-C Programming Language (emphasis mine):
...the declaration
id <Formatting> anObject;
groups all objects that conform to the Formatting protocol into a type, regardless of their positions in the class hierarchy. The compiler can make sure only objects that conform to the protocol are assigned to the type.
In each case, the type groups similar objects—either because they share a common inheritance, or because they converge on a common set of methods.
The two types can be combined in a single declaration:
Formatter <Formatting> *anObject;
Protocols can’t be used to type class objects. Only instances can be statically typed to a protocol, just as only instances can be statically typed to a class. (However, at runtime, both classes and instances respond to a conformsToProtocol: message.)
Also, if we take into account that objc_class is in fact just an extension to objc_object then two expressions of kind:
Class<TDWLoadable> classObj;
id<TDWLoadable> obj;
Should follow the same contract (i.e. + (void)classMethod has to refer to metaclass of classObj and - (void)instanceMethod to the class object itself).
Having that said, since the syntax essentially has no effect and just ignored by the compiler, you are free to come up with your own convention to the Class<Protocol> typing.
i have 7 custom objects with the same properties, createDate and modifiedDate. can i create a method that accepts Object1 but actually takes all 7 objects?
right now, this works:
[self setCreateAndModifiedTimeWithEvent:((Object1 *) object2
WithCreateDate:[[eventsArray objectAtIndex:i] objectForKey:#"create_date"]
AndModifiedDate:[[eventsArray objectAtIndex:i] objectForKey:#"modified_date"]];
.h file
-(void) setCreateAndModifiedTimeWithEvent:(Object1 *)object
WithCreateDate:(NSString *)createStamp
AndModifiedDate:(NSString *)modifiedStamp;
.m file
-(void) setCreateAndModifiedTimeWithEvent:(Object1 *)object
WithCreateDate:(NSString *)createStamp
AndModifiedDate:(NSString *)modifiedStamp
{
object.A = #"Hello,";
object.B = #"World";
}
this would cut back on good chuck of lines of code.
i know you can do this sort of thing with UIView and its subclasses. say i have a
UITextField myTextField.
i can do
((UIScrollView *)myTextField).tag = 2;
is there anything inherently bad about typecasting my objects like this or is it acceptable?
Like Joe said, you'd be better off with something like this:
#interface DatedObject : NSObject
#property NSDate *createDate;
#property NSDate *modifiedDate;
#end
#implementation DatedObject
#synthesize createDate;
#synthesize modifiedDate;
#end
Then have each of the 7 classes inherit from the DatedObject base class. Inheritance is a fundamental part of Object Oriented Programming, and you should learn to use it (wisely).
Then your method can be:
-(void) setCreateAndModifiedTimeWithEvent:(DatedObject *)object
WithCreateDate:(NSString *)createStamp
AndModifiedDate:(NSString *)modifiedStamp;
You could also do this with a protocol, but the nice thing about using a base class that the other classes inherit from is that you only have to implement this functionality in one place. If the 7 classes don't all currently inherit from the same base class (which would end up being the superclass of DatedObject), a protocol is probably the way to go. In that case, you can declare your method like this:
-(void) setCreateAndModifiedTimeWithEvent:(id<DatedObjectProtocol>)object
WithCreateDate:(NSString *)createStamp
AndModifiedDate:(NSString *)modifiedStamp;
One of the big advantages to these two approaches over what you've posted in your question is that you get more help from the compiler in catching places where your code sends a message to an object that doesn't respond to it.
Andrew's answer is correct.
But, if for some reason you don't want to create a common base class or a protocol, you could always set the type of the method parameter to id, like this:
-(void) setCreateAndModifiedTimeWithEvent:(id)object
WithCreateDate:(NSString *)createStamp
AndModifiedDate:(NSString *)modifiedStamp;
Parameters of type id don't do any type checking at compile time (like the values in an NSArray) so you can call any method you want on them without generating compiler warnings (this is obviously quite dangerous if you aren't careful).
You can't use dot notation on id variable without casting, but it's better to cast from an id to a concrete type than to cast from a different unrelated type.
It doesn't actually make any difference except to your code readability though.
A class can be extended in Objective C using a category such as:
#interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
#end
/////////////////////////////
#implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
#end
In this small example, I would be adding the method myFabulousAddition to NSString. I could then call it by [anNSString myFabulousAddition] just as if it were part of the NSString set of methods. Great and useful.
In the Apple documents regarding Categories, the docs state:
There’s no limit to the number of
categories that you can add to a
class, but each category name must be
different, and each should declare and
define a different set of methods.
What if you have something like this:
#interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
#end
#interface NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition; // a DIFFERENT fabulous additional method
// BUT with same name as the other category
#end
/////////////////////////////
#implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
#end
#implementation NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition {
// do something equally fabulous, but DIFFERENT...
}
#end
The lack of a name in the parenthesis indicates that the form is an extension to the class, like so:
#interface MyObject () // No name -- an extension vs category to MyObject
- (void)setNumber:(NSNumber *)newNumber;
#end
Does the category name have any meaning to the compiler or linker? Is the category name part of the method signature in anyway or is it part of a primitive namespace? If the category name is meaningless, how do you know if you are about to stomp on another method and get undefined behavior?
The way to avoid stomping on methods is to prefix your category method names, like this:
#interface NSString (MyCompanyCategoryName)
- (NSString *)MYCO_fabulousAddition;
#end
If you get a collision of method names from different categories, then which one 'wins' at run time is completely undefined.
The name of a category is almost entirely useless, with the exception being that the nameless category (i.e. ()) is reserved for class extensions. Methods from class extensions are supposed to be implemented in the class' main #implementation.
The category name doesn't mean anything special, it's just an identifier. Unless the linker (or runtime loader) decides to give you a warning, there is no way to tell that multiple categories are defining the same method.
The behavior is (largely) unpredictable - one of the categories will win out, but you can't tell which one. Also, I think it's well possible you will start out with one implementation and end up with another one (if the second category is loaded after the first).
It certainly acts as an identifier, from the programmer's point of view. In the compiler point of view category methods are simply added as an extension of the class ( from which it is extending), regardless of the name.
And yes you can add categories of the same class with the same identifiers, even with same functions. But you definitely can't override any function because categories are just part of the class once you define them ( Just like you can't override a function of a class from within that class ).
As they are being added at runtime, they don't raise any error and only at runtime compiler selects the function, which is totally unpredictable.
i believe that they don't have any meaning. You don't really use them in your code ... Since they are categories and ... the semantic of a category ... is just to categorize something, i think this is somewhat logical ...
I would say they just simply gather the methods ...
On the other hand your question is very valid ... You DON'T KNOW if you override a method. If you are in the same project then the compiler issues a warning (or an error ? i don't remember), however if you are overriding a method from a library, then .. you are out of luck ...