UITextField not working inside a UITabBarController with IOS5 - cocoa-touch

Are there any restrictions on a UITextField when placed inside a tabview which not the main interface. In other words
Working fine scenario
1. A tab based application, with one of the view having a UITextField.
2. The tabview is the main interface for the application.
This works fine without any glitches
Not-working so fine scenario.
1. A tab based application, but the tab view is not the mainview.
2. There is another view MainWindow.xib with some intro animation, which then calls and shows the tabview.
3. UITextfield in such tabviews does'nt seem to work - especially in IOS5. Both methods work fine till IOS 4.3
4. The textfield is visible, but tapping it does not show any keyboard, if i call becomeFirstResponder via code, the keyboard is shown but is not responsive.
Any suggestions
The code is pretty standard
in the AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
tabViewController = [[tabView alloc] initWithNibName:#"tabView" bundle:nil];
[self.window addSubview:tabViewController.view];
//self.window.rootViewController=tabViewController
[self.window makeKeyAndVisible];
return YES;
}
tabViewController has a ProfileViewController with a simple textfield.
The textfield works fine if i do this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
tabViewController = [[tabView alloc] initWithNibName:#"tabView" bundle:nil];
profileView=[[Profile alloc] initWithNibName:#"Profile" bundle:nil];
//calling the view directly without using a tab view
[self.window addSubview:profileView.view];
[self.window makeKeyAndVisible];
return YES;
}
Is there something else that needs to be done for IOS5 when the tab view is not the main interface? I have been cracking my head at this for a few days, all my apps with a UITextfield inside a tabview are not usable in ios5. Any help is highly appreciated
Edit: Uploaded the project file http://www.mediafire.com/?xjuc4udlph78saj - XCode 4.2 on Lion
It is a simple project with two options, Creating a tabbarcontroller from the delegate itself, and i also have a view(tabView) with a tabbarcontroller. There are 2 views for the tabbar FirstViewController & SecondViewController.
In the AppDelegate.m if using method 1(create UITabBarController inside AppDelegate, all is well). If i choose to add a subview of tabView, the uitextfield does not work.
I have not really handled the releasing of objects, since this is test project and it is only for proof of concept.
Thanks

After hours of searching, fiddling and experimenting. I have found out the solution.
This seems to happen when there are more than one UIWindow in the application.
In my case, i was diong this
AppDelegate starts off with its own UIWindow Once i have played some
startup animations, i try to display another view with a
tabbarcontroller, and ofcoures a window to hold the UITabBarController
The second window (even after setting it to makeKeyAndVisible) seems
to be blocking keyboard events fore UITextField inside the
UITabBarController.
The following has worked for me:
Rather than having the second view with its own window, i had it with a UITabBarController, and a UIView/UIWindow(this is for the sake of having a default view for the nib file). And when i needed to show the tabbarview i have used this
[[[UIApplication sharedApplication] keyWindow] setRootViewController:TabBar]
I am not sure of a better way, but that have worked for me. In short, i have found that having another UIWindow inside the app causes issues with becomeFirstResponder.

Related

Application windows are expected to have a root view controller at the end of application launch warning

I have been stuck with this warning for several hours now. I've looked around SO for answers, attempted all the ones I found and couldn't find the solution. Here's the run-down of the code I have, which Xcode generated by default.
This is in my AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
I have this on main.m (according to this answer)
int main(int argc, char *argv[])
{
#autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
return retVal;
}
}
I also have all the connections in my MainWindow.xib connected correctly. So I'm at a loss right now. Anything that I could be missing? Thanks in advance!
It's odd to be setting your window's rootViewController in application:didFinishLaunchingWithOptions: if you have a MainWindow.xib. Usually a project follows one of three templates:
Some projects have a MainWindow.xib. The target's “Main Interface” is set to “MainWindow” in the target's Summary tab (or in its Info.plist). This xib's File's Owner is UIApplication. The xib contains an instance of AppDelegate, connected to the File's Owner's delegate outlet. The xib also contains a UIWindow, whose rootViewController outlet is connected to a UIViewController (or subclass, such as UINavigationController), which is also in the xib. By the time the application delegate receives the application:didFinishLaunchingWithOptions: message, the xib is entirely loaded, so the window and its root view controller are already set up.
Other projects don't have a MainWindow.xib. The target's “Main Interface” is empty. Instead, the UIApplicationMain function creates an instance of AppDelegate, sets it as the UIApplication's delegate, and sends it the application:didFinishLaunchingWithOptions: message. The app delegate handles that message by creating a UIWindow, creating a view controller (or several), and setting the window's rootViewController property. The default version looks like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Some projects have a MainStoryboard.storyboard. I'm not going to describe this in detail because it doesn't seem relevant to your problem.
The problem you're describing makes it sound like you're using half of the first template, and half of the second template. That won't work. You need to decide which approach you're taking, and go all-in.
You can open xib file and right-click "File's Owner" in Placeholders. If view didn't connect to View outlet then hold "Ctrl" key and drag right mouse click to design, then run again ^^ (do not drag to particular control, drag to background design when appear border View).
I have this message because I had in my RootViewController #property(weak, nonatomic) IBOutlet UIView* loadView;
and viewDidLoad was called twice... Rename it to something else...
I have solve issue in my project, Follow the below steps to solve it..
1) Open the main view controller nib file, that file you have reference in appDelegate
eg.ViewCotroller.xib
2) On nib file check the view connection, if not connected to file owner then connect it.
3) Now run the project.

