I'm writing an iPhone program that has a login view controller that allows the user to login. I have a method I use within that controller that checks the authentication of the username and password. I'm using the keychain to store the username and password, but I'm wondering how I go about communicating outside of the class that the username and password is authentic without duplicating code.
This is probably very simple, but it's getting late and my brain is completely fried...
Good question, and Simon's approach is certainly reasonable.
Another idea would be to create a new class, modeled as a Singleton, called Security and place your authentication method there. Then any object who wishes to validate the user could simply call into Security.
You can read more on the Singleton pattern here: http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/cocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW6
Hope this helps.
Andrew
One way would be to move the code for handling storing and checking username/password into your AppDelegate class, then in your view controller classes you can do something like:
MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
// Store password
[appDelegate storePassword:foo forUsername:bar];
// Then later, or in another class...
if ([appDelegate userIsAuthenticated]) {
// Stuff for authenticated users goes here
}
(You'll need to add #import "MyAppDelegate.h" to the top of the view controller's .m file.)
To better match the MVC paradigm, you should probably move all your password checking and storing code outside of the view controller, and into a state modeling class.
The password model object doesn't particularly need to be a singleton (some app might need multiple passwords, etc.).
When creating the view controller and any other objects than needs to touch the password credentials, pass it a pointer to the new password model object to message for store, verify, etc. That way all your password modeling code will be encapsulated and hidden in one place.
Related
OK, here is my situation and I'm really not sure on which design approach to use. So, I'd be glad to read some input on my particular case...
The scenario :
I've got a tab-based application
Initially we create an instance of NSWindowController (e.g. MyDocumentManager) which takes care of the tab creation/manipulation
Each tab contains (= is attached to) an instance of MyDocument
Now, I'm about to implement the menu actions.
For each menu there is a separate Menu Controller (actually a subclass of NSObject grouping all relevant functions), e.g. MyFileMenuController
File Menu's actions are linked to actions in a MyFileMenuController object, via Interface Builder
The question :
How is it possible that MyFileMenuController "knows" about MyDocumentManager (created in my AppDelegate.m), so that we can access current document details and perform all relevant actions? Any ideas? Which approach is preferable?
My ideas :
Passing object from class to class (not sounding that great)
Singletons (although I've honestly never used them, and do not know whether/how it could be my particular case)
Notifications & Notification Listeners
(Looking at it from the opposite side, though not sure) Delegate methods
OK (not sure if that's the best way to do it), but this is what I decided to do :
[[[NSApplication sharedApplication] delegate] MyDocumentManager]
So, as long as an object is part of my AppDelegate, this way I can access it from anywhere.
I would make an initial UIViewController linked to appDelegate.rootViewController.
In this new view controller (just call it "mainViewController") I would put my tabBar and the menuController.
I understand your interface is similar to facebook with a leftBarbutton which makes horizontal scroll and discover the menu. So in the selector for this leftBarButton I would call a method like:
- (void)discoverMenuForDocument:(MyDocument*)document {
// Set menu configuration for specific document
// Make animation to discover menu
}
Where document could be something like:
self.selectedViewController (<-- You cand make this in several ways depending on your code...)
Realize that (MyDocument*) is not an object but just a reference, so in my opinion there isn't any problem doing this.
Good luck!
I am using CoreData in iOS.
I have a modal AddViewController, with a RootViewController as the delegate.
Should I do the saving of the managed object context in the root controller, or in the actual modal controller itself?
I am seeing examples of passing the data back to the rootViewController, but can't see how this will work with data validation failures, or more complex scenarios that need the managed object context.
// AddViewController.m
- (void)save
{
[[self delegate] controller:(id)controller didFinishWithSave:(BOOL)save withName(NSString *)name;
}
// RootViewController.m
- (void)controller:(id)controller didFinishWithSave:(BOOL)save
{
if (save)
{
// save context
}
[self dismissModalViewControllerAnimated:YES];
}
As at the moment I am dismissing the modal using the delegate protocol.
Any advice on the best practices?
Thanks
I know this is a little late, but for others who come across this, I'd add a little more to Levend's answer.
Yes, you should have a separate manager class to handle the operations (possibly the class itself).
I would think that if your modal needed to handle validations, before calling on the delegate, it would validate the object. If it had an error, you could handle it right there. If it passed validations, then you could pass the valid object to the delegate. Thus the delegate can make the assumption that any object that is getting passed to it is a valid one.
As to which class you should save it, I think that is just a preference thing. But I would suggest you have a save method in the core data model itself.
Something I came across recently is the mogenerator which is supposed to help with managing CoreData classes. I haven't tired it yet, but it sounds good.
From an architecture point of view, you should create a separate manager class responsible for core data operations. From technical point of view, it isnt matter where you save(root, or modal VC) as long as you do it on the same thread where the data origins.
With MVC in mind I would let the M(odel) perform saving of the context as well as fetching data from it.
I have a NSDocument based application, which allows the user to send messages, after he has logged in.
These should be the user's steps:
The user starts the App and logs in (credentials are stored in the user model)
The user user sends the first message
The user hits CMD + N and sends another message (without having to log in again)
The message model is placed in the MyDocument.xib. However the user model should be place in a global place (I would say MainMenu.xib).
My question is now:
Does it make sense to put the model in the MainMenu.xib and how can I access it from MyDocument.m
Is there maybe a better way to do this properly without having to make a singleton class?
I would create an NSApplication delegate and then add you functionality in you delegate or an property of you delegate, you can then use [[NSApplicaton sharedApplicaton] delegate] to get you delegate. You application delegate is the place to associate model data that is common to you application.
I finally got it working with my NSApplication subclass (some say this is not the way to go). For this I had to change the principal class from NSApplication to my new custom NSApplication subclass.
Hey guys, I currently have a root table view which has a toolbar at the bottom and has labels and a refresh button within it, much like the Mail app's toolbar. This root table view controller obtains data from a server by allocating and initializing a DataUpdater class. Within this class are the NSURLConnection delegate methods that are called while communicating with the server.
As you can probably guess, I need to know when certain (delegate) functions are called within the DataUpdater class and the values of the parameters passed to these delegate functions so that I can update the labels on the toolbar accordingly (i.e. Connecting..., Updated, etc).
The problem I am having is determining how to notify the root table view controller of what is going on in these delegate methods. Would I use protocols, if so how? I have been skimming the documentation and don't quite see how I would get this effect. Or would you suggest I implement my program another way?
Thanks in advance!
A protocol is a kind of contract that says: I promise to provide the non-optional methods defined in the protocol, and maybe even the optional ones. It's purpose is like Java interfaces: to work around missing multiple-inheritence.
The delegate pattern in Objective-C normally works like this: you define a protocol, and then in your class, you define a variable like id<MyProtocol> myDelegate; and define a setter and maybe getter (either via normal methods, e.g. - (void)setDelegate:(id<MyProtocol>)aDelegate; or via properties.
Note that the delegate is not retained ! So if you work with a property, you need the assign option, not retain.
Now back in your class, you check whether myDelegate is nil and if not, you can directly call its non-optional methods. If you want to call an optional method, you first need to verify its presence via respondsToSelector:.
So if you decide to use the delegate pattern, you need to define a protocol, add that protocol to your root table view controller, implement the necessary methods there, and make sure to call [foo setDelegate:self]; or something similar to inform your other class that the root table view controller is the delegate. And of course implement the delegate calls in your class.
Edit:
An alternative might be to use NSNotifications, BTW. The advantage of notifications is that you can have multiple objects listen and react to them. The disadvantage is that you cannot (directly) pass values back. For example, you can define a delegate method that asks the delegate whether to do something or not. That's not possible with notifications, it's more like shouting into a room instead of having a one-to-one conversation.
DarkDust's answer about protocols is fine but I would like to add some things to it.
One underlying thing that is often forgotten when it comes to delegation is object ownership. When a program is running it creates a tree of objects. Its root object is the application delegate and for example it owns a navigation controller, which owns the individual view controllers, which own the view and the view owns its subviews and so on.
Often the question comes up: "Why is the delegate not retained, just assigned?" The problem is that if you send a message to a deallocated object the program crashes. So how do you make sure the delegate stays around? The answer is object ownership.
I give you an example: a UITableView and its data source which is the TableViewController which is nothing but a delegate. The TableViewController holds a reference with its view property to the UITableView, so it owns the TableView. That means when the tableView is alive there must also be its parent object present, which is the UITableView's delegate. So there is no danger that the delegate goes away somehow.
In the end it is again all about memory management.
Take home message is: think upfront about object ownership will make your program mode modular, easier to maintain and will lead to a looser coupling between individual objects.
I'm currently working on persisting the UI state of my iPhone app across launches, but it's proving to be a bit of an issue in one of my controllers - a sub-classed MFMailComposeViewController.
Essentially, I need to store (on app exit) the current To/CC/BCC lists, the subject, and the body so I can set the view up again after a relaunch. Unfortunately, Apple seems to have only provided setter methods for this data (e.g. setToRecipients:).
No doubt there's some private getters in there somewhere, but I'd rather not risk getting bounced by the App Store approvers...
Any thoughts/suggestions?
The best bet is to use controller.view, and search for all UILabels in the subview hierarchy.
(Also, there aren't private getters for MFMailComposeViewController. Those setters only delegates the message to its internal implementation class.)