I have done this successfully many times before, but this time it just won't work.
The code in my .h file:
#interface Images : NSView {
}
- (void) draw;
#end
The .m file (of another object):
- (IBAction) go: (id) sender; {
[Images draw:nil];
}
When I try to compile this, it says the following:
'*' may not respond to '*
Images may not respond to '+draw'
This has me quite confused. Shouldn't this be working?
Please Note: Yes, I have seen the other questions about messages, but none of those answers was even partially helpful for me. After reading them, I was even more confused.
Your draw method is an instance method: it can only be called on instances of the Images class. In your go: method you're trying to call it as a class method—if this is what you want, change it to:
#interface Images : NSView
+ (void)draw;
#end
I think a review of some of the basic concepts of object-oriented programming is in order; namely the difference between a class and an object or instance.
A class, in the general sense, is a collection of data and the functions which act upon it. A class defines the interface that one uses to access and manipulate data that is logically grouped together, and serves as a blueprint for creating objects or instances. See http://en.wikipedia.org/wiki/Class_(computer_programming)
Instances of a class (objects) are the typical things you manipulate in an object-oriented program, and they are created from the class "blueprint" and follow the behavior as specified by the class.
A typical example would be a fruit- take apples for example. An imaginary Apple class would represent all apples in the general sense and would model properties such as color and size and actions such as wash and eat. An instance would represent one, single physical apple- a Granny Smith or Pippin or whatever variety.
Just as it doesn't make sense to wash or eat apples in the general sense of the word (the concept of apples, not the agglomeration), typically it doesn't make sense to tell a class what to do. You tell objects (individual apples) what to do.
The code you present above defines the class Images. The "-" in front of -(void)draw indicates that the draw method only exists for specific objects. It is an instance method in typical OO parlance.
Of course, in Obj-C it is also possible to send a message to a class without requiring an object. This is denoted by a "+" in front of the method name, as other answers indicate. This is called a static method and it typically used to control some shared behavior or aspect of all objects of that particular class.
The problem with your code is that you are declaring -(void)draw as an instance method but calling it as a static method. Which way you want to do things is up to you, and it's difficult to determine from your code what the intent of the Images class is.
Related
Is it a good practice or a bad practice to have same-named methods across classes, particularly where inheritance and/or protocols are involved?
For example, I have a protocol of some kind:
#protocol DataReceiver <NSObject>
- (void)handleNewData:(id)data;
#end
And I have a controller class that owns some stuff, such as
#interface OwnerOfAllThings <DataReceiver>
//this child does NOT conform to DataReceiver
#property (nonatomic, strong) SomeOwnedModel myChild;
#end
But the child is opaque, so my implementation of -handleNewData: is basically just a pass-through and calls a method in the child that takes care of the actual handling. So my question is, although it's not functionally so different, is it a bad idea to put an identically named method in SomeOwnedModel, being that it might be confused with the declaration in the protocol? Or should it in fact be exactly the same, for consistency?
i.e., which is better (assuming that the SomeOwnedModel.h declares the appropriate method):
#implementation OwnerOfAllThings
- (void)handleNewData:(id)data {
//Option 1:
[self.myChild handleNewData:data]; //OR...
//Option 2:
[self.myChild ownerReceivedNewData:data]; //or whatever else
}
#end
Since OwnerOfAllThings is simply invoking the method in the child, I might be inclined to keep the same method names, possibly even have SomeOwnedModel conform to the same protocol. If you use the "use unique names" pattern, I can only imagine how unwieldy it would become if you had three or four levels of classes or if you had a ton of methods in your protocol, being forced to come up with arbitrarily unique names for each.
By way of example, I have NSOperation based framework for NSURLSession, with a session manager object (a wrapper for NSURLSession), and a bunch of individual NSOperation classes (one for download tasks, one for data tasks, etc.). In this case, while NSURLSession conforms to not only NSURLSessionDelegate, it also conforms to NSURLSessionTaskDelegate, NSURLSessionDataDelegate, etc. (because that's how NSURLSession works). But when this session manager receives one of these task-related delegate calls, it simply routes the event to the appropriate operation object. So to make this clear, I made the various operation objects conform to the appropriate protocol (e.g. download operation conforms to NSURLSessionDownloadDelegate, data operation conforms to NSURLSessionDataDelegate, etc.). The end result is that despite a dizzying collection of classes and protocols, the intent is unambiguous.
So, bottom line, if the parent is simply routing the event to the appropriate child and offering no material contribution beyond that, I'd be inclined to use same methods (and possibly same protocol). But if the parent class is offering something substantively richer/different, functionally, over what the child is performing, then a unique name would probably be appropriate.
As an aside, when coming up with your method names, I might suggest a method name that distinguishes "I received a bit of data and more may be coming" (i.e. didReceive...) vs. "I received all of the data" (i.e. didComplete...). This is an informal convention Apple uses in NSURLConnection and NSURLSession, and following it might be helpful to make your intent clear.
The best way to name a method is always to try to accurately describe (beware of excessive verbosity) what the method does. If both your methods do exactly the same it's probably a good idea to extract that functionality to a self-contained class.
Often the convention is followed in iOS to name delegate methods like the one you have shown in the following form:
-(void)dataSource:(DataSource*)dataSource didReceiveNewData:(id)data {
//Call your "child" object here
[self.myChild doAWithData:data];
}
Where dataSource is the object that calls the delegate method.
In my opinion you're running into this problem because you're not accurately describing what the method actually does by using "handle" data.
Perhaps a good source for standards is Apple's documentation.
This has been bugging me for a long time, and I have tried to look it up many times.
When I first began learning Objective-C, I remember looking into class variables. I saw many threads on stack overflow and elsewhere that basically said, "Objective-C doesn't support class variables like C does, but there are some workarounds."
Reading this made me shy away from using class variables, especially because I have read hundreds of times that global variables tarnish the elegance of OOP.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it right?
Here is my situation: I am making an app, and I set up a touch handling class to deal with all the input received from screen touches. The data is pretty useful, and I would like every single sprite to have access to it.
Since every object is a subclass of my GameObject class, I figure I just make a class variable, done like so:
header for GameObject class:
+(SSTouchHandler *)touchHandler;
+(void)setHandler:(SSTouchHandler *)handler;
implementation for GameObject class:
static SSTouchHandler *touchHandler = nil;
+(SSTouchHandler *)touchHandler
{
if (touchHandler)
return touchHandler;
else
return nil;
}
+(void)setHandler:(SSTouchHandler *)handler
{
touchHandler = handler;
}
Now, this works. This works beautifully.
I can refer to my handler with [GameObject touchHandler] from every place I need.
This is all I could ever want and more.
But should I use this method? Am I dirtying the beauty that is object oriented programming?
Is there a way I should touch up this process to make it work optimally?
Thanks for any and all input, I probably rambled a bit, I just don't want to proceed with a faulty game structure.
I saw many threads on stack overflow and elsewhere that basically
said, "Objective-C doesn't support class variables like C does, but
there are some workarounds.
"Class variables" make no sense in the context of C since C is not object oriented.
So I have a very open ended, opinionated, and conversational question:
Should I use class variables in objective C? Also, am I doing it
right?
This is more of a general OOP question than anything specific to Objective-C. The answer tends to be pretty subjective, but in general I'd say to avoid them unless you're trying to set a property of some sort that affects all instances of a class.
Here is my situation: I am making an app, and I set up a touch
handling class to deal with all the input received from screen
touches. The data is pretty useful, and I would like every single
sprite to have access to it.
It sounds to me like a better design pattern for this would be to pass the SSTouchHandler instance as a parameter to the initializer of the sprite objects that use it. e.g.:
#interface GameObject : NSObject
- (id)initWithTouchHandler:(SSTouchHandler *)handler;
#end
Now, if you really want to use the same instance of SSTouchHandler for every GameObject, you have two options:
1) The controller/factory that creates the GameObject objects should create and keep a reference to a single instance of SSTouchHandler, and then initialize any new GameObject instances with it. For example:
#interface GameObjectController : NSObject
#property (nonatomic, strong, readonly) SSTouchHandler *touchHandler;
- (GameObject *)newGameObject;
#end
#implementation
- (id)init
{
if ((self = [super init])) {
_touchHandler = [[SSTouchHandler alloc] init];
}
return self;
}
- (GameObject *)newGameObject
{
return [[GameObject alloc] initWithTouchHandler:self.touchHandler];
}
#end
2) You could make SSTouchHandler a shared singleton and call methods on the shared instance directly from the implementation of GameObject. However, shared singletons are discouraged in OOP because they hide dependencies and make it difficult to unit test code that depends on them. You shouldn't go down this route unless you deem it absolutely necessary.
implementation for GameObject class: ...
If you decide that the patterns above aren't suitable for your use case (and that sometimes does happen), yes that is essentially how you would implement class properties in Objective-C. One thing:
if (touchHandler)
return touchHandler;
else
return nil;
This is not necessary, you can just return touchHandler since it will be nil anyways if not set.
If it works, you're done. I think there are some improvements, though. First, you might like to use an instance var here: it's not more complicated, but it allows some flexibility in the future (e.g. if you want to make two views side by side). Also, using a bare pointer is not so good; the class here does not own the pointer, and it can be left dangling! Defining the touchHandler as a property (also an instance var) takes care of that problem.
I am having a lot of repeated code throughout my app classes given that some properties & method are stable across all my views.
I am looking to extend whatever class I am working with so that it automatically inherit all properties and methods that I think should be common to those classes.
I looked into the apple guide on extending classes. But I am left confused in the terms of the level of heritance that I can achieve.
I've successfully created Categories on lets say a UIViewController. But that limits me to only be able to declare Methods. I can not declare Properties on my Category and call them in side my Category or in the Extended Class. I want to be able to declare Properties and use it inside and outside my Extended-Class.
Its my first time trying to extend a class in objective-c taking full advantage of heritance but I do not know if it is possible. Am I missing something?
As an example in the code below every time I try to instantiate activityIndicatorView inside my method _activityIndicator it wouldn't recognise it. I've tried #syntetize and #dynamic but it doesn't work
NOTE: I am seeking an answer based on how to achieve heritance of methods and propeties. not highlighting what categories cant do (as I already tried and know I cant have properties there)
My attempt went as far of
#import <UIKit/UIKit.h>
#interface UIViewController (customViewController1)
#property (strong, nonatomic) UIView *activityIndicatorView;
- (void) _activityIndicator;
#end
#import "UIViewController+customViewController1.h"
#implementation UIViewController (customViewController1)
- (void) _activityIndicator {
//......
}
Your question is too broad, plus it is not clear what your problem is. Yes, you can subclass in Objective-C.
This is all very well documented in Apple's document "Object-Oriented Programming with Objective-C", section "The Object Model", subsection "Inheritance".
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
Categories only add methods, you can't add variables to a class using categories. If the class needs more properties, then it has to be subclassed.
When you use the term “extend”, you're talking about creating a subclass. This is, IIRC, how the term is used in Java and some other languages.
Apple uses the term differently (as Hermann Klecker hinted in his first comment). They literally mean extending an existing class with more functionality (in the form of methods)—that's what categories do. This is the normal English definition; extending something in the real world generally does not create a new thing.
Objective-C supports subclasses, too; it just doesn't call them “extending” the superclass. It's called creating a subclass, which inherits from the superclass.
Strctly spoken you cannot add a property to an existing class any differnt than creating a subclass.
If you cannot halp yourself and subclassing is not an option, then you can extend the class with getters and setters for the property that you want to store within the class.
Instead of really storing it as a member/instance variable/property, which you can't do, you could store the object (it cannto be a scalar, must be an object) in the global space using objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy).
This is some sort of global dictionary with two keys, the key itself and the ojbect to which you want to associat the stored object to. In your case that is the object of the type of the exended class. The setter stores it there and the getter receives it from there using objc_getAssociatedObject.
You delete an association by sending nil as value to objc_setAssociatedObject
AFAIK retained associated objects (values) are released shortly after the object that holds the associateion (object) is deallocated.
For further details see the Ojbective-C Runtime Reference https://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
Just: I do not say that this is strictly following the OO paradigm. :-)
I need to have a class, which has all methods of NSArray, which behave the same way, but 2 methods are modified.
I want to override these 2 methods in my custom class:
1) countByEnumeratingWithState:objects:count:
2) objectAtIndex:
After hours of research I don't see any reasonable way to do that, because:
I don't want to use category, because not all NSArray instances should have the modified behaviour. (Plus that throws warnings)
I don't want to re-write all initializers plus all arrayWith... methods + the primitive methods + implemented my own storage (because this functionality is already implemented in Cocoa, right? Why would I re-implement all the functionality of a class that is already there?)
If I have my custom class inherit NSObject and use NSArray as storage in an ivar, then all NSArray's methods are not available when programming in Xcode (even if I can forward them to the NSArray ivar)
I had some success overwriting the method implementations on demand by using method_setImplementation(...), but still can't figure out a way to have dynamically a class created at runtime, which then will have custom implementation of the 2 methods I mentioned.
Looking forward to your ideas! Thanks
Mantra: If something is hard (or seems like it requires more code than is necessary), it is likely that your design is counter to the design principals of the iOS / OS X frameworks. It may yield a better solution to revisit your design.
To answer the original question, if you want to subclass NSArray (or NSMutableArray), you need to implement the primitive methods, no more, no less.
The primitive methods are the methods declared in the #interface of the class itself. I.e.:
#interface NSArray : NSObject
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
#end
And for NSMutableArray:
#interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
#end
If you subclass NSMutableArray and implement the above 7 methods (the two from NSArray, too), you will have an NSMutableArray subclass that is compatible -- assuming your methods are correctly implemented -- with all APIs that consume mutable arrays.
This is because of the way class clusters are designed. The public classes are abstract; are never directly instantiated. They provide a primitive interface that contains the class's core functionality and then concrete implementations of all the other non-primtive API (save for the initializers, see below) that are implemented in terms of the primitives. Concrete, private, subclasses then override all the primitives and some of the non-primitives to provide optimal behaviors for specific configurations.
I want to have an NSArray instance for a library I'm working on and I
want to have it working transparently for the users of my library. Ie.
for them should be no difference between using a normal NSArray and
the modified class I'll be providing. Ie. it's a storage concern,
which the end users should not be concerned with and the interface
should remain the same as NSArray - therefore loosing all init methods
is not really an option at that point.
The initialization methods are not a part of the primitive interface to NSArray. You are adding a requirement above and beyond "make a class compatible with NSArray / NSMutableArray" as defined by the documentation. Nothing wrong with that, just pointing it out.
The reason why this is the case is because it is exceptionally rare to subclass the collection classes to provide the kind of business logic you describe. Collections are very generic in their behavior whereas such business logic that conditionalizes collection behavior would be done in a class that manages the overall model layer object graph.
If you really want to do this, provide an implementation of whatever init* methods you want, calling through to your wrapped generic instance as needed. There isn't anything so special about the implementations of the initializers that you are going to lose much in doing so.
No need to implement all of them, either. Implement one or two and #throw a descriptive exception on the rest.
If you do decide to forward the ones that accept var-args, you can't directly because there are no va_list accepting methods. Instead, you'll want to convert the va_list of arguments into a language array (i.e. id[] foo = malloc(... * sizeof(id));) and pass it to initWithObjects:count:.
Some other comments:
What you are doing [provide full NS*Array interface in a subclass] seems hard because it is not a common pattern and the framework designers saw no need to create a design to support it. Custom behaviors at the primitive collection levels are almost always better implemented at a higher level within the object graph. Almost always.
method_setImplementation() and dynamic class creation is academically interesting, but pretty much never a solution. Obviously, mucking with the NSArray or NSMutableArray classes (or the concrete implementation classes) is going to blow up the rest of the frameworks that rely upon standard behavior. Beyond that it, it is a pattern of dynamic OO composition that is not really intended to be used in Objective-C; it'll be a pain in the ass to maintain.
Instead of subclassing NSArray why not create a new class based on NSObject that contains an NSArray?
Then you can use all the functions of the NSArray and add your own methods that will do custom actions with it?
Or do you NEED an NSArray?
I'd like an instance variable object to adopt a protocol.
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer *content <CocosNodeOpacity>;
}
For example I'd like my Layer object to adopt the <CocosNodeOpacity> so that I can get the methods
-(GLubyte) opacity; //and
-(void) setOpacity: (GLubyte) opacity;
for free. The syntax shown above is invalid. Is it possible to achieve this without creating a new implementation file and creating a custom object? Thanks.
If these are all code you created, the best way to do this is probably to make the Layer class itself adopt the protocol, rather than the variable.
#interface Layer : NSObject <CocosNodeOpacity> { ... }
A key benefit to this approach is that the compiler will check whether you've implemented all required methods in the protocol at compile time, which is generally what you want. Adding the methods in same place as the rest of the standard class implementation is easier to understand (no hunting to find where the magical code came from) and less fragile than using categories (adding the same method via different categories can result in undefined behavior). As a general rule, I only use categories when I have to, such as adding methods to (closed-source) third-party code.
If you don't control the source of Layer, you may have to use this instead when you declare your ivar:
Layer<CocosNodeOpacity> *content;
Note that adopting a protocol allows you to statically type variables with a class type and get compile warnings if the methods aren't present. However, you don't get the methods "for free", since you still have to implement them. Still, judicious use of protocols and static typing can make your code more robust and "fail-fast" than using id as the type for everything. You are to be commended for not just taking the easy way out. :-)
For some details about protocols (including required and optional methods) see this SO answer.
A protocol in Objective-C is similar to an interface in Java. The protocol defines a set of functions and acts as a contract. It's like saying "I guarantee that whatever this object is, it has these methods."
You're pretty close on the syntax in your first code block. It would actually look something like this:
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer<CocosNodeOpacity> * content;
}
However, that doesn't save you from having to define the methods for opacity in your Layer class. Using the protocol, you've established that your class will have those functions, but you haven't actually provided them. You'll still need to write the code for them.
I think what you're looking for is an Objective-C category. A category provides a way to extend the functionality of any class by adding methods to it at runtime. They're possible because Objective-C is a completely dynamic language. If you aren't the author of the Layer class and can't easily add the opacity methods to it, a category is the way to go. In some cases, categories are extremely useful - you can add methods to built-in classes, like NSString and NSColor, without having the existing class source.
There's plenty of documentation for categories here on stack overflow. The apple docs are also very good. Here's an article to get you started:
http://macdevelopertips.com/objective-c/objective-c-categories.html