Black screen on iPad storyboard using splitViewController

I have an app whose iPhone storyboard is working fine. My iPad storyboard (which uses a split view controller) just comes up with a black screen.
Logging tells me that both the master and detail view controllers' -viewDidLoad: methods are being called
Logging also tells me that my detail's view's -drawRect: is being called
I didn't post code because I think the problem lies in my storyboard setup (iPhone storyboard works fine).
Update: -viewDidAppear: isn't being called in either of my view controllers, either.
On an iPhone application, you can specify the root view of your application with the "Main nib file base name" key in the info.plist file. From the sound of it, the correct root view is not getting loaded for the iPad. Trying adding/or setting the correct view for "Main nib file base name (iPad)" in your info.plist file.
Also, make sure you are using the correct application lifecycle method to load your views.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[self.window addSubview:yourSplitViewController.view];
} else {
[self.window addSubview:yourNavigationController.view];
}
[self.window makeKeyAndVisible];
return YES;
}

Draggable/tabbable UIPopOverController?

I don't know if you people are familiar with the Blackboard Learn app for iPad. Well it has PopUp windows to show info.
Well, I would like to implement something similar on a iPad app, and I was wondering if it is possible to doit with UIPopOverControllers...
Basically you can open a view and drag it around and keep it on a border of the screen as a tab to show updates and so.
Is it possible to do something similar with UIPopOverControllers or UIViews (the dragging and the tabbing)?
Cheers from Mexico
UPDATE 1:
Well, I managed to load multiple UIViews, next thing goes to be able to drag 'em around, any suggestions?
UPDATE 2:
I tried to add the UIPanGestureRecognizer in otherView.m (the Pop Up Window), here's how it looks
otherView.h
#interface otherView : UIViewController <UIGestureRecognizerDelegate>{
UIPanGestureRecognizer *drag;
}
#property (nonatomic, retain) UIPanGestureRecognizer *drag;
...
otherView.m
- (void)viewDidLoad {
[super viewDidLoad];
// Drag
drag = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(dragAction)];
[self.view addGestureRecognizer:drag];
[drag release];
}
otherView is displayed in mainWindow directly from the appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
// Set the view controller as the window's root view controller and display.
//self.window.rootViewController = self.viewController;
[window addSubview:viewController.view];
[window addSubview:secondView.view];
[self.window makeKeyAndVisible];
return YES;
}
Hope you can help me out
As far as I know there is no mechanism to move a popover around on the screen - they are attached to a bar button or point in a view and that is where they exist until they are dismissed. Popovers also don't allow interaction with views (buttons, text fields etc) in the main view while they are visible.
Sounds like a great user interface concept though, good luck!!

