I understand that I should set self.title in -initWithNibName:bundle:.
What about self.navigationItem.titleView?
Since self.navigationItem.titleView seems only to be used when self.view is loaded, I'm thinking I should, to save memory, set self.navigationItem.titleView in -viewDidLoad and nil it in -viewDidUnload, e.g.:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"logo.png"]];
}
- (void)viewDidUnload {
self.navigationItem.titleView = nil;
[super viewDidUnload];
}
What about self.navigationItem.backBarButtonItem?
It seems to work OK to set self.navigationItem.titleView in -viewDidLoad and nil it in -viewDidUnload.
You should set self.navigationItem.backBarButtonItem in -initWithNibName:bundle because if you push two view controllers without animation -viewDidLoad will not get called for the first view controller that's pushed. So, if that view controller sets self.navigationItem.backBarButtonItem in -viewDidLoad, it will actually not get set, and the back button on the second view controller will just default to the title of the first view controller as usual.
Related
Still having issues with pushing a new UIView on rotation. I am following an example that I found. It's SO freaking close. It wigs out with an error at this point with the error of;
'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target .'
controller nvs = [self.storyboard instantiateViewControllerWithIdentifier:#"LandscapeView"];
[self.navigationController pushViewController:nvs animated:YES]
Clearly, I'm missing something here. What I'm trying to achieve is a different view pushed onto the stack when the user rotates their device. Like calendar.
Entire statement
LandscapeViewController * nvs;
- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && self.presentedViewController == nil)
{
if (!self.landscapeViewController)
//self.landscapeViewController = [[LandscapeViewController alloc] initWithNibName:#"LandscapeView" bundle:nil];
//Set the location of the where you want the view to go i.e. the next view controller
nvs = [self.storyboard instantiateViewControllerWithIdentifier:#"LandscapeView"];
//Push the view onto the device
[self.navigationController pushViewController:nvs animated:YES];
if ([self respondsToSelector:#selector(presentViewController:animated:completion:)])
[self presentViewController:self.landscapeViewController animated:YES completion:NULL];
else
[self presentModalViewController:self.landscapeViewController animated:YES];
}
else if (deviceOrientation == UIDeviceOrientationPortrait && self.presentedViewController != nil)
{
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)])
[self dismissViewControllerAnimated:YES completion:NULL];
else
[self dismissModalViewControllerAnimated:YES];
}
}
Thanks in advance!
Jeremy
Got it. Rather then pushViewController pushing nvs which was set outside the statement. I referenced it directly in using self.landscapeViewController.
Below is the code. Hope this helps someone in the future.
self.landscapeViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"LandscapeView"];
[self.navigationController pushViewController:self.landscapeViewController animated:YES];
I'm trying to open one link in safari when i click the UIWebview (its like ad display).
Following code am using but what happend is when i click the webview its opening inside UIWebview for some links (not all).
- (BOOL)webView:(UIWebView *)webView1 shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if (webView1==webview) {
if (UIWebViewNavigationTypeLinkClicked == navigationType) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
}
what happens here is if any text link in that UIWebView then its opening correctly ,But if a UIWebview with images then its opening in same UIWebview instead of a new browser.
MY CURRENT CODE
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.example.com/files/ad.htm"]]];
[_webView setBackgroundColor:[UIColor clearColor]];
[_webView setOpaque:NO];
_webView.scrollView.bounces = NO;
}
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}
Seems like those images has been linked using anchor tags...
Try this...
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
static NSString *reguler_exp = #"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])[.])+([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$";
//Regular expression to detect those certain tags..You can play with this regular expression based on your requirement..
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", reguler_exp];
//predicate the matched tags.
if ([resultPredicate evaluateWithObject:request.URL.host]) {
[[UIApplication sharedApplication] openURL:request.URL];
return NO;
} else {
return YES;
}
}
EDIT: Don't allow this delegate method to get called for the first time.Add some logic that it won't get called for the 1st time loading the webview.
(SOP's new requirement,see below comment)
How to to detect the touch on uiwebview,
1)Add the tapgesture to your webview.(before that add UIGestureRecognizerDelegate in your viewcontroller.h)
example:
UITapGestureRecognizer* singleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleSingleTap:)];
singleTap.numberOfTouchesRequired=1;
singleTap.delegate=self;
[webview addGestureRecognizer:singleTap];
2)Then add this delegate method,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
//return YES,if you want to control the action natively;
//return NO,in case your javascript does the rest.
}
Note: In case you want to check whether the touch is native or htmml(javascript) check the nice little tutorial here,about handling the javascript events etc....Hope this helps you..
I have a tabbed application project in Xcode and I'm trying to create a back button for one of the viewcontrollers in order to go back to the previous view. You can get to this viewcontroller from 2 different viewcontrollers so I'm wondering if it's possible to pop the viewcontroller in order to go back to the correct view controller(the one you were previously on). This code doesn't seem to work with tabBarController.
-(IBAction) goBack: (id)sender{
[self.tabBarController popViewControllerAnimated: YES]; }
NSArray *array = [self. tabBarController viewControllers];
[self.tabBarController popToViewController:[array objectAtIndex:2] animated:YES];
Think this one works . Havent tested it . Please let me know
check this.
id controller = [self.tabBarController selectedViewController];
if([controller isKindOfClass:[UINavigationController class]])
{
[controller popViewControllerAnimated:YES];
}
NSArray *array = [self. tabBarController viewControllers];
for (UIViewController *controller in array) {
if ([controller isKindOfClass:[ReachViewControllerName class]]) {
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}
May be it ll helps.
I have an item detail view which I would like to use for two purposes:
1) to create a new item
2) to edit an existing item
When editing, the view will be pushed onto the navigation stack, getting the nav bar from it's parent.
On item creation, I want to present the view modally, but still have a navigation bar at the top, with "Done" and "Cancel" buttons.
What I don't want is to ever see the view with two nav bars, or none.
How would I implement this?
In order to accomplish this I:
Removed the nav bar from my view.
When launching modally, first created a nav controller, and then displayed the nav controller modally with my view as the root view (even though I didn't plan on pushing anything else onto the stack). So changed this:
StoreDetailView *storeDetailView = [[StoreDetailView alloc] initWithNibName:#"StoreDetailView" bundle:nil];
// ... configure the view, including setting delegate...
[self presentViewController:storeDetailView animated:YES completion: nil];
to this:
StoreDetailView *storeDetailView = [[StoreDetailView alloc] initWithNibName:#"StoreDetailView" bundle:nil];
// ... configure the view, including setting delegate...
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:storeDetailView];
[self presentViewController:navController animated:YES completion: nil];
And then in the StoreDetailView, determined what the nav bar should look like based on whether the delegate was set:
if (self.delegate == nil) {
self.navigationItem.rightBarButtonItem = [self editButtonItem];
} else {
[self setEditing:TRUE];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(done:)];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel:)];
}
When I use the following code to insert a view on top of a split view, I am getting orientation problems.
Here is the code I use,
[window addSubview:aSplitViewController.view];
[window insertSubview:aViewController.view aboveSubview:aSplitViewController.view];
What happens here is that the view controller ( which contains labels and buttons) loads in landscape mode while its components load in portrait mode...
I feel that the window insertSubview is creating this problem because when I used [window addSubview:aViewController.view] the view is getting displayed properly in landscape mode with its components in landscape mode as well...
Here is the code which I feel is giving me the problem
In my App Delegate
- (void) makeSplitViewController {
NSMutableArray *controllers = [NSMutableArray arrayWithArray:tabBarController.viewControllers];
// First tabbbar item
// detail view
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
UINavigationController *navDetailView = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
navDetailView.hidesBottomBarWhenPushed = YES;
// root view
rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
rootViewController.detailViewController = detailViewController;
rootViewController.navigationItem.title = #"List";
UINavigationController *navRootView = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
navRootView.hidesBottomBarWhenPushed = YES;
navRootView.navigationBar.barStyle = UIBarStyleBlackTranslucent;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.tabBarItem.title = #"Face Sheet";
splitViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
splitViewController.navigationItem.title = #"Face Sheet";
splitViewController.viewControllers = [NSArray arrayWithObjects:navRootView, navDetailView, nil];
splitViewController.delegate = detailViewController;
splitViewController.hidesBottomBarWhenPushed = YES;
[controllers addObject:splitViewController];
// Second tabbbar item
scoreViewController = [[ScoreCardViewController alloc] initWithNibName:#"TableViewController" bundle:nil];
scoreViewController.tabBarItem.title = #"Score Card";
scoreViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
scoreViewController.navigationItem.title = #"Score Card";
[controllers addObject:scoreViewController];
tabBarController.viewControllers = controllers;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Create tabbar
tabBarController = [[UITabBarController alloc] init];
//tabBarController.delegate = self;
// Set window
[window addSubview:splashController.view];
[window insertSubview:tabBarController.view belowSubview:splashController.view];
[self.window makeKeyAndVisible];
application.statusBarOrientation = UIInterfaceOrientationLandscapeRight;
return YES;
}
and here is the code in my SplashScreenView
- (IBAction) proceedButtonClick:(id)sender
{
// Initialize loginpopview
PhysicianLoginViewController *loginViewController = [[PhysicianLoginViewController alloc] init];
popOverController = [[UIPopoverController alloc] initWithContentViewController:loginViewController];
popOverController.popoverContentSize = CGSizeMake(350, 200);
popOverController.delegate = self;
// Set a notification to dismiss it later
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loginViewControllerDone:) name:#"loginViewControllerDone" object:popOverController.contentViewController];
// Present popover
if ([popOverController isPopoverVisible])
{
[popOverController dismissPopoverAnimated:YES];
}
else
{
[popOverController presentPopoverFromRect:CGRectMake(485, 600, 100, 100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
}
// Dismiss popview controller and setup the tabbar
- (void)loginViewControllerDone:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Button in content view controller was tapped, dismiss popover...
[self.popOverController dismissPopoverAnimated:YES];
// remove subview
[self.view removeFromSuperview];
// set tabbar
i3EAppDelegate *appDelegate = (i3EAppDelegate *) [[UIApplication sharedApplication]delegate];
[appDelegate makeSplitViewController];
}
It would be great if someone could point out where I am going wrong. I have been stuck with this problem for quite a few days and I have tried everything that comes to my mind...
Your problem is that the rotation handling of UIWindow and UIViewController just isn't designed to work that way. Quoth the documentation:
In an iOS application, the window object does much of the work associated with changing the current orientation. However, it works in conjunction with the application’s view controllers to determine whether an orientation change should occur at all, and if so, what additional methods should be called to respond to the change. Specifically, it works with the view controller whose root view was most recently added to, or presented in, the window. In other words, the window object works only with the frontmost view controller whose view was displayed using one of the mechanisms described in “Presenting a View Controller’s View.”
This paragraph is somewhat vague and contradictory (is it the most recently added view controller, or the controller for the topmost view?), and in practice doesn't seem to necessarily match observations. The bottom line is that adding multiple views to a UIWindow will screw up the automatic rotation handling.
You should change your code to use presentModalViewController:animated: (maybe with modalPresentationStyle set to UIModalPresentationFormSheet) or a UIPopoverController instead of adding multiple subviews to the window.
Try:
[aViewController.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];