uiwebviewdelegate not called from non-visible uiwebview - iphone

I am trying to avoid the blank white window that shows while a UIWebView loads content. Instead of putting a background on the UIWebView, I'd like to just put up a HUD on the current window and then push the new uiviewcontroller that contains the uiwebview when the content is loaded. Here's what I've done (code shortened for sanity's sake):
FirstView:
MyViewController *myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
myVC.parentController = self.navigationController;
UIView *myView = [myVC view]; // Force view to load
MyViewController:
- (void)viewDidLoad
{
...
[myWebView setDelegate:self];
[myWebView loadHTMLString:htmlString baseURL:baseURL];
...
}
- (void) webViewDidFinishLoad:(UIWebView*) webView {
[parentController pushViewController:self animated:YES];
}
OK, so viewDidLoad is getting called, but none of the uiwebviewdelegate methods are getting called. However, if I push the view controller
FirstView:
MyViewController *myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[self.navigationController myVC animated:YES];
Then all of the uiwebviewdelegate methods in MyViewController do get called.
I'm stuck.

I don't know the specific requirements for your app, but it's usually a better practice to first push your view controller and then show the HUD on top of the new view controller while your content loads. You would add the HUD to the view controller's view in viewDidLoad, and remove the HUD in your webView's webViewDidFinishLoad callback method.
If you are not already doing so, make sure you are loading your web view's content in a background thread so as to not block the main UI thread while the content loads, otherwise it will appear to the user that your app has temporarily frozen.

Related

Sharing a UIView across multiple UIViewControllers without background flashing

Is there way to share a UIView between a parent and child UIViewController without any noticeable visual glitches when it's added to the child's view as a subview?
I have a UIViewController and its corresponding UIView, considered as a 'masthead', that will be shared between a parent and child UIViewController. (image something like a stock ticker that will be present somewhere on the screen, across all screens in the app)
When the child UIViewController is created and pushed on to view hierarchy (I'm using them with 'UINavigationController'), what I see is its placeholder background area peaking through before the masthead view is added as a subview.
I thought about creating unique masthead view for each screen but most of the app's views will share this masthead. Thus managing content changes across all of them seemed complicated and I'm trying to take the simpler route by having 1 instance.
AppDelegate work:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Other prep work, including setup of self.window
UIViewController *vc = [[ParentViewController alloc] initWithNibName:nil
bundle:[NSBundle mainBundle]];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = navController;
}
The Parent UIViewController implementation:
#interface ParentViewController : UIViewController {}
#implementation ParentViewController()
- (void)viewDidLoad
{
// The shared controller and its view has already been created and initialized.
// Adding the masthead to my view
[self.view addSubview:self.mastheadController.view];
[super viewDidLoad];
}
- (void)showChildController
{
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:nil
bundle:[NSBundle mainBundle]
withMastheadController:self.mastheadController];
[self.navigationController pushViewController:detailController animated:YES];
detailController = nil;
}
Here's Child UIViewController implementation:
#interface DetailViewController : UIViewController {}
#implementation DetailViewController()
- (void)willMoveToParentViewController:(UIViewController *)parent
{
// Since this method is invoked before our viewDidLoad and the
// parent's viewWillDisappear, remove shared view from parent view
// stack.
[self.mastheadController.view removeFromSuperview];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Adding the shared masthead controller view to our view
[self.view addSubview:self.mastheadController.view];
}
The reason I'm using willMoveToParentViewController is because I thought that if I wait until 'viewWillDisappear' gets called for the ParentViewController, it was not enough time for the mastheadView to get inserted into the child view hierarchy without any noticeable effects.
This is my understanding about the order in which the view appear/disappear events happen:
child:willMoveToParentViewController (parent will be null upon dismiss)
child:viewDidLoad
parent:viewWillDisappear
child:viewWillAppear
Any help would be greatly appreciated.
I would approach this differently. Why not add the view to navController's view, and then remove it when you don't want to see it any more?

How to load a navigation view created programmatically and make it a ModalView?