Cocoa-Touch internals: How does the view know its controller?

If you add a subview to a view or add a view to a window, how does iOS know which controller this view belongs too?
Easy example:
Have a UIView without UIViewController and add it to the window [window addSubView:myView] --> it will not rotate.
Now use a UIViewController, have it implement shouldAutoRotateToInterfaceOrientation: and add the controller's view to the window: [window addSubView:myController.view] --> magically, the view will adjust to interface orientation.
But look at the code: in both cases a UIView was added. How can iOS possibly be aware that in the second case a UIViewController was involved?
I'm interested in how this is done internally. My best guess is that UIViewController.view is a setter which adds the controller to an internal array of controllers or assigns itself to some internal variable which holds the currently active controller.
Simple. Look in UIView.h. It's right there. Each UIView has a pointer back to a UIViewController (which is apparently referred to as the "viewDelegate").
Dave DeLong is correct (and gets +1) as it is clearly defined UIView.h as #package so anything in UIKit can access it.
Here is an example of accessing that variable for educational purposes only (obviously you will not do this in a real application).
SomeAppDelegate.m
#synthesize navigationController=_navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
//DO NOT TRY THIS AT HOME
UIView *mynavview = self.navigationController.view;
//Guaranteed _viewDelegate atleast in iOS 4.3
Ivar ivar = class_getInstanceVariable([UIView class], "_viewDelegate");
UIViewController *controller = object_getIvar(mynavview, ivar);
NSLog(#"controller = self.navigationController? %#", controller == self.navigationController ? #"Yes" : #"No");
return YES;
}
UIViewController has a private class method (called controllerForView:, I believe) which is used to find the view's controller. Internally, there is probably a table used to connect the two together, and this method simply finds the proper location in that table and returns its value. When the result is nil, the default implementation will be used (don't rotate).
If you want to be sure about the name of the method, set a breakpoint in -[UIView becomeFirstResponder], tap on a text field, and step through the code until it shows up in the call stack. I suggest using becomeFirstResponder because it is easier to control than most things which get the view controller.

UIView is shown displaced to the top

I have a simple app that has two view controllers. Both of them have a UINavigationBar at the top, as a header. The second UIViewController is displayed as a modal view, when the user clicks on a button on the first one.
When my app first launches, the initial view doesn't completely cover the main UIView and seems "pushed" to the top (see image below).
After I click on the "instructions" button, which displays another view with presentModalViewController:animated:, and dismiss the modal ViewController, everything is displayed correctly.
Anybody knows what I might be doing wrong?
I have nothing in viewWillAppear, and this is my viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
if (!self.model) {
self.model = [[FRRSushiRiceModel alloc] init];
[[self.header.items objectAtIndex:0] setTitle: #"Perfect Sushi Rice: Ingredients"];
}
}
and my application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create and add the main controller (ingredients)
self.ingredientsController = [[FRRIngredientsViewController alloc] init];
[window addSubview:self.ingredientsController.view];
[window makeKeyAndVisible];
return YES;
}
This small project reproduces this behavior:
Test Case
Did you untick the "Wants Full Screen" setting in IB, either for the UINavigationController or UIViewController?
I found the error, guys.
Basically I was trusting the system to correctly set the frame of my views to match the usable portion of the screen. This works when you add it to some controller of controllers (such as UINavigationController), or add it via IB.
If you add your controllers programmatically, you need to set the view's frame explicitly. A good default is:
[[UIScreen mainScreen] applicationFrame]
represents the part of the screen available to applications: the whole screen minus the status bar.