In the Master-Detail Xcode template, where do I define a function such that it is globally accessible (by all UIViewControllers and their subclasses)?
One possibility: You can define a category on an UIViewController with the method. So any UIViewController now has this method too.
Another possibility: subclass a UIViewController and write you method there. And then subclass from this custom viewcontroller.
Edit:
Also, my MasterViewController is a subclass of the UITableViewController while the DetailViewController is a subclass of UIViewController. If I subclass them both to a custom UIViewController, the MasterViewController will lose its UITableViewController inheritance
You could subclass a UITableViewController and do the same thing as with the UIViewController and subclass from this.
The basic idea is to have a UITableViewController and a UIViewController as template.
You can create methods in the appDelegate class that you can access through all your app. For example, in your AppDelegate.h you have declared this method as follow:
-(void)myMethod;
In your AppDelegate.m, you define it as:
-(void)myMethod
{
NSLog(#"myMethod is getting called");
}
From any other classes (Master or Detail, etc.), you access myMethod by:
#import "AppDelegate.h"
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate myMethod];
make the class and the methods static. use the plus instead of minus e.g. +(void)methodName:param(ParamType *); .
Note, you can't instantiate a object of this class. It is like procedural programming. I usually use if I need the same but changing value in different objects and views. I don't a better way it works for me, though.
If you have some code that doesn't care what class of object calls it, it could probably be encapsulated into a function or subroutine instead of a method.
A method is a special type of function or subroutine that knows about an object and its class. A function or subroutine is like a global method that doesn't.
Added:
Objective C is a superset of the C programming language. So C functions and subroutines are the same in both languages. You can write one in a (or any) .c or .m file, and declare it in a .h file to be included wherever you want it used. Pass it parameters as needed and get a return value from functions, just like methods (except for being unrelated to any inherent class of object).
Added #2: But since you want your method to know about some NSStreams, then it should probably be a method of some Model class (MVC paradigm) containing those streams, and not truly global. Pass this Model object to any view controllers or other classes that need to access it.
Related
I've seen several Obj-C tutorials. The delegate classes all inherit from NSObject. For example, the applicationDidFinishLaunching delegate method, in some tutorials, it inherited from NSObject but NSApplication to implement it. The reason I don't think it should inherited from NSObject is that I didn't find any delegate protocol declaration in it, but I found that delegate protocol declaration in NSApplication. My Objective-C toy environment is GnuSep.
Here is some code:
#interface browserController : NSObject //here. inheriting from NSObject,but NSObject don'have any protocols declaration about applicationDidFinishLaunching.
{
NSBrowser *browser;
}
#end
#implementation browserController
- (void)menuAction:menuItem
{
..............................
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSWindow *win;
ActiveBrowserDelegate * abd;
WindowDelegate *wd;
NSRect wf = {{100, 100}, {600, 500}};
NSRect bf = {{10, 10}, {580, 350}};
.............................
}
It is called informal protocol (though GNUstep declared it anyway as GSAppDelegateProtocol for documentation purpose) NSApplication will simply check it at runtime if your delegate object will respond to the message, (using -respondsToSelector:) A delegate can be a view, a string, a proxy, anything as long as you make it responds to the selector. You don't need to make your delegate implement every method in such protocol since all verifications would be done at runtime. To make it looks cleaner you could just redeclare -applicationDidFinishLaunching: in #interface though you don't really need to, just make one in the #implementaiton is enough.
A delegate may inherit from anything appropriate. It is usually supposed to implement a certain protocol.
A protocol is a way of implementing a formal communication interface between two classes.
However, it is most unlikly that a delegate will inherit from its communication partner class.
With other words: Protocols are often used to overcome the unavailability of multiple inheritance. (Pretty much like interfaces in Java)
Example: A UIViewController subclass' instance controls a view that contains a UITableView. Rather than subclassing the UITableView for the implementation of its look or data, there are two delegates assigned to the table view object. One delegate serves as provider for custom layout (provides items such as the header view) and another (?) delegate provides the data that is being displayed.
Now, this delegate could be any object, inheriting from NSObject and implementing the two protocols. This object cold then be instanciated by the view controller and assigned to the table.
However, it is common practice that the view controller itself serves as delgate for the table(s) that it controls. That is a good pattern but strictly spoken not required. It could be any object.
Now the custom view contoller inherits from UITableViewController (which already implements the protocols and inherits from ViewController) and serves as delgate for the table view. The table view itself could be any subclass of UITableView. (Although this is a bad example here because subclassing UITableView is normally not advisable)
If the delegate does not need to inherit from any class and just implements the protocol, then it shold at least inherit from the cocoa base class NSObject. That ensures that it inherits all the usual capabilites and behaviour of any object. (init method, copy method, description method etc.) That may be required to work properly with other classes of the framework such as beeing used as an object within an NSArray, NSLog etc.
I have a two different ways of representing data in my app: via UITableView or UIScrollView.
So I have 2 main classes: AppTableView: UITableView and AppScrollView: UIScrollView.
And I want to implement the same additions to both views. So I wrote two classes: SomeAdditionsTableView: UITableView and SomeAdditionsScrollView: UIScrollView. The code of this classes is the same.
Main classes now looks like
AppTableView: SomeAdditionsTableView and AppScrollView: SomeAdditionsScrollView.
How to avoid this code duplicate? Thanks in advance.
Yeah this is a problem with the lack of multiple inheritance in Objective-c. I had the same problem when needing certain methods on a subclass of UIView and UIScrollView separately here: Subclassing UIView vs UIScrollView. There are 3 possible solutions I know of:
If you don't need to store any kind of instance variable, simply declare a category on UIScrollView and make sure to import that category into the two subclasses. This is the easiest solution, but least likely to work since you probably need to store state information if you're subclassing anyway.
Only create a subclass of UITableView and simply don't use it as a UITableView when you don't want a UITableView. You can technically just use a UITableView as a UIScrollView without invoking any of the tableView's methods. Of course, you're going to end up carrying around the 'weight' of a tableView (all of it's instance variables) but there no reason you have to use a UITableView as a UITableView and not just a UIScrollView.
Delegate as much of your code to a separate object to minimize code duplication. In each separate subclass carry an instance variable that is the method delegate and forward method calls to that delegate. Now here's where it gets fun. You can use protocols to declare the delegate methods in your subclass and override a special NSObject method: - (id) forwardingTargetForSelector:(SEL)aSelector to make sure those method calls get sent to the delegate. You use a category on the subclass that conforms to the protocol declared in the delegate class. This will expose all the methods of the delegate class in the subclass without requiring you to actually implement those methods in the subclass. When the runtime can't find the declared method in the subclass, it will call - (id) forwardingTargetForSelector:(SEL)aSelector, which you can use to return your delegate/forwarded class. This will prevent you from needing forward each individual method. Depending on what those method calls do, this may take a little more 'wiring', but it'll save you a lot of code writing in the end. It essentially 'mimics' multiple inheritance in objective-c using protocols. See my question/answer here for more details: https://stackoverflow.com/a/9419587/1147934.
Of the three, the last option tends to work the best for me. It takes a little work to get your head around but will significantly reduce code duplication. I also use it when I want to subclass without subclassing. The biggest requirement, though, is any class that you want to do this with will have to move it's method declarations out of it's interface into a separate protocol. But it's really not a big deal and the benefits of getting 'multiple inheritance like behavior' is great.
Also, there are times you may need the forwarded class to access instance variables in the forwarding class (the subclass). You can achieve this by using a delegate pattern whereby the forwarded class maintains a weak reference to the forwarding class in order to access those instance variables. For example, in your case, if you're trying to delegate methods that operate on a UIScrollView, those methods may need to be able to access that view. If those methods are stuck in a delegate class, they won't have direct access to the view's variables unless you give it to them. As usual with any delegate pattern, be very careful you don't create a retain cycle.
If your additions don't need any state of their own, you can make them a category on UIScrollView. Then, since a UITableView is a type of UIScrollView, you can use the category methods on one of those too.
If they do need to define new variables, then I would make it an independent class and have a MyTableView : UITableView subclass with a SomeAdditions property and, similarly, MyScrollView : UIScrollView.
You can achieve a lot by using protocols and "has_a"-relationships, instead of inheritance's "is_a"-relationships.
One very common pattern is delegate, but protocols are also useful for forwarding methods calls to encapsulated or wrapped objects.
in the following example to classes, that are not related to each other, share a common object, but it is also possible, that objects of the same kind use objects of different classes, that all implement a common protocol, so equal objects could do very different stuff.
#interface ClassA : NSObject
#property (strong) id<BrainProtocol> *brain
#end
##implementation ClassA
#synthezise brain;
-(void)theMethod
{
[brain theMethod];
}
#end
#interface ClassB : NSObject
#property (strong) id<BrainProtocol> *brain
#end
##implementation ClassB
#synthezise brain;
-(void)theMethod
{
[brain theMethod];
}
#end
ClassA *a = [[ClassA alloc] init];
ClassB *b = [[ClassB alloc] init];
//A object, that implements the BrainProtocol
Brain *brain = [[brain alloc] init];
[a setBrain:brain];
[b setBrain:brain];
When you have an UIViewController and UITableViewController classes and you wanted to let these two do some common stuff in their - (void)viewDidLoad how could you achieve this in Objective-C without actually duplicating your code?
I tried to create MyUIViewController inheriting UIViewController and implement viewDidLoad in there. This perfectly works with UIViewController classes obviously, but won't work in UITableViewController, since I can't simply replace #interface MyTableViewController : UITableViewController with #interface MyTableViewController : MyUIViewController.
I believe this topic is about "multiple inheritance" in Objective-C language, but other than figuring out what's different in Objective-C, I'd really like to know how to do guys do such thing?
This thread has some good information. One of your main options is to make a class with that shared functionality and hold it as an instance variable, then forward messages to it in forwardInvocation.
when i create a new view based application a few methods in the implementation file (.h)
i do not understand their purpose and when i look into the developer center its kind of hard to understand because of how its explained.
what purpose do these methods have and what are they used for in plain english.
- (void)loadView
- (void)viewDidLoad
- (void)viewDidUnload
what im guessing the viewdidload is , is that when the view is loaded and anything between the braskets are executed first, but when there are other custom methods created (if that is the purpose of viewdidload) how does it know which method to execute? is the code executed from top to bottom? being that whatever method is listed first is executed?
also i have noticed the word super inside brackets along with other keywords. what is the purpose of super?
thank you!
Well, "super" means Super Class, or the parent class that your current class extends.
#interface MyViewController : UIViewController{}
In the code above, that you can find in some .h files, MyViewController extends UIViewController. So, all the time that you call "super" inside MyViewController, you are calling the UIViewController.
So, when you see the following structure, inside MyViewController...
- (void)viewDidLoad {
[super viewDidLoad];
.
.
.
.
.
}
... it means that when the method "viewDidLoad" is called, it will first call the method from it's super class, to after run it's own code.
if you let the whole viewDidLoad method commented, it means that the parent method will be called automatically, because you are not overwriting it like on the previous example.
To understand what all the methods (loadView, viewDidLoad, viewDidUnload), take a look at the UIViewController Class reference on Apple Developer Connection.
Cheers,
VFN
Your class is a derivative of the system class UIViewController (is a subclass, in Objective C lingo). [super someMethod] means - call this method for the base class (superclass in ObjC lingo).
If you're familiar with C#, super in ObjC means same as base in C#. And the same as super in Java. :)
The system-provided UIViewController class has loading functionality in its loadView method. This method is called by the system, and it does a lot of work. The viewDidLoad method, on the other hand, is defined in the base class but does not do much. Its purpose is that you can override it and provide your own functionality there. Same for viewDidUnload.
In Objective-C, how do you rewire a class's instance method to call a method in another class?
Say a UIView class A contains another UIView class called childA. I want it so that when childA's drawRect is called, a method in class A is invoked without having to subclass childA and do the desired call in its drawRect there. How can this be achieved?
Also, how do I supply a method to childA's draw class dynamically? I know this is probably not a good practice but it would be useful for testing purposes.
To answer your first question about rewiring methods:
You don't want to be doing this on general principle, since it kinda defeats the whole purpose of object-oriented design, but for testing purposes, it can be useful. As long as you're on Leopard, it's not especially difficult, either.
Take a look at the Objective-C 2.0 Runtime Reference, which contains the keys to the kingdom, as it were. Look at the functions class_getInstanceMethod, method_getImplementation, method_getTypeEncoding, and class_addMethod which, in combination, let you change the methods of a class at runtime.
If you're just swizzling one selector for another, method_exchangeImplementations is a useful shortcut.
To answer your second question about supplying a method dynamically, that's as simple as passing a SEL to a method and then calling -performSelector:withObject::
#interface MyView : NSView {
SEL drawingSelector;
id drawingDelegate;
}
#property SEL drawingSelector;
#property id drawingDelegate;
#end
#implementation MyView
- (void)drawRect:(NSRect)rect {
[self.drawingDelegate performSelector:drawingSelector withObject:[NSValue valueWithRect:rect]];
}
#end
For the first issue you raise, it seems like you would set up UIView A as a delegate object of childA and the other UIViews - then they could use delegate methods to call the extra drawing features you wanted in A.
Either that or have each child ask for the superview and if it is of type "A" call the method you are interested in.