NavigationViewController with WebView-containing View Controller - iphone

I have a problem with a navigation controller.
First of all, there is a navigationviewcontroller.
Also, there is A webviewcontroller-containing view controller, meaning that webview controller is loaded inside WEBcontroller.m
I made that when the WEBcontroller is loaded, it automatically loads google.com. The function is in the -viewDidLoad()
First, when the app is launched, navigationview loads WEBcontroller.m, then WEBcontroller loads google.com as intended.
Then, when I click any link in the google.com, navigationview pushes a new view with
[self.navController pushViewController:newWebController animated:YES];
[newWebController gotoUrl:[request.URL absoluteString]];
It, of course, works. The newly loaded(and alloc) WEBController.m loads gmail.com by calling "gotoUrl" function.
And, I click another links to go "gmail.com/help"
So,
google.com -> gmail.com -> gmail.com/help
Then, I close the app, and play some games... it makes iPhone free memory.
Launching the app again, the "gmail.com/help" webpage is shown. Then, I click the [Back] button which is at the navigationBar which calls [popViewController].
Then, the navigation controller properly go back to preceding WEBController.m which was showing "gmail.com" page.
BUT!! there is a problem. Because the memory was 'dealloc' by iPhone, the WEBController is loaded AGAIN with "google.com" page, not "gmail.com" page.
I've searched this problem but I couldn't get any.
Really thank you for reading and giving some interests to my problem.

I'm confused. You are using a UIWebView? If so, why don't you just let it handle the links/navigation? Why are you creating (and pushing) a new UIWebView for every link click? Technically speaking, a view controller needs to be able to handle being freed and restored from memory by IOS. This is done in viewDidLoad and viewDidUnload. But I don't think that's what you want/need here.

Related

Switch between view without closing view xcode

I have a Login interface, user interface, and a Main menu.
When I'm logging in, I switch on my user interface.
if I do a UIModalTransition, and if I come back to the page, I need to RE-login again, it's a problem for me.
I search a method for Switch between view but don't close them, because if you closed them, views restart, it's the same for UIWebview, I would like to switch between views without closed and reset views.
Is it possible ?
I don't really know what kind of Code is it.
If you have ideas, please tell me.
In this answer i tried to explain the view controllers orchestration as i see it.
The idea is to create the manager class taking care of elements storage and presentation. It also mentions the way to manage the login information.
You can use pushViewController ie..
[self.navigationController pushViewController:yourUserInterFaceViewController animated:YES]; for transition between login and user interface.
you can use 3 ways
1)pushing the view into UINavigationController
2)presenting the view with ModalViewController
3)adding subView to rootViewController and remove it using removeFromSuperView when needed.
(you can allocate them when app launches and access them using
[YourAppDelegate sharedApplication].yourViewController)
Since your appDelegate is a singleTon class it will always return the same viewcontroller you've allocated at the time of launching the app. You can use Lazy Load also.
May be this will help.

iPhone [self performseguewithidentifier... ] is not showing the new view controller

