I have a UIViewController called MainViewController (it is inside a navigationController). I have another UIViewController called OptionsViewController. Inside OptionsViewController I have a logout button and when clicked it calls a delegate in the MainViewController:
- (IBAction) logout:(id)sender
{
[self.delegate viewController:self loginSuccess:YES]; //calls this delegate
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
NSString * username = [standardDefaults stringForKey:#"kApplicationUserNameKey"];
NSError * error = nil;
[standardDefaults removeObjectForKey:#"kApplicationUserNameKey"];
[SFHFKeychainUtils deleteItemForUsername:username andServiceName:#"convore" error:&error];
[self dismissModalViewControllerAnimated:YES];
}
The delegate called at MainViewController is:
- (void) viewController:(OptionsViewController*)viewCon loginSuccess:(BOOL)loadFlag
{
if (loadFlag){
LoginViewController* lvc = [[LoginViewController alloc] init];
lvc.delegate = self;
[self.navigationController presentModalViewController:lvc animated:YES];
//this same code works in the viewDidLoad (it presents the LoginViewController, but not here)
[lvc release];
[self.groups removeAllObjects];
[self.table reloadData];
Topic * topic = [Topic object];
topic.tid = [NSNumber numberWithInt:-2];
self.detailViewController.topic = topic;
self.detailViewController.detailItem = topic.tid;
}
}
The issue is that when this delegate is called, it should present a LoginViewController (as can be seen from the code above), however it doesn't. I tried to put the presentModalViewController code in the delegate inside the viewDidLoad of MainViewController and it shows up, but when trying to show it in this delegate it doesn't. Why is this? And yes I checked the delegate is getting called (tried putting a NSLog inside the delegate)
UPDATE:
The OptionsViewController is shown as a modalViewController as well with the following code from MainViewController:
- (IBAction)showOptions:(id)sender
{
if ([self.detailViewController.message isFirstResponder])
[self.detailViewController setViewMovedUp:NO];
OptionsViewController * opt = [[OptionsViewController alloc] init];
opt.delegate = self;
opt.mgvc = self;
UINavigationController * uinc = [[UINavigationController alloc] initWithRootViewController:opt];
uinc.navigationBar.tintColor = [UIColor blackColor];
uinc.modalPresentationStyle = UIModalPresentationFormSheet;
uinc.title = #"";
uinc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; //transition shouldn't matter
[self presentModalViewController:opt animated:YES];
float xCenter = 384;
float yCenter = 512;
if (self.splitViewController.interfaceOrientation == UIInterfaceOrientationPortrait || self.splitViewController.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown){
xCenter = 384;
yCenter = 512;
} else if (self.splitViewController.interfaceOrientation == UIInterfaceOrientationLandscapeLeft || self.splitViewController.interfaceOrientation == UIInterfaceOrientationLandscapeRight){
xCenter = 512;
yCenter = 384;
}
uinc.view.superview.frame = CGRectMake(0, 0 , 318, 209);//it's important to do this after presentModalViewController
uinc.view.superview.center = CGPointMake(xCenter, yCenter);
[opt release];
}
When I try to just show OptionsViewController itself (without the UINavigationController, everything works fine). Why is this?
Are you sure your view is inside a navigation controller? If not, change the line to:
[self presentModalViewController:lvc animated:YES];
Related
I implemented a map view in my app.
I implemented a didselect annotation method.
In this method,i open a popover. It works fine. But when the popover is dismiss & try to click on annotation again, then method is not called more.
if i clicked other annotation except previously select annotation then method will called.
My code is follow:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)aView {
ReadingDatabaseAppDelegate *appDelegate = (ReadingDatabaseAppDelegate *)[[UIApplication sharedApplication] delegate];
if([self isPad])
{
detailsView *popUp=[[detailsView alloc] initWithNibName:#"detailsView_ipad" bundle:nil];
popView = [[UIPopoverController alloc]initWithContentViewController:popUp];
popView.delegate =self;
[popView setPopoverContentSize:CGSizeMake(400, 400)];
AnnotationImageView *myLocationImage = (AnnotationImageView *)aView;
popUp.locationID = myLocationImage.locationID;
NSLog(#"%d",popUp.locationID);
popUp.list=listdata;
detView.fromMapView = TRUE;
if (appDelegate.preferenceRow == 1) {
detView.title = #"ATM Details";
popUp.isBranch = 0;
}
else {
detView.title = #"Branch Details";
popUp.isBranch = 1;
}
CGPoint annotationPoint = [mapView convertCoordinate:aView.annotation.coordinate toPointToView:mapView];
float boxDY=annotationPoint.y;
float boxDX=annotationPoint.x;
CGRect box = CGRectMake(boxDX,boxDY,5,5);
UILabel *displayLabel = [[UILabel alloc] initWithFrame:box];
[popView presentPopoverFromRect:displayLabel.frame inView:mapView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[displayLabel release];
}
}
** How can i solve this??**
When you dismiss your popover, deselect the annotation using -deselectAnnotation:animated:.
I have a problem when trying to display the GKMatchmakerViewController on my game view.
Normally I create a multiplayer match programmatically by auto-matching 2 opponents, and that works fine.
But when I try to display the standard Game Center Matchmaking view, it dismisses my game view and pushes me back to the menu.
Menu View -> Game View.
I think the problem might be that my menu view acts as my main view and all other views are removed when the Game Center view is displayed (since only one view controller can be shown at the time).
am I setting up my view hierarchy wrong? How should it be done so my Game View wont be dismissed when displaying the Game Center view?
EDIT - updated with code that calls the GKMatchMakerViewController
GameviewController with method that is called when I want to display the Game Center match making controller
- (void)presentCustomVSBattle {
ourRandom = arc4random();
[self setGameState:kGameStateWaitingForMatch];
AppDelegate * delegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[[GCHelper sharedInstance] findCustomMatchWithMinPlayers:2 maxPlayers:2 viewController:delegate.viewController delegate:self];
}
// This method is called in GCHelper.m
- (void)findCustomMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id<GCHelperDelegate>)theDelegate {
if (!gameCenterAvailable) return;
matchStarted = NO;
self.match = nil;
self.presentingViewController = viewController;
delegate = theDelegate;
if (pendingInvite != nil) {
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
self.pendingInvite = nil;
self.pendingPlayersToInvite = nil;
}
else {
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
request.playersToInvite = pendingPlayersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
self.pendingInvite = nil;
self.pendingPlayersToInvite = nil;
}
}
In your case, the dismissView Controller calls look unnecessary, try getting rid of them :)
I have a programatic tabbar delagate with navbar with a banner view delegate. And for the life of me I can't seem to get the tabs to pop the root view on click. I know I need to use something like [self.navigationController popToRootViewControllerAnimated:NO]; But I don't know where to put it in my app delegate.
#implementation AppDelegate {
UITabBarController *_tabBarController;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
NSError *setCategoryError = nil;
CGRect bounds = [[UIScreen mainScreen] bounds];
self.window = [[UIWindow alloc] initWithFrame:bounds];
self.window.backgroundColor = [UIColor whiteColor];
NSMutableArray * viewControllers = [[NSMutableArray alloc] init];
NSString * subscriptionListFile = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"Subscription.plist"];
NSDictionary * subscriptionList = [[NSDictionary alloc] initWithContentsOfFile:subscriptionListFile];
NSArray * subscriptionFolders = subscriptionList[#"Folders"];
NewsListViewController * newsController = nil;
UINavigationController * newsNavigationController = nil;
BannerViewController * bannervcs = nil;
for (NSDictionary * folderDetails in subscriptionFolders) {
NSArray * newsItems = folderDetails[#"Items"];
NSString * folderTitle = folderDetails[#"FolderName"];
NSString * folderIcon = folderDetails[#"FolderIcon"];
UIImage * folderIconImage = [UIImage imageNamed:folderIcon];
newsController = [[NewsListViewController alloc] initWithNewsSourceList:newsItems];
[newsController setTitle:folderTitle];
newsNavigationController = [[UINavigationController alloc] initWithRootViewController:newsController];
[newsNavigationController setTitle:folderTitle];
bannervcs = [[BannerViewController alloc] initWithContentViewController:newsNavigationController];
[bannervcs.tabBarItem setImage:folderIconImage];
[viewControllers addObject:bannervcs];
}
_tabBarController = [[UITabBarController alloc] init];
_tabBarController.viewControllers = viewControllers;
self.window.rootViewController = _tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
#end
Any idea where I add popToRootViewController? I tried at the end but it doesnt seem to be grabbing any controller...
You'll need to set something to be your UITabBarControllerDelegate. Assuming you want to try this out on your AppDelegate, add the line to your method:
_tabBarConroller.delegate = self;
And then, add this method to your AppDelegate (since it is now also considered an UITabBarControllerDelegate)
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
viewController.navigationController popToRootViewControllerAnimated:NO];
}
This is assuming that, regardless of what state the user left the navigation stack on a tab, that tapping another tab always takes the user to the root view controller of the nav stack.
If you want navigationController in your tabBar then you have to add yourNavigationController instead of viewController.
So in your case you are not adding navigationControllers to your tabBarControllers array.
[viewControllers addObject:bannervcs];
so instead of adding bannervcs add newsNavigationController
[viewControllers addObject:newsNavigationController];
For more info just read and take sample code from UITabBarController Class Reference
I am trying to build a custom tab bar controller but for some reason the views will not switch... The initial view is loaded properly. Here is my init method:
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
AccountViewController *accountViewController = [[AccountViewController alloc]
initWithNibName:#"AccountViewController" bundle:nil];
MoreViewController *moreViewController = [[MoreViewController alloc]
initWithNibName:#"MoreViewController" bundle:nil];
BarTabViewController *barTabViewController = [[BarTabViewController alloc]
initWithNibName:#"BarTabViewController" bundle:nil];
LocationsViewController *locationsViewController = [[LocationsViewController alloc]
initWithNibName:#"LocationsViewController" bundle:nil];
self.viewControllers = [NSArray arrayWithObjects:locationsViewController, accountViewController,
barTabViewController, moreViewController, nil];
[self.view addSubview:locationsViewController.view];
self.selectedController = locationsViewController;
return self;
}
Like I said, this will display the selected controller properly, however when the app launches and I try to switch views with the tab bar, the subview just become grey... I have been looking through several tutorials to try to figure out this issue, but it seems that I am doing it exactly the same. I have also checked the IB file to make sure my tabs are connected properly, they are. The following is the code to switch items:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
if (item == locationsTabBarItem) {
UIViewController *locationsController = [viewControllers objectAtIndex:0];
[self.selectedController.view removeFromSuperview];
[self.view addSubview:locationsController.view];
self.selectedController = locationsController;
}
else if (item == accountsTabBarItem) {
UIViewController *accountsController = [viewControllers objectAtIndex:1];
[self.selectedController.view removeFromSuperview];
[self.view addSubview:accountsController.view];
self.selectedController = accountsController;
}
else if (item == barTabTabBarItem) {
UIViewController *barTabController = [viewControllers objectAtIndex:2];
[self.selectedController.view removeFromSuperview];
[self.view addSubview:barTabController.view];
self.selectedController = barTabController;
}
else {
UIViewController *moreController = [viewControllers objectAtIndex:3];
[self.selectedController.view removeFromSuperview];
[self.view addSubview:moreController.view];
self.selectedController = moreController;
}
}
try With this one
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.selectedIndex = 0;
self.tabBarController.viewControllers = [NSArray arrayWithObjects:locationsViewController, accountViewController,
barTabViewController, moreViewController, nil];
self.tabBarController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self.navigationController pushViewController:delegate.tabBarController animated:YES];
How do I access a previous view controller while in a subview? Because I'm able to perform actions but I'm just not able to use self.[my main view controller].
This is my code, for testing purposes:
PhotoViewController.m
-(IBAction)likeButton:(UIButton *)sender
{
//this part works
NSString *num = #"2";
self.label.text = [NSString stringWithFormat:#"%# + %#",
self.label.text,
num];
//this part doesn't work
//switch over to the third view to see if it worked
self.tabBarController.selectedIndex = 0;
}
I have a UITabBarController and one of its view controllers has a UIScrollView. Inside of the UIScrollView is a PhotoViewController object.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch
MyTabBarViewController *vc2 = [[MyTabBarViewController alloc] init];
SecondViewController *vc3 = [[SecondViewController alloc] init];
controller = [[DemoAppViewController alloc] init];
controller.view.frame = CGRectMake(0, 20, 320, 460);
controller.title = #"Intro Screen";
vc2.title = #"Explore";
vc3.title = #"Send a Pic";
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = [NSArray arrayWithObjects:controller, vc2, vc3, nil];
[controller release];
[vc2 release];
[vc3 release];
[self.window addSubview:tbc.view];
[self.window makeKeyAndVisible];
return YES;
}
Also, my TabBarViewController.m //not my actual UITabBarController though, wording is confusing
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
arrayCount = [array count];
scroller.delegate=self;
scroller.pagingEnabled=YES;
scroller.directionalLockEnabled=YES;
scroller.showsHorizontalScrollIndicator=NO;
scroller.showsVerticalScrollIndicator=NO;
//should have an array of photo objects and the number of objects, correct?
scrollWidth = 0;
scroller.contentSize=CGSizeMake(arrayCount*scroller.frame.size.width, scroller.frame.size.height);
for (int i = 0; i < arrayCount;i++) {
PhotoViewController *pvc = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
UIImageView *scrollImageView = [[UIImageView alloc] initWithFrame:CGRectOffset(scroller.bounds, scrollWidth, 0)];
CGRect rect = scrollImageView.frame;
pvc.view.frame = rect;
pvc.label.textColor = [UIColor whiteColor];
id individualPhoto = [array objectAtIndex:i];
NSLog(#"%#",individualPhoto);
NSArray *keys=[individualPhoto allKeys];
NSLog(#"%#",keys);
NSString *imageURL=[individualPhoto objectForKey:#"source"];
NSURL *url = [NSURL URLWithString:imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
pvc.imageView.image = [[UIImage alloc] initWithData:data];
pvc.label.text = [individualPhoto objectForKey:#"id"];
[scroller addSubview:pvc.view];
[scrollImageView release];
//[pvc release];
scrollWidth += scroller.frame.size.width;
}
if (arrayCount > 3) {
pageControl.numberOfPages=3;
} else {
pageControl.numberOfPages=arrayCount;
}
pageControl.currentPage=0;
}
If a UIView subclass needs to message a controller above itself, a common (and often recommended?) way to do this is to have the view subclass implement the delegate protocol (a weak linked instance variable pointing to the view controller that you want to use). The view controller should then set itself as the delegate of the view when that view is being initialize.
Try defining this method in your PhotoViewController:
+ (YOURTABBARCONTROLLER*)parentTabBarController:(UIResponder*)view {
id nextResponder = nil;
id v = view;
while (nextResponder = [v nextResponder]) {
NSLog(#"Found Responder: %#", nextResponder); //-- ADDED THIS
if ([nextResponder isKindOfClass:[YOURTABBARCONTROLLER class]])
return nextResponder;
v = nextResponder;
}
return nil;
}
it will traverse the responder chain and return the first controller of a given type that is found. Replace YOURTABBARCONTROLLER with your actual tab bar controller class and you should be able to have:
-(IBAction)likeButton:(UIButton *)sender
{
//this part works
NSString *num = #"2";
self.label.text = [NSString stringWithFormat:#"%# + %#",
self.label.text,
num];
[PhotoViewController parentTabBarController:self.view].selectedIndex = 0;
// self.tabBarController.selectedIndex = 0;
}
Updated
-(IBAction)likeCommentButton:(UIButton *)sender
{
//code goes here
TypeSomethingViewController *typeSomethingViewController = [[TypeSomethingViewController alloc] init];
typeSomethingViewController.delegate = self;
[self presentModalViewController:typeSomethingViewController animated:YES];
[typeSomethingViewController release];
}
-(void)typeSomethingViewController:(TypeSomethingViewController *)controller didTypeSomething:(NSString *)text
{
//NSLog(#"response: %#", controller);
NSString *commentID = self.label.text;
for(UIViewController *controller in [PhotoViewController parentTabBarController:self.parentViewController.view].viewControllers)
{
if([controller isKindOfClass:[DemoAppViewController class]])
{
DemoAppViewController *davc = (DemoAppViewController *)controller;
//[davc commentPicture:commentID :message];
[davc likePicture:commentID];
}
}
[PhotoViewController parentTabBarController:self.view].selectedIndex = 0;
[self dismissModalViewControllerAnimated:YES];
}
Try this out to switch to the first controller.
self.tabBarController.selectedViewController
= [self.tabBarController.viewControllers objectAtIndex:0];
Change the index value to switch to whichever controller you want to switch to.
The tabBarController should be a property of the app delegate.
Try accessing it with :
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication]
delegate];
appDelegate.tabBarController.selectedIndex = 0;
Unless you declare the same property in PhotoViewController, you won't be able to access it this way.
Try importing the app delegate header in PhotoViewController.h like so :
#import "MyAppDelegate"
then try this code above replacing tabBarController by tbc which, as the example suggests is the name given to this property.