Hello and thanks for any help in advance. I tried searching but it seems that what I am trying to do is no common. If there is another post talking about my question please link.
To get started, I have two classes. To keep names simple, one is called Controller and the other is my AppDelegate. The controller is a static library. The AppDelegate creates an instance of the controller using the following.
*Note: I have already declared _controller in .h file.
_controller = [[Controller alloc] initWithAppDelegate:self];
What I would like to do, is call methods in the AppDelegate class from the controller. Relevant code in the controller.h class is as follows.
#interface
{
id _appDelegate;
}
-(id) initWithAppDelegate:(id)appDelegate;
and in controller.m
-(void)someMethodName
{
[_appDelegate method];
}
The issue I am having is that method is not available to be called. I can call several other methods but not the custom methods I have created within AppDelegate. I have tried replacing ID with the AppDelegate but I can't seem to be able to import AppDelegate, I somewhat understand why I can't import it.
The reason I am creating my project this way is that I would like to reuse the controller code in applications that have a UI designed for different devices. If any of this is unclear or you need more information, feel free to ask.
Thanks.
Declare a protocol like this in your static library:
#protocol AppDelegateRequiredMethods
#required
... methods here ...
#end
Then, import the header that declares that protocol into your various AppDelegate implementations and declare your app delegate as implementing said protocol:
#interface MyAppDelegate:NSObject <AppDelegateRequiredMethods>
...
#end
The Controller has no knowledge of the app delegate or its methods. You must declare the interface using a protocol.
#protocol AppDelegateMethods
- (void)method;
#end
//Then replace your current id with
id <AppDelegateMethods>
I am creating an iPhone application, a game, and I am trying to understand and embrace the MVC architecture. I am planning to create a model, in this case called HighScoresModel that is responsible for holding all the information about high scores in my game.
Where should this model be created? In the AppDelegate? In the first view controller?
How should other view controllers access the model in order to pass messages like addScore:withDifficulty:?
I think the best option to to have a class method on HighScoresModel that will access a single, shared instance of the model from any object that needs it.
This is superior to the other options because no controller is responsible for instantiating the model, and the controllers are not unnecessarily coupled to the app delegate either.
As an example:
#interface HighScoresModel : NSObject
+ (HighScoresModel *)sharedHighScoresModel;
...
#end
#implementation HighScoresModel
static HighScoresModel *SharedHighScoresModel;
+ (HighScoresModel *)sharedHighScoresModel
{
if (!SharedHighScoresModel)
{
SharedHighScoresModel = [[HighScoresModel alloc] init];
}
return SharedHighScoresModel;
}
...
#end
Hope this helps!
Create a Singleton and create the HighScoresModel in there. The singleton will be accessible from all ViewController.
As far as other view controller passing messages you'll be able to do something similar from anywhere within the controller.
[MySingleTon myHighScoresModel] addScore:myScore withDifficulty:myDifficulty];
See the following link for more reference to singleton http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/
we are a group working on an iPhone app. and its our first time. I just would like to know the easy way to implement a public class so that my partner can give me a variable that contains a value i need to use in my code. It doesn't have to be a class any other easy solution would work.
Just to make it more clear my friend has a value in his code that i need to use to display it on the screen "using my code". What i know is that everything has to communicate through a controller class which in this case the thing i need to implement my friend must be able to call it, give it the value then i take this value and display it. THANK YOU IN ADVANCE!
I. Just make an property in .h
#property (nonatomic, retain) NSString *userName;
and in .m file
#synthesize userName;
Docs here
II. He can make and delegate protocol in his class, the you need to set your object to be the delegate of his class instance and implement the delegate method. When he has the vale will call the delegate method and you will recive it in your method.
Docs here
I am trying to call a method in my root view controller from a child view controller such that when I change my options they will automatically update the root view, which will in turn update several other view controllers. For the second part I have used notifications, but for this first I am trying to use a delegate because it (so I have been lead to believe) is a good programming practice. I am having trouble making it work and know that I can set up another notification easily to do the job. Should I continue trying to implement the delegate or just use a notification?
Delegating is a good programming practice for many situations but that doesn't mean you have to use it if you're not comfortable with it. Both delegating and notifications help decouple the view controllers from each other, which is a good thing. Notifications might be a little easier to code and offer the advantage that multiple objects can observe one notification. With delegates, such a thing cannot be done without modifying the delegating object (and is unusual).
Some advantages of delegating:
The connection between delegating object and delegate is made clearer, especially if implementing the delegate is mandatory.
If more than one type of message has to be passed from delegatee to delegate, delegating can make this clearer by specifying one delegate method per message. For notifications, you can use multiple notification names but all notifications end up in the same method on the side of the observer (possibly requiring a nasty switch statement).
Only you can decide what pattern is more appropriate for you. In any case, you should consider not having your view controller send the notification or the delegate message. In many cases, the view controller should change the model and then the model should inform its observers or its delegate that it has been changed.
Implementing a delegate pattern is simple:
In your ChildViewController.h, declare the delegate protocol that the delegate must implement later:
#protocol ChildViewControllerDelegate <NSObject>
#optional
- (void)viewControllerDidChange:(ChildViewController *)controller;
#end
At the top of the file, create an instance variable to hold the pointer to the delegate in your ChildViewController:
#protocol ChildViewControllerDelegate;
#interface ChildViewController : UIViewController {
id <ChildViewControllerDelegate> delegate;
...
}
#property (assign) id <ChildViewControllerDelegate> delegate;
...
#end
In RootViewController.h, make your class conform to the delegate protocol:
#interface RootViewController : UIViewController <ChildViewControllerDelegate> {
...
In the RootViewController implementation, implement the delegate method. Also, when you create the ChildViewController instance, you have to assign the delegate.
#implement RootViewController
...
// in some method:
ChildViewController *controller = [[ChildViewController alloc] initWithNibName:...
controller.delegate = self;
...
- (void)viewControllerDidChange:(ChildViewController *)controller {
NSLog(#"Delegate method was called.");
}
...
In the ChildViewController implementation, call the delegate method at the appropriate time:
#implementation ChildViewController
...
// in some method:
if ([self.delegate respondsToSelector:#selector(viewControllerDidChange:)]) {
[self.delegate viewControllerDidChange:self];
}
...
That's it. (Note: I have written this from memory so there are probably some typos/bugs in it.)
I would like to add:
objects receiving notifications can
react only after the event has
occurred. This is a significant
difference from delegation. The
delegate is given a chance to reject
or modify the operation proposed by
the delegating object. Observing
objects, on the other hand, cannot
directly affect an impending
operation.
Typically, if you need to update the UI based on a change to data in a model, you would have the view controllers observe the relevant model data and update their views when notified of changes.
I see delegation as a bit more formal and like the distinction that Peter Hosey shared recently:
The difference is that delegation is
for to-one (and bidirectional)
communication, whereas notifications
are for to-many, unidirectional
communication.
Also, I have found that (completely) updating the view in viewWillAppear: works fine (but this is not the best solution where performance is a concern).
Notifications can make the runtime behavior of your program significantly more complex. Think of it like a goto with multiple destinations. The order of those destinations is not defined. If you ever crash there is little stack trace information.
There are cases when it makes sense to use notifications--the typical one being to communicate a model change or a global state change to your views. Example, the network is down, the application will resign, etc!
It is worthwhile to learn the delegate pattern in iOS. Delegates give you complete stack traces when you debug. They result in significantly simpler runtime behavior while still achieving the goal of decoupling your objects.
Delegates are a little hard to get used to, but I think it's the best practice and, like Apple, they just work.
I always use the formal protocol declaration. It's a bit more logical in my mind, and it's very clear in the code. I suggest using a UIView to change your options instead of a controller. I always use one main controller and have a lot of subclassed UIViews that the one controller can control. (However, you can modify the following code for a controller, if you really need a controller instead of a normal view.) In the header file of the child view, make it look like this:
// ChildView.h
#import <UIKit/UIKit.h>
#protocol ChildViewDelegate; // tells the compiler that there will be a protocol definition later
#interface ChildViewController : UIView {
id <ChildViewDelegate> delegate;
// more stuff
}
// properties and class/instance methods
#end
#protocol ChildViewDelegate // this is the formal definition
- (void)childView:(ChildView *)c willDismissWithButtonIndex:(NSInteger)i; // change the part after (ChildView *)c to reflect the chosen options
#end
The method between #protocol and the second #end can be called somewhere in the implementation of the ChildView, and then your root view controller can be the delegate that receives the 'notification.'
The .m file should be like this:
// ChildView.m
#import "ChildView.h"
#implementation ChildView
- (id)initWithDelegate:(id<ChildViewDelegate>)del { // make this whatever you want
if (self = [super initWithFrame:CGRect(0, 0, 50, 50)]) { // if frame is a parameter for the init method, you can make that here, your choice
delegate = del; // this defines what class listens to the 'notification'
}
return self;
}
// other methods
// example: a method that will remove the subview
- (void)dismiss {
// tell the delegate (listener) that you're about to dismiss this view
[delegate childView:self willDismissWithButtonIndex:3];
[self removeFromSuperView];
}
#end
Then the root view controller's .h file would include the following code:
// RootViewController.h
#import "ChildView.h"
#interface RootViewController : UIViewController <ChildViewDelegate> {
// stuff
}
// stuff
#end
And the implementation file will implement the method defined in the protocol in ChildView.h, because it will run when the ChildView calls for it to be run. In that method, put the stuff that happens when you'd get the notification.
In this case, you don't need to use either delegation or notification because you don't really need to communicate directly between your views. As gerry3 said, you need to change the data model itself and then let all other views respond to that change.
Your data model should be an independent object that all your view controllers have access to . (The lazy way is to park it as an attribute of the app delegate.) When the user makes a change in View A, View A's controller writes that change to the data model. Then whenever Views B through Z open up, their controllers read the data model and configure the views appropriately.
This way, the neither the views, nor their controllers need to be aware of each other and all changes occur in one central object so they are easily tracked.
Is it really necessary for your root view controller to know about the changes, or just the subviews?
If the root controller does not have to know, having the settings send out the notifications the other views are looking for seems like a better answer to me, as it simplifies code. There is no need to introduce more complexity than you have to.
i created a TTViewController that should show some Informations from a external (web) source.
i already worked with some TTableViewControllers where i used the TTModel System (i created a TTURLRequestModel and a TTListDataSource for my TTTableViewControllers)
whats the way to do this with a TTViewController?
is there also something like a DataSource and Request Model or do i have to assign my ViewController with the TTURLRequestDelegate and run a simple URL Request?
im asking because i dont know whats the "best" and "newest" way to fill my viewcontroller with data from the web. i know how to do this for tableviews but not for views.
thanks in advance
edit: some code
my singlePostViewController:
#interface singlePostViewController : TTModelViewController
singlePostModel *_singlepostmodel;
#end
- (void) createModel {
_singlepostmodel = [[singlePostModel alloc] init];
}
and my singlePostModel
#interface singlePostModel : TTURLRequestModel {
}
#end
but what to do now? where to load my stuff and setting it up?
Check out the TTModelViewController class. You'll want to subclass that. You create the TTURLRequestModel in the createModel: method and add "self" to the list of model's delegates. There are a bunch of interesting methods available that should be sufficient for what you're trying to do.
In particular, this PDF shows a good relationship between the model, datasource, and controller classes.
Check this twitter example
https://github.com/facebook/three20/tree/master/samples/TTTwitter
Its straightforward example.
You need to override "-(void) load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more" method in your subclass of TTURLRequestModel to fetch remote data.