Hey is it possible for muliple objects to share a single function but extend different classes? Cause I would rather not have to rewrite my code over and over. Here is an example of what I would do without said method:
I want to have a single, method without having to call [MovieClip loadLandscape]; in the Timeline Implementation
RotatingProtocol.h
#protocol RotatingProtocol
#required
- (void)loadPortrait;
- (void)loadLandscape;
#end
MovieClip.h
#import "RotatingProtocol.h"
#interface MovieClip : UIButton <RotatingProtocol> {
}
#end
MovieClip.m
#import "MovieClip.h"
#implementation MovieClip
- (void)loadPortrait {
// UIButton -> setframe to fit portrait screen
}
- (void)loadLandscape {
// Popup and alert!
}
#end
Timeline.h
#import "RotatingProtocol.h"
#interface Timeline : UIScrollView <RotatingProtocol> {
}
#end
Timeline.m
#import "Timeline.h"
#implementation Timeline
- (void)loadPortrait {
// Do funny animation
}
- (void)loadLandscape {
// Do exactly the same thing as [MovieClip loadLandscape]
}
#end
One possible solution, that I hesitate to recommend, is to provide a category on UIView (the highest level superclass both classes share) that adds the loadLandscape method implementation, then you could leave it out of the objects and just declare the class supports that protocol (and also import the category).
That's kind of extreme since every UIView instance gets the method that could be called, which might confuse something that checks for respondsToSelector instead of conformsToProtocol.
The technique I'd use is to put that implementation into something like a RotatingProtocolImplementation class as a class level method. Something has to know to call the loadLandscape method of your protocol, and that something could just as easily detect the class declared support for the protocol and call the shared class level method instead of a method on the class instance itself - so the protocol could become more of a marker protocol, without as many (or any) methods a class would have to define to support it.
Related
A very basic question on how to interact between classes here: how can I trigger an action called by clicking on a button linked to one class (the graphic user interface in my case - which does not contain any drawing code) inside another class (my drawing class - which is defined programmatically)?
Thanks!
Edited: I have tried to implement the solutions suggested below but I didn't manage to trigger the action from the other class. I have two classes: the main view controller and a class with the drawing code. Any advice would be highly appreciated. Thanks!
//MainViewController.m
//This class has a xib and contains the graphic user interface
- (void)ImageHasChanged
{
//do something on the GUI
}
//DrawView.m
//This class has no associated xib and contains the drawing code
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//I want to call ImageHasChanged from MainViewController.m here
//How can I do this?
}
Inter-class functionality is done simply by importing one class into the other, and calling an accessible method/instance variable on the import.
For the button IBAction example in your question:
ClassA.m (This will be imported via its header):
#import "ClassA.h"
#implementation ClassA
// This is a class-level function (indicated by the '+'). It can't contain
// any instance variables of ClassA though!
+(void)publicDrawingFunction:(NSString *)aVariable {
// Your method here...
}
// This is a instance-level function (indicated by the '-'). It can contain
// instance variables of ClassA, but it requires you to create an instance
// of ClassA in ClassB before you can use the function!
-(NSString *)privateDrawingFunction:(NSString *)aVariable {
// Your method here...
}
#end
ClassB.m (This is your UI class that will call the other method):
#import "ClassA.h" // <---- THE IMPORTANT HEADER IMPORT!
#implementation ClassB
// The IBAction for handling a button click
-(IBAction)clickDrawButton:(id)sender {
// Calling the class method is simple:
[ClassA publicDrawingFunction:#"string to pass to function"];
// Calling the instance method requires a class instance to be created first:
ClassA *instanceOfClassA = [[ClassA alloc]init];
NSString *result = [instanceOfClassA privateDrawingFunction:#"stringToPassAlong"];
// If you no longer require the ClassA instance in this scope, release it (if not using ARC)!
[instanceOfClassA release];
}
#end
Side note: If you're going to require ClassA a lot in ClassB, consider creating a class-wide instance of it in ClassB to re-use wherever it's required. Just don't forget to release it in dealloc (or maybe set it to nil in ARC) when you're finished with it!
Finally, please consider reading through the Apple Docs on Objective-C classes (and indeed all other sections of the documentation relevant to what you're trying to achieve). It is a bit time-consuming, but very well invested in the long run into building your confidence as an Objective-C programmer!
//As you said an instance of MainViewController has to be created first
MainViewController *instanceOfMainViewController = [[MainViewController alloc]init];
[instanceOfMainViewController ImageHasChanged];
//Thanks for your help Andeh!
Actually you can use #protocol(Delegate) to interact message between two classes this is standard way Or refer this document
http://developer.apple.com/library/ios/#documentation/General/Conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html to learn more
I have a few custom UIViewControllers in my app which need to know the string returned of an NSDate. I could copy and paste the same code between these classes, but that's obviously terrible practise. It's also probably not good to put it in 1 class as a method, then have another class add this class to take advantage of it's method. It seems like a messy thing to do. So what would you recommend i do?
To clarify - I need a method which is given an NSDate and returns a string, for use in several other classes.
Sounds like you either need a function, rather than a method:
//Helpers.h
#import <Foundation/Foundation.h>
NSString * makeAStringFromThisDateSomehow(NSDate * d);
//Helpers.m
#import "Helpers.h"
NSString * makeAStringFromThisDateSomehow(NSDate * d)
{
// Body
// of
// your
// function
}
Or to make a category on NSDate to do what you need:
//NSDate+AndrewsCategory.h
#import <Foundation/Foundation.h>
#interface NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow;
#end
//NSDate+AndrewsCategory.m
#import "NSDate+AndrewsCategory.h"
#implementation NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow {
// Body
// of
// your
// method
}
#end
Note the stupid prefix on the method name. That's important to keep your method names from colliding with other method names on framework classes. Usually you would use initials: your company's, yours, or the project's.
In either case, just import the relevant header where you need to use the function or method, and you should be hunky-dory.
I'd consider writing a category on NSDate. Categories let you extend the functionality of existing classes with additional methods without having to mess with the existing implementation of the class. So you can add yourMethod to NSDate, and in the future just be able to call [yourDate yourMethod].
To do this in Xcode, just hit ⌘N to create a new file, and choose Objective-C category, then give it some name and make it a category on NSDate.
Then set up your header:
#interface NSDate (YourCategory)
- (NSString *) yourMethod;
#end
And your implementation:
#implementation NSDate (YourCategory)
- (NSString *) yourMethod {
return [NSString stringWithFormat:#"yourMethod on this date: ", [self description]]; // for example
}
#end
Then just include "NSDate+YourCategory.h" in any file where you want to use yourMethod.
i'd recommend adding the method to a catagory and then adding the header to your projects pch file
#ifdef __OBJC__
#import "yourHeader.h"
#endif
if you google for NSDate+Helper that should give you an idea of the implementation.
Nik
It's probably good to put it in 1 class as a method, then have another class add this class to take advantage of it's method.
simple 1 or 2 methods NSObject subclasses won't make slightest differences in execution
Ok, this is going to be a really embarrassing question, but I looked like mad in my beginner's books (especially those usually helpful indices) and behold, I did not find a down-to-earth explanation of what 'super' does in my applications.
I had a look at this here, but I'm afraid that's well beyond me. Can anyone offer a very simply explanation of what 'super' does in my apps and why I should become friends with it? E.g.:
- (void)viewDidLoad {
[super viewDidLoad];}
Thanks!!
super calls the superclass's implementation of the method. So if your class inherits UIViewController, then [super viewDidLoad]; will call the UITableViewController class's viewDidLoad method. You should usually do this because the super class may do important things that need to happen. In the case of viewDidLoad, I'm not sure it actually does anything currently, but it always could in a future version of the framework.
at the low level, self contains a pointer to the set methods it responds to. this is a basic mechanism for the implementation of dynamic dispatch. each class is given a unique set. if you're familiar with c++, this is similar in concept to a virtual table. you can think of an objc method as being like a C function with 2 hidden arguments (self,_cmd).
super is a dynamically created representation of self, with a pointer to the next-in-line methods implemented by the instance's superclasses. this representation is based on self, and just directs to another set of implemented methods.
#interface MONTypeA : NSObject
- (void)monMethod;
#end
#interface MONTypeB : MONTypeA
- (void)monMethod;
#end
#implementation MONTypeA
- (void)monMethod {
printf("i am MonTypeA\n");
}
#end
#implementation MONTypeB
- (void)monMethod {
[super monMethod]; /* << will call -[MONTypeA monMethod], which will print "i am MonTypeA\n" */
printf("i am MonTypeB\n");
}
#end
if you create an instance of MONTypeA, then it will respond to monMethod:
MONTypeA * a = [MONTypeA new];
[a monMethod];
[a release], a = 0;
// outputs: "i am MonTypeA\n"
MONTypeB * b = [MONTypeB new];
[b monMethod];
[b release], b = 0;
// outputs: "i am MonTypeA\n""i am MonTypeB\n" because -[MONTypeB monMethod] calls through super
therefore, calling super performs the implementation of the method of the superclass in this specific case.
it is important to remember: the set of methods super refers to is always those of the previous implementation of the method in the hierarchy, it is not the same set as the set of instance methods which an instance of the superclass would be given (unless your class were to override every method).
I am trying to get my head round Objective-C Protocols. I have looked at the Apple docs and also relevant chapters in a couple of books that I own, but nearly always protocols seem to be defined in terms of using them as in interface to delegate objects. I understand the concept of creating the protocol definition:
#protocol PetProtocol <NSObject>
- (void)printCat;
- (void)printDog;
#end
I also understand the bit where I conform a class to a protocol:
#interface CustomController : UIViewController <PetProtocol> {
followed by implementing the required methods.
#implementation CustomController
- (void)printCat {
NSLog(#"CAT");
}
- (void)printDog {
NSLog(#"DOG");
}
I guess my question is how to use this protocol, it seems a bit strange to call, printCat and printDog from CustomController where the methods are implemented, can anyone point me at or give me a really simple example of using this protocol or similar?
much appreciated
gary.
A protocol is just a list of messages that an object can respond to. If an object conforms to a protocol, it's saying, "I respond to these messages." This way, you can return an object that the caller can use without having to promise that the object will be of any particular type. For example, with that protocol, you could do this:
id<PetProtocol> getSomeObjectThatConformsToThePetProtocol() {
return [[[CustomController alloc] init] autorelease];
}
int main() {
id<PetProtocol> foo = getSomeObjectThatConformsToThePetProtocol();
[foo printCat];
[foo printDog];
return 0;
}
See, main() doesn't need to know that the object is a CustomController — it just knows what messages you can send the object. Any class that conforms to PetProtocol would do. That's what protocols are for.
Protocol (or delegation) is used to call a method in a different class. For example, the class that contains the protocol (lets call it PetClass) would call [self.delegate printCat] and the delegated class (CustomController) would carry that method out for the PetClass object.
This might help as well:
delegation: the assignment of
authority and responsibility to
another person (normally from a
manager to a subordinate) to carry out
specific activities
This assumes of course you have defined self.delegate in your header and synthesized it in your implementation:
Header iVars:
id <PetProtocol> delegate;
Implementation:
#implementation PetClass
#synthesize delegate;
I know this is quite possibly a lame question, but I've pulled three consecutive all-nighters and I'm very blurry. And I'm new to Objective C and Cocoa Touch.
I've created a class that provides a delegate method. I'll use simplified example code since the specifics aren't important. The header file looks like this:
#import <Foundation/Foundation.h>
#protocol UsernameCheckerDelegate <NSObject>
#required
- (void)didTheRequestedThing:(BOOL)wasSuccessful;
#end
#interface TheDelegateClass : NSObject {
id <TheDelegateClassDelegate> tdcDelegate;
}
#property (assign) id <TheDelegateClassDelegate> tdcDelegate;
- (void)methodThatDoesSomething:(int)theValue;
#end
And the source file looks like this:
#import "TheDelegateClass.h"
#implementation TheDelegateClass
#synthesize tdcDelegate;
- (void)methodThatDoesSomething:(int)theValue {
if (theValue > 10) {
[[self tdcDelegate] didTheRequestedThing:NO];
// POINT A
}
// POINT B
int newValue = theValue * 10;
NSString *subject = [NSString stringWithFormat:#"Hey Bob, %i", newValue];
// Some more stuff here, send an email or something, whatever
[[self tdcDelegate] didTheRequestedThing:YES];
// POINT C
}
#end
Here's my question: if theValue is in fact greater than 10 and the line above POINT A runs, does program flow control pass out of this method (and back to the didTheRequestedThing delegate method in the object that called this) or does flow continue on through POINT B to POINT C?
I'm hoping for the former because I can simplify the heck out of my code, currently an unpleasant mess of deeply nested ifs and elses.
When the -didTheRequestedThing: method returns, control flow returns back to your POINT A and continues on to POINT B and POINT C. Delegate method calls are exactly like any other method call. If you want to avoid executing the rest of the method after the delegate call, just stick a call to return where your // POINT A comment is.