I'm making an iphone app out of the utility template in xcode. So in my FlispSideView I have a button that should show a custom image picker. I decided to use this nice one here link.
Now I made some changes cuz I'm not using a navigation controller to load the custom image picker (but rather modally) which is created programmatically inside the .m file. So I made the FlipSideView the delegate for the custom image picker but still lost when I come to loading the view. I created a xib file and tried to connect it to the image picker but that didn't work.
So I wonder what's the best way to do that?
I'm not sure I interpreted your question correctly, but based on the title, I think this might be what you are looking for:
// Initialize your custom controller and set the delegate
UIViewController *controller = [[UIViewController alloc] initWithNibName:#"MyView" bundle:nil];
controller.delegate = self;
// Set the title of your custom controller (optional)
controller.title = NSLocalizedString(#"My View", nil);
// Create a navigation controller with your custom controller as the root view controller
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:controller];
// Present the navigation controller as a modal view controller
[self.navigationController presentModalViewController:navCon animated:YES];
// Release objects you own
[navCon release];
[controller release];
If your image picker is a controller, and all the outlets on your xib are properly connected to it, this should work. You should be able to make your FlipSideView the delegate. Pressing cancel or done in the modal view should call a message in the delegate that says
[self.navigationController dismissModalViewControllerAnimated:YES];
EDIT:
Here is the first line of my example code updated to match the tutorial you are using:
CustomImagePicker *controller = [[CustomImagePicker alloc] init];
The rest is the same. You initialize a navigation controller with controller as the root view controller, then present the navigation controller as a modal view controller.
Creating navigation programatically
Use the code below to navigate programatically. Write the following code in
AppDelegate.m class
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
self.nav = [[UINavigationController alloc] initWithRootViewController:firstViewController];
[_window addSubview:nav.view];
[_window makeKeyAndVisible];
}

Why my presentModalViewController method doesn't work

I created a UIImagePickerController in the viewDidLoad method in my rootViewController.
- (void)viewDidLoad {
[super viewDidLoad];
UIImagePickerController *pickerController=[[UIImagePickerController alloc] init];
pickerController.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.delegate=self;
[self presentModalViewController:pickerController animated:YES];
[pickerController release];
}
But the view of UIImagePickerViewController didn't appear on the screen.
The SDK version is 4.3
Is there some mistakes i make?
Thanks!
viewDidLoad is called after the view has been loaded and before the view is displayed. viewDidAppear: is called when the view is onscreen and is the correct point to present a modal view controller.
And if you want to do it only once, you might want to consider using a BOOL to keep track of it.

Change UIWindow's presented view from UIViewController method

I have a simple application with two subclasses of UIViewController.
I want to change the view being displayed by my application's UIWindow by calling a method from one of my UIViewController subclasses.
Essentially I'm just messing around and I'm trying to construct a simple test application with a login screen, that after a user enters credentials a main view is presented. I'm not too familiar with the window and view mechanisms of iOS programming, and I'm currently reading http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW1 and attempting to learn a bit about it.
If this is for the purpose of a login screen, you should add the main view controller to window directly, and add the login view controller as a modal view inside the main view controller.
Inside applicationDidFinishLaunching...
MainViewController *mainViewController = [[MainView....... // instantiate UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:mainViewController];
[mainViewController release];
[window addSubview:navController.view];
Inside MainViewController
-(void)viewWillAppear:(BOOL)animated
{
LoginViewController *loginVC = .... //instantiate
[self.navigationController presentModalViewController:loginVC animated:NO];
[loginVC release];
}
if login successful,
[self dismissModalViewControllerAnimated:YES];

Change from UIViewController to UITableViewController

This one make me go crazy. I am building an iphone app where the first view is a login view. UIViewController, when the user succesfully logs in i want to display i table view. Somehow i just have big problems doing this.
In my app delegate i load my loginViewController, and then i want from the loginViewController load my listViewController.
What is the logic behind switching to a UITableViewController from a UIViewController?
you'd better to do it in your app delegate and surely NOT add the UITableViewController.view to the UIViewController.view... just add it to the UIWindow and then dismiss the old UIViewController (removeFromSuperView it's view and then release it)
EDIT:
that's how i manage:
i add a method in my appDelegate:
-(void)switchMainView;
and from my UIViewController i just call it with this:
[[[UIApplication sharedApplication] delegate] switchMainView];
in switchMainView i just
remove my UIViewController.view from superview,
release UIViewController,
alloc the UITableViewController and init it, then
add its view to the window app:
-(void)switchMainView{
if (mainView!=nil){ // mainView is the UIViewController
[mainView.view removeFromSuperview];
[mainView release];
mainView = nil;
}
Menu *vc; // Menu is my class, subClass of a UITableViewController
vc = [[Menu alloc] init];
nc = [[UINavigationController alloc] initWithRootViewController:vc];
[window addSubview:nc.view];
[vc release];
}
and then i do the same for going back, eventually
Assuming you already have your custom UITableViewController created:
YourTableViewController *vc = [[UITableViewController alloc] initWithStyle:...];
[self presentModalViewController:vc animated:YES];
[vc release];
you can use either i do'nt think there is a major impact but definitely they might have some advantage/Disadvantage over other..
for better understanding read the below tutorial.
http://cocoawithlove.com/2009/03/recreating-uitableviewcontroller-to.html