Instance variables not working in ViewController in UINavigationController - objective-c

I'm still new to iOS development but I've ran into a problem that I can't solve and I've tried looking online but can't find anything yet.
I'm using a UIImagePickerController to pick and image and I'm using it in the App Delegate. When an image is returned, in the imagePickerController:didFinishPickingMediaWithInfo method, I want to make a new navigation controller with a view controller and put it over the "app".
Here is how I'm doing it:
CustomNavigationController *customNavigationController = [[CustomNavigationController alloc] init];
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:[NSBundle mainBundle]];
[customNavigationController pushViewController:photoViewController animated:NO];
[customNavigationController.view setFrame:[[UIScreen mainScreen] applicationFrame]];
[photoViewController release];
[self.window addSubview:customNavigationController.view];
//Call method of photoViewController.
[[customNavigationController.viewControllers objectAtIndex:0] addPhotoFromData:info];
[self.tabBarController dismissViewControllerAnimated:YES completion:nil]; //Get rid of UIImagePickerController
However in the photoViewController, I don't have access to any instance variables synthesized and loaded in viewDidLoad. They all return to null. There is also a tableView and calls to reload the tableView do not actually cause the tableView to respond.
Here is some of the code from photoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.photoCount = 0;
self.timestamp = [[NSDate date] timeIntervalSince1970];
self.photos = [[NSMutableArray alloc] initWithCapacity:5];
self.photosData = [[NSMutableArray alloc] initWithCapacity:5];
self.uploadingCount = 0;
UINib *customCell = [UINib nibWithNibName:#"CustomTableCell" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:customCell forCellReuseIdentifier:#"customCell"];
self.tableView.separatorColor = [UIColor clearColor];
NSLog(#"%#", self);
}
and also the addPhotoFromData method:
- (void)addPhotoFromData:(NSDictionary *)info
{
[self.photos addObject:info];
NSLog(#"%#", self.photos); //Doesn't add "info" and does not return anything when later called from other methods.
[self.tableView reloadData]; //Doesn't work
Everything was working before I add in the UINavigationController. I'm completely lost.
EDIT: After some more debugging attempts, I have discovered that the view is not loaded when addPhotoFromData is called. viewDidLoad is called afterwords. Is there a way to delay method calls?

Any reason you can't have the PhotoViewController call addPhotoFromData: inside the viewDidLoad method? You can always access properties of the app delegate from the view controller:
YourAppDelegateType * delegate = [UIApplication sharedApplication].delegate;
[self addPhotoFromData:delegate.info];

Related

Bugged Game Center Matchmaker appearance

I am developing multiplayer for my game and I have encountered following issue
I am using Cocos 2d 2.1 , iOS 6 and following code to show matchmaker (Landscape orientation)
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:4 viewController:[app navController] delegate:self];
And thats how it appears
Following code is used for that function
- (void)findMatchWithMinPlayers:(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;
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
GKMatchmakerViewController *mmvc =
[[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
}
is this code in HelloWorldLayer? if so is that the first layer that the director calls? I have the same problem but it's fixes if I follow strictly the cocos2d template that was created for me. Meaning that I use the IntroLayer as the initial layer and from there it transitions into the HelloWorldLayer where I have the game center code. I think it has something to do with the director being loaded too late but I'm not sure
This happens when you try to push on a UIViewController, but you only have a UIView in your app, and no UIViewController. Let me guess, you do not have a rootViewController.
If you are working from the EAGLView template, you must declare a UIViewController for the UIView. This can be as simple as,
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
window.rootViewController = [[UIViewController alloc] init];
window.rootViewController.view = glView; // MUST SET THIS UP,
// NOW THE EAGLView HAS A UIViewController.
[glView startAnimation];
}
Then, anytime you want to push on one of those GameKit UIViewControllers, use the presentViewController method of your Window object's rootViewController
For example:
[self.window.rootViewController presentViewController:vc animated:TRUE completion:^(void){puts("DONE");} ] ;
The bugginess will go away and the window will be correctly formed.

White screen after presenting a modal view controller

I'm getting a white screen after presenting a modal view controller. This is how I do it:
SomeViewController *controller = [[[SomeViewController alloc] initWithManagedObjectContext:managedObjectContext] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
[navController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentModalViewController:navController animated:YES];
The navigation bar works fine, as I set it up in SomeViewController, but the view's contents are not visible, and all I see is the white background color of the root window.
The strange thing is, that this used to work, but now it doesn't for some reason.
What could be the problem?
EDIT:
This is how I create SomeViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:#"Some View"];
UIBarButtonItem *sortButton = [[[UIBarButtonItem alloc] initWithTitle:#"Sort" style:UIBarButtonItemStylePlain target:self action:#selector(sortButtonClicked:)] autorelease];
[[self navigationItem] setRightBarButtonItems:[NSArray arrayWithObjects:sortButton, [self editButtonItem], nil] animated:YES];
UIBarButtonItem *backButton = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(dismissModalViewControllerAnimated:)] autorelease];
[[self navigationItem] setLeftBarButtonItem:backButton];
// Hack to force landscape orientation
UIViewController *controller = [[UIViewController alloc] init];
[self presentModalViewController:controller animated:NO];
[self dismissModalViewControllerAnimated:NO];
[controller release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
The white screen was caused by the xib file of the controller not being part of the target(its target membership checkbox was unchecked).
Do you happen to have some other init meted also in the SomeViewController class? Please post the whole .m file. If so, you can try to delete the initWithNibName method and check if it shows the content.
EDIT:
Another strange point is the initWithManagedObjectContext method you are using on the viewController instance. Can you explain it?
try
SomeViewController *controller = [[[SomeViewController alloc] init] autorelease];
it should work fine.

pushViewController not working with tab bar controller

I am trying to push in a new view controller with the code:
[self.navigationController pushViewController:webViewController animated:YES];
But its not working. This code happens when you select a cell in my table view. I have a table view which I think is preventing this from happening. I have tried presenting it modally but that gets rid of the navigation bar and i can't go back. There is an extremely similar to this but the answer didn't work for me!
UPDATE
- (void)loadView {
// Create an instance of UIWebView as large as the screen
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
// Tell web view to scale web content to fit within bounds of webview
[wv setScalesPageToFit:YES];
[self setView:wv];
[wv release];
}
puts the web view as the WebViewController's view
there is no nib as shown above
the didSelect cell method IS CALLED using an NSLog to find out
Everything is initialized and allocated and non-zero
UPDATE:
my did select cell method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Push the web view controller onto the navigaton stack - this implicity
// creates the web view controller's view the first time through
NSLog(#"TOUCHED!");
webViewController = [[WebViewController alloc] init];
if (webViewController == nil) {
NSLog(#"webViewController in nil state");
}
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView] loadRequest:req];
// Set the title of the web view controller's navigation item
[[webViewController navigationItem] setTitle:[entry title]];
}
ALL OF THIS WORKED BEFORE INSERTING TAB BAR CONTROLLER
UPDATE
Where I create the controllers (IN APP DELEGATE):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
[lvc autorelease];
// Create the tabBarController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Make an array containing the two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:vc1, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
// Put the tabBarController's view on the window
[[self window] setRootViewController:tabBarController];
// The window retains tabBarController, we can release our reference
[tabBarController release];
// Show the window
[[self window] makeKeyAndVisible];
return YES;
}
So I really have no idea whats going on here. Also IF YOU COULD PLEASE HELP ME WITH ANOTHER QUESTION! Go to my profile and see the question about how to stop cutoffs/add extra line for text label in uitableviewcell
I don't see the initial UINavigationViewController in your app delegate. In order to use the self.navigationController pushViewController, the view controller needs to be in one of the self.navigationController.viewControllers. Can you modify your code and try the following and see it works for you.
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Create the UINavigationController and put the list view controller as the root view controller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc1];
// Make an array containing the two view controllers and the UINavigationController which has the ListViewController is the first one.
NSArray *viewControllers = [NSArray arrayWithObjects:navController, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
[navController release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
There are several points you have to check, in order to make the push successful.
First, the view controller to be pushed is probably designed and stored in a NIB file. Check how you create it in your code, particularly the NIB file name (assuming you use -(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle). It must be the real NIB filename without the NIB/XIB extension.
Second, is the selection event triggered and the message really sent to the table view delegate ? You could put some logging to ensure that. The table view won't prevent the view controller from being pushed on the navigation stack.
The question isn't really precise on how/where you create that controller, so finally, if none of this works, make the test to alloc/init the controller just before pushing. You might have a better understanding of what is going on.
If the view controller is under the "More" button, then things change a bit.
Here's what worked for me to figure out what navigation controller to use:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
UITabBarController *tabBar = (UITabBarController*) self.window.rootViewController;
UINavigationController* navigationController = (UINavigationController*)self.tabBarController.selectedViewController;
UIViewController* top = nil;
if ([navigationController respondsToSelector:#selector(topViewController)]) {
top = navigationController.topViewController;
}
// the actual current navigation controller depends on whether we are on a view under the More tab
UINavigationController *curNavController;
if (top == nil) { // this implies a view under the More tab
curNavController = tabBar.moreNavigationController;
} else {
curNavController = navigationController;
}
[[LocalNotificationMgr Get] ReceivedNotification:notif navController:curNavController];
}
Basically if the user is on a view under the More tab, the actual current UINavigationController you want to use to push a UIViewController onto is the UITabBarController's moreNavigationController property.
If on a view actually visible on the tab bar itself, use the UITabBarController's selectedViewController property.
NOTE: if you're on the "More screen" itself, you can use either property.
Did you do it in the manner like below??
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(reqList==Nil)
{
reqList = [[RequestList alloc]initWithNibName:#"RequestList" bundle:nil];
}
[self.navigationController pushViewController:reqList animated:YES];
}

How to get rid of EXC_BAD_ACCESS

So, another EXC_BAD_ACCESS topic on StackOverflow, but as I'm new to Objective-C this is still a topic I don't really grasp yet. Even though I have done a lot of research about it already.
The issue is the following. I have a UIScrollView that I have overwritten using a Custom Class (named MultiSelectView). If the user taps this UIScrollView and then I want to open a view that allows him to select some data.
So I have declared a UITapGestureRecognizer that calls the openMultiSelect: method. But on the line [parent.navigationController pushViewController:view animated:YES]; I get a Program received signal: "EXC_BAD_ACCESS". error. Why o why?
- (id) initWithCoder:(NSCoder *) coder {
self = [super initWithCoder: coder];
if (self) {
// Add a Tap Gesture Recognizer to the Scrollview.
// If the user taps the view, it triggers the 'openMultiSelect' method.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(openMultiSelect:)];
[singleTap setNumberOfTapsRequired:1];
[singleTap setNumberOfTouchesRequired:1];
[self addGestureRecognizer:singleTap];
}
return self;
}
- (void)openMultiSelect:(UIGestureRecognizer *)gesture {
//int myViewTag = gesture.view.tag; // now you know which view called
DataSelectView *view = [[DataSelectView alloc] initWithNibName:#"DataSelectView" bundle:[NSBundle mainBundle]];
view.allowMultiSelect = YES;
[parent.navigationController pushViewController:view animated:YES];
[view release];
}
So the parent that you see is a ViewController that contains the tab. Is there a better way to do this? Because for now I have thus a ViewController that contains Tabs. In its activateTab: method I thus create the tab and pass self along. I do the same in the viewDidLoad for that tab to pass the parent to the custom UIScrollView:
- (void) activateTab:(int)index {
... code ...
self.tab_Basic = [[TabBasic alloc] initWithNibName:#"TabBasic" bundle: [NSBundle mainBundle]];
self.tab_Basic.parent = self;
... code ...
}
You should make some change to your callback method. Something like that:
- (void)openMultiSelect:(UIGestureRecognizer *)gesture {
//int myViewTag = gesture.view.tag; // now you know which view called
if(gesture.state == UIGestureRecognizerStateEnded){
DataSelectView *view = [[DataSelectView alloc] initWithNibName:#"DataSelectView" bundle:[NSBundle mainBundle]];
view.allowMultiSelect = YES;
[parent.navigationController pushViewController:view animated:YES];
[view release];
}
}
What you are doing wrong is releasing the object "view" too early, don't release it until the view is popped. That should fix the problem.
- (void)openMultiSelect:(UIGestureRecognizer *)gesture {
//int myViewTag = gesture.view.tag; // now you know which view called
DataSelectView *view = [[DataSelectView alloc] initWithNibName:#"DataSelectView" bundle:[NSBundle mainBundle]];
view.allowMultiSelect = YES;
[parent.navigationController pushViewController:view animated:YES];

Tab bar, reload every time tab is pressed

I am creating an app in which I have five tabs. I need to reload each controller every time when tab is pressed.
Put the code you want to reload, in the view will appear or in view did appear of all the view.
All the best.
Example:
// AppDelegate ( and <UITabBarControllerDelegate> )
// Creation tabbar and controllers
UIViewController* myController1 = [[UIViewController alloc] init] autorelease];
UINavigationController* nav1 = [[[UINavigationController alloc] initWithRootViewController:myController1] autorelease];
UIViewController* myController2 = [[UIViewController alloc] init] autorelease];
UINavigationController* nav2 = [[[UINavigationController alloc] initWithRootViewController:myController2] autorelease];
NSArray *array = [NSArray arrayWithObjects: myController1, myController2, nil];
UITabBarController* tab = [[[UITabBarController alloc] init] autorelease];
tab.viewControllers = array;
tab.delegate = self; // <-- don't forget set delegate for TabBarController
// TabBarController Delegate methods
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
{
// Reload selected VC's view
[viewController.view setNeedsDisplay];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//other codes
[self.tabBarController setDelegate:self]
//other codes
}
// UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if ([viewController respondsToSelector:#selector(reloadDataTemp)]) {
[(YourViewController *)viewController reloadData];
}
}
So write a method to redraw the elements on your page and call it on tab press. I will edit this post if you provide more information on the problem you are facing.
if you are you are using the uitableview use this
[tableview reloaddata];
I hope you are talking about the webview the webview should reload every time a tabbar item is navigated well just implement [webview reload] in the tab bar delegate.
Swift 5
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let vc = self.viewControllers?[1] as? stepVC // ViewController That need to be loaded
vc?.viewDidLoad()
}