I have been all over stackoverflow and all over Google and I cannot seem to figure this one out. Here's my scenario:
I have my app's "main screen" where the user first makes decisions about what they're going to do. The app works off of a CoreData database which is created by "importing" XML files. The user can choose to open an XML file attached to an email in my application, which automatically triggers my main screen to show up and run the import of the file.
I can get this far without any issues. In my storyboard, I have a segue called ParseSegue from my main screen to a view controller which will handle the parsing and give the user some status information.
When the main screen is called via the email app, the main screen automatically calls
[self performSegueWithIdentifier:#"ParseSegue" sender:self];
I then check for this segue name in prepareForSegue and it's a valid name. This is where I assign the file URL to the parser controller so that it can parse the correct file.
The problem is that the segue never actually happens. The prepareForSegue method gets called, the name "ParseSegue" can be checked against and is valid, but the segue itself simply does not happen. If I add a button to the main screen and tell it to perform the segue within the storyboard, it works fine. But calling it programmatically seems to do nothing.
It turns out that I was looking in the wrong place entirely. My problem was that in my appDelegate, where the app reacts to the incoming URL, I was inadvertently creating a new instance of my storyboard and my main view controller. This was different than the one which was already active and may or may not have been on the screen.
The controller I was creating was never actually shown. I only noticed this because the log:
NSLog(#"Source: %#", [segue.sourceViewController description]);
would show different memory addresses for my test (the button push) and the import test. This led me to believe that I was, in fact, working with two different instances of the storyboard and the app's main view controller. Thanks to Paul for the suggestion of logging the destination and the source controllers.

Loading background data and launch image

I have read the apple guidelines and I know it says you shouldn't do that but hear me out as I would like to know if what I am doing is bad practice.
When my application loads up, in the app delegate, a web call is made which sets up the order of the tabs, as well the content within it. Web call is like this
WebCalls *wc = [[WebCalls alloc] init];
[wc setWebCallDidFinish:^(NSString * json) {
// set up tab order here, as well as stores the JSON in a file on the phone
// Also code here to download images and cache them on phone
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
}
[wc getData:phoneNumber];
Now this code works great but the problem is what will happen when app starts is
Launch image shows for a second (which is not very long, sometimes it's half a second or less so just annoying)
Screen goes black for about 2 seconds while json is parsed and images downloaded etc
Then first tab controller is shown
What I want is a seamless transition between the splash screen and the first screen so the user never sees black screen.
What I was thinking of doing is something like this
Change iPhone splash screen time
In the answer given, the guy pushes a view forward to be the splash screen. Would it be bad practice to push that view forward, and then in that screen do the web calls which gets json data, and downloads images, then dismiss the view and have the tabcontroller view become main view?
Or how else would I prevent this delay? Is it bad practice to have a large enough web call like this in AppDelegate?
If this is bad practice to push a view forward while doing background loading, what else would you recommend? Would it be better if I just make the tabController the main rootViewController first and do the webCall in the first tab shown instead, then update the tabs when this web call finished? I was considering this one, but the tab order could be in any order after the web call is made, so not sure what tab will be shown first.
Would be grateful for your input
In the answer given, the guy pushes a view forward to be the splash screen. Would it be bad practice to push that view forward, and then in that screen do the web calls which gets json data, and downloads images, then dismiss the view and have the tabcontroller view become main view?
This is the way to do it. It's generally bad practice to download stuff from applicationDidFinishLaunching, what happens if the phone is not connected to the internet?
Present a simple view controller (using presentModalViewController:controller animated:NO with a UIActivityIndicator and a label describing what's going on, and then dismiss it when loading finishes (or it it fails, just display an error and deny access to the app). Remember to also check for airplane mode and notify the user.

UIWebView delegate not working the second time

I have an rss feed which returns a json containing a title, short text and full-size text. The title and part of he short text is displayed in a TableView.
I have 3 controllers with 3 views.
View 1 displays a TableView containing articles from the json( the title and short text ), each article has a "Read more" button, in the IBAction of the button, i push a viewcontroller(2) into the navigation controller, the controller has a UIWebView(second View), which loads a html string. The string contains links, when the user taps a link, i want to present a modal view controller with another WebView(3), this time using the request(keep in mind that both WebViews have separate controllers and nibs).
The delegates are set properly on both of them, i tried both from code and using visual tools. In the delegate method shouldStartLoadWithRequest in the first WebView i check to see if the request parameter contains "http" or "www", because only then i want to call the second WebView. The second WebView works well the first time, the view is presented modally fine, but when i dismiss it and tap the same link or another, the shouldStartLoadWithRequest delegate method is not called, but the link loads in the same WebView(the first one).
I googled this but didn't find a similar case to mine, or a solution. I don't have that much experience with ios app development, but a colleague is pretty good, and we didn't manage to find a solution to this problem. We took the code apart and analyzed it, but we didn't find a potential source for this problem, and he has a separate project where he has the same problem, only he uses only one controller and one WebView (our controllers and nibs where created independantly). We were pretty thorough with the research and the code examination
It seems that the solution was quite easy. The first WebView, aparently looses the connection to it's delegate, so, in the second WebView controller just add
- (void)viewWillDisappear:(BOOL)animated {
[self.parentViewController viewWillAppear:YES];
}
and in the first controller of the first WebView:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
webView_.delegate = self;
}
I hope this helps someone

How do I implement an automatic jump to a detailed page if the user was on this previously (or fix my code for doing this which has a design flaw)

Any advice on how to fix this issue I have, or a better implementation design perhaps?
Requirement
Needed a way for the application at start up to take the user to the previous details page, if this was what they were on prior to quiting the application in their last session
If they were on the main screen of the app, then at restart they can stay here
The assumption is I'm working with UINavigationController and the main screen and details screen are built on a UITableViewController
My Implementation Concept
Put a check in "viewdidLoad" to see whether they were on a detailed screen, and then if so jump to this (refer to code below)
Issue
Works fine normally, however when I trigger a memory warning things screw up and I get nav bar weird behavior. For example I see the main page nav buttons, when it looks like I'm on the detail page content (UITableView)
My Analysis
From what I see when I am on the details page (appointmentsListController) and cause a memory warning in the simulator I see:
(a) the main page "viewDidLoad" actually gets called, which my concept didn't expect, so whilst I had hit the BACK button from the detailed view (UINavigationController) to go to the main view (RootViewController), in fact my code is run and it try's to throw the user back to the details page again
(b) I note in my logs after this point that [AppointmentListController viewDidLoad] seems to get called before the previous AppointmentListController dealloc method is called (i.e. like I was in controller A, went back to controller B, but got thrown back to A - and the initial dealloc for the first part didn't kick in until late...)
So I guess it's obvious my idea isn't too great
Question
Any suggestions on how to better implement my requirement? (how to check, which method to put them in)
Code
- (void)viewDidLoad {
[super viewDidLoad];
// My Implementation of the Requirements which seems flawed in the case there is memory warning triggered
if ( previousSelectedScreen >= 0 ) {
// Setup New Controller
AppointmentListController *appointmentListController = [[AppointmentListController alloc] initWithNibName:#"AppointmentListController" bundle:nil];
appointmentListController.screenToShow = previousSelectedScreen;
// Push new view onto stack
[[self navigationController] pushViewController:appointmentListController animated:NO];
[appointmentListController release];
}
}
Here's what I'd suggest: rather than having this logic in your view controller, but it in your application delegate. By constructing your navigation stack before displaying it you will hopefully avoid some of the weird things that can happen with nav bars, etc. To get rid of the memory warnings you may need to look at how your app allocates memory: it may not necessarily be to do with this.
Anyway - in your application delegate you can perform your check to see if the user was on a detail page when they exited. If they are, you can create an array containing the navigation stack (ie, Main Screen -> Details Page). You can then pass this into a navigation controller using its setViewControllers method. Once this is done, you can display your window and finish launching the app.