Does anyone have an idea how Apple implemented the UITabBarController in the iOS Remote App (for controlling iTunes)?
Specifically, how the Remote will show a blacked out Tab Bar until the user selects an iTunes library (in a modal view), after which the tabs show "Songs," "Artists," etc.
Where would they have placed the logic to check that an iTunes library is selected and how do they blackout the tabs until it is?
Thanks
You basically can set the UITabBarItem's enabled property to false.
Like:
[tabBarItem setEnabled: NO]; // to disable
Related
I am building my first iOS app (other than just samples etc) that I will try to put on the app store. I will make this for iPhone/ipad and using iOS 5.0.
I was thinking of having my app have tabbed views. I will have a basic users and a "member" user. The member user would have access to a feature/view/data that a basic user does not. I am looking for two things. One, some ideas on a best way to protect/hide this from the basic user and two, some technical code help too on how to do it. I have had an idea that I could possibly have one pin code that all members know or even do an id/password where I keep that info in a plist or something and then I could in viewdidload (maybe?) cause a modal view to come up and challenge the person before letting them see the view/data.
Looking for any ideas.
I would not recommend a preset password approach. You will find the baked-in username and password posted on message boards almost instantly. You will want to use either a web-service for authentication or have it be an in-app purchase.
Implement this delegate method, then use logic to decide whether to return YES or NO:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
Parameters
tabBarController
The tab bar controller containing viewController.
viewController
The view controller belonging to the tab that was tapped by the user.
Return Value
YES if the view controller’s tab should be selected or NO if the current tab should remain active.
Discussion
The tab bar controller calls this method in response to the user tapping a tab bar item. You can use this method to dynamically decide whether a given tab should be made the active tab.
I have been searching the net, and i have found many very good examples on how to create a login page for your iPhone app. However... none of then meets my demands, an since i am new to iPhone development( i know java / c / C++ and objective-c), so the programming itself is not the issue.. The issue is where to put the code and what design patterns to use..
My app is a basic tabbar controller with 3 tabs that could contain navigation controllers, but that is not important.. it is the part before the tabbar controller i am interrested in, namely the need to authenticate the user towards a Lotus Domino Server. I have the authenification code working, so that is not the issue either..
By the way, i am concentrating on IOS5 and using storyboards..
Where do i put the "check if user is still authenticated" code ? The domino server will log the user out after 1 hour, so if the user has the app open(in background) then the code that downloads data will die if the user is not told that the session has expired..
So here is what i would like..
When the app launches, show the login page. This is working for now with the Login View Controller as initial controller, and a modal segue to the tabbar controller..
Next time the App is launched(either from background or from new is user has closed it completely), check if username and password is stored in userdefaults, and then just login in background, and if that fails(password has changed or another failure) then show the login view controller again..
So to sum up, where do i put the "part 2" code ? I have a seperate authenticator class that is using delegates, and i can use this class to perform the authentification, and the it will answer back if all is good.
Do i put this in the AppDelegate code ? If i put it in one of the tabbar viewcontrollers, then there might be an issue with the user having tab2 open when launching after 2 hours, and if the check is in tab1, then tab 2 will fail.. Should i put the code in ALL the tabbar viewcontrollers ? Naaa, that is ugly..
I am leaning towards the AppDelegate(appdidbecomeactive), but can that be used as delegate in my authenticator class ?
That was a bit long, sorry for that, but i needed to explain my problem fully so people would understand what i need..
Thank you for your help.. This is my first post, but this forum is fantastic :)
I'd definitely put both part one and part two code in the AppDelegate.
This allows you to create the appropriate viewcontroller at app start and remove the tabbarcontroller from within the AppDelegate if the authentication times out etc.
I'm not sure about your modal segue to a tabbarcontroller though (I'm not familiar with storyboards yet though). Modal implies you wouldn't be able to present any other view modally on top of the tabbar controller. I think it sounds like it would be much more appropriate to create your logincontroller and tabbarcontroller programmatically and add/remove them directly in your application’s main window as needed from your AppDelegate.
I would tell the AppDelegate to check the login status very time the tab is changed or data loaded.
In my app there is authentication required, so when you launch one of the tabs on tab bar, "class A" checks are there credentials saved if not, "class B" modal view controller with fields to login launches.
So my question is : in which method in class A (loadView, viewWillAppear or maybe in another one) should be implemented checking if there are credentials saved and other stuff described above.
And my additional second question is:
is pushing modalviewcontroller correct way to show login screen, or i should do that differently?
Thank you for reply guys.
OH ! One More Thinh
And one more thing. I've done implementing LoginView by adding delegate and presenting ModalVC (Harkonian the Piquant's method). But in my tab bar app i have got very confusing problem. I mean when user taps login button (assume that everything was correct and he's able to secured data) how PROPERLY switch to tab where is secured info. I mean previously selected tab.
i did it by adding in
-(IBAction) login {
//some code
self.tabBarController.selectedIndex =1;
And it seem to work good but is it correct ?
I have a very similar use case in my app -- it requires a passcode to authenticate. After a lot of testing and tweaking I found the following design to be the best approach:
Don't use class A to launch your credentials VC -- use the app delegate instead.
For security purposes, typically you'll want the credentials VC to show before the user can view the underlying view. It's much easier to handle this in the app delegate than in a VC. In addition, you need to consider what happens when your app is backgrounded -- a screen shot is taken of the current state of the app. If you are using viewController A to show the credentials view, when the app relaunches the user will be able to see whatever sensitive information was visible on app close until the app finishes launching and VC A presents the credentials VC.
Don't insert your credentials view into an existing ViewController -- use a new UIWindow instead.
You don't ever want any other view to be able to sit on top of your credentials view. Ever. Even views that would normally always be on top, like UIAlertView. The easiest way to achieve this is to have a special UIWindow just for your credentials view. Show this window and hide the primary app window whenever you need to display the credentials view.
How does this approach look in practice?
If you are at all interested in how well this design works, you can check out the passcode feature in Audiotorium Notes for iPad. I spent a lot of time with this design to make sure it was as secure as possible.
If you have any specific implementation quests feel free to ask and I'll try to answer them.
I'm writing an app that will allow iPhone users to login to their accounts. Once logged in the user can pull information, change passwords, change other types of data via webservices. I'm new to iPhone programming and I'm a bit confused on my viewController setup to handle this. What I would like to do is the following;
1) if the user is NOT logged in - display a view which takes up the entire screen displaying my login/password text fields etc. ( I will have some conditionals set in place checking to see if the user has u/p saved in a plist)
2) if user is logged in or once the user logs in, remove the current full size view and load the tabBar view. If the user logs out then the main login view will load.
I will need two viewControllers for this particular scenario? I've read a great deal on view controllers. Read all of the Apple documentation but I still get confused since there are so many options/methods to use.
As always I thank you in advance.
T
Just one of many possible options:
Create LoginViewController and UITabBarViewController. Application delegate will check on start-up whether it already has user's credentials and show the appropriate controller
if ([dataModel hasUserCredentials])
[window addSubview:[tabControlle view]];
else
[window addSubview:[loginController view]];
LoginViewController performs log in and notifies app delegate:
- (void) loginComplete
{
// XXX animation?
// XXX view(Will/Did)(Appear/Dosappear) and all the stuff,
[[loginContoller view] removeFromSuperview];
[window addSubview:[tabController view]];
}
Here is how I would do it:
The tab bar controller is your main view controller. You initialize it first (in the main NIB file) and add it to the window in your app delegate.
In application:didFinishLaunchingWithOptions:, you check whether the user is already logged in or not. If not, you immediately present your login screen as a modal view controller. If you do this without animation, the user will not notice that the tab bar controller is already present underneath.
When the user logs in, you dismiss the modal view controller and your tab bar UI becomes visible.
You should look at creating a Navigation-Based application. This will have a UINavigationController built in. You can use that to control your windows.
I have a window within an iPhone application, which is displayed modally to allow the user to enter their settings for a web service upon 'first run'.
The text fields have helper text set, and when you tap them the keyboard shows and allows you to enter text.
Unfortunately the text fields do not clear the helper text, show the edit caret or show the text being entered (as in the screenshot below).
Any suggestions?
The window is being displayed with [self presentModalViewController:<controller_name> animated:YES];, which may or may not be the cause of this issue - when I run the UI via the Interface Builder 'test' application the text boxes respond like normal.
Clear when editing begins has been set for both fields.
Thanks in advance!
Edited: More information
After the info Bart Gottschalk provided I thought I should add some more information. First, the application is a Navigation Based Application.
Secondly, the test app Bart recommended worked fine, so that takes the modal window and the view out of the equation.
Third, I was presenting the modal view when the -(void)viewWillAppear... delegate method was being called - which may very well be the wrong place... however I'm not 100% sure if I should be presenting the modal view from within the didFinishLaunchingWithOptions of the App Delegate...
(this is happening on Simulator and iPhone 3.1.3)
In Interface Builder did you check the box for "Clear When Editing Begins"? With that checked the text field should clear any value once the use taps to edit which is the behavior I think you're looking for.
You can also set the same property programatically using clearsOnBeginEditing if that is convenient in your code.
My guess is that you've done this and it's not behaving as you expect. Just checking on this as a first step in helping you debug.
Also, does this happen in both the Simulator and on a testing device?
Bart
Edited Below...
This seems strange. Let's strip away everything but the basics of presenting a modal view when the application starts and see what happens.
I've recreated the most basic app (that I know of) to test presenting a modal view controller at launch and verify that field editing works fine. What happens for you when you do the same/similar in a new project?
Here is what I'm doing:
1) Create a new view-based app in Xcode called "ModalViewTest"
2) Create a new UIViewController with xib called ModalViewController
3) In ModalViewController.h add a method
-(IBAction)closeModalView;
4) In ModalViewController.m add the method implementation as
-(IBAction)closeModalView {
[self dismissModalViewControllerAnimated:YES];
}
5) In the ModalViewController.xib create two text fields and set the placeholder text for each to abcd1234 and confirm that "Clear When Editing Begins" is checked.
6) In the ModalViewController.xib add a button "Close" and set Touch Up Inside to fire "closeModalView"
7) In the application delegate (ModalViewTestAppDelegate) add the following import
#import "ModalViewController.h"
8) In the application delegate (ModalViewTestAppDelegate) applicationDidFinishLaunching add the following after the line containing [window makeKeyAndVisible];
ModalViewController *modalViewController = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
[viewController presentModalViewController:modalViewController animated:YES];
9) Save everything
10) Build and Run this new app
Does editing of the text fields work as expected? If yes, what is different about how you are building and presenting your modalView? If no, then we'll need to dig further to determine what is going on in your environment.
Second Edit Below...
When creating a navigation-based application I did the following to present the modal view at application start. Does this work for you in both your test app as well as your real app?
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
ModalViewController *modalViewController = [[ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
[navigationController presentModalViewController:modalViewController animated:YES];
}
Well, I just figured it out, but honestly without the persistence and awesome help from Bart it would have taken much longer and been much more frustrating.
It turns out the problem was that I was using a Window instead of a View in the XIB file. This was why when showing the modal view within the Navigation controller it wouldn't display properly (i.e. only a white screen) and why the UITextField would not work properly when showing the view from the RootViewController.
So, to recap - modal views should have UIView, not UIWindow in the XIB/NIB File.
Thanks for your help Bart!
I have the same problem but in iOS7 only. I solved it by changing the tint color of textField to blue in the Storyboard