UIView subviews don't responde to delegates - iphone

I have following code in viewDidLoad
myViewController = [[UIViewController alloc] initWithNibName:#"myView" bundle:nil] ;
self.myView = myViewController.view;
[self.view addSubview:myView];
This code loads view from myView.nib (I have corresponding view controller m and h files of course). myView view has UITextField and other controls. So far so good - I can see all my controls on the screen.
The problem however is that even though I set a delegate for UITextField to be File's Owner (which is myView) and I implement UITextFieldDelegate in myView.m, delegate methods are never fired!
This does NOT happen if I add UITextField to the original view (created by the XCode as default template). Why is this happening?
The reason I need to useSubview because in actual code will layer view to the UIScrollView so I can pan and zoom.
THanks!

My first question to your question is, "is there a reason to use UIViewController to load your NIB file?".
It appears that you're "throwing away" the UIViewController and merely using it for its ability to load a NIB file. I'd stop that first, as that may help you debug this issue. Use:
self.myView = (UIView*)[NSBundle loadNibNamed:#"myView"];
The second part I'd question is that you say "File's Owner" -- because you're using a separate UIViewController, you may have it set to call back to your UIViewController, not the code that you mean to callback to. Maybe you could tell us a little about the setup of the XIB file?

Related

UIView presented with Black screen, fix?

I call a View to be presented with the following code:
#import "infoView.h"
...
infoView *viewInfo = [[infoView alloc] initWithNibName:nil bundle:nil];
viewInfo.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewInfo animated:YES];
But when it is presented in run-time the view that is loaded turns out black.
Currently I am using storyboard, but I need to use this code, for it is a lot more efficient in my case, because I am dealing with multiple views!
It works fine if I connect it via StoryBoard.
I should be seeing 2 labels, 1 UITextView, and 2 UIButton.
The view was created using StoryBoard, when the .m and .h files for the view where created I did not add a .xib for it. And also it is linked through the "Custom Class" section in StoryBoard.
Thanks, hope someone can help!
It's generally pretty bad form to mock people who are taking the time and effort to help you.
Naming is important it makes your code easier to work with and allows other people to use it. Not following the conventions for the language you are working in is dangerous and means that your code is not compatible with other developers as things are interpreted differently.
If you look at the docuemntation for UIViewController you'll see this note in the initWithNibName:bundle: method description
If your app uses a storyboard to define a view controller and its associated views, your app never initializes objects of that class directly. Instead, view controllers are either instantiated by the storyboard—either automatically by iOS when a segue is triggered or programmatically when your app calls the storyboard object’s instantiateViewControllerWithIdentifier: method. When instantiating a view controller from a storyboard, iOS initializes the new view controller by calling its initWithCoder: method instead. iOS automatically sets the nibName property to a nib file stored inside the storyboard.
Therefore you are instantiating your controller wrong, the storyboard should be instantiating it. Which is done like this (naming corrected)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle bundleForClass:[self class]]];
InfoViewController *infoViewController = [storyboard instantiateViewControllerWithIdentifier:#"InfoViewController"];
infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self infoViewController animated:YES];
Side note
infoView is a bad name for the class not only because you didn't start with a capital but also because it's completely deceiving. Anyone reading this would assume that InfoView is a subclass of UIView not UIViewController.

I can make UINavigationController load only at 2nd level, not at Root View Controller

I tried looking for a similar problem but I could not find a similar question.
I am loading a UINavigationController in a UIView which is not (as in most examples) the MainWindow.
I created one new .xib called DocumentsViewController which is subclass of UIView (it has the related .m and .h files). And I created a DocumentsRootViewController.xib, which is a subclass of UITableViewController, which is supposed to be the UINavigationController's RootViewController.
I moved to DocumentsViewController and added a UINavigationController object in Interface Builder. Then I went to code, and added it as in IBOutlet, and connected it to the object.
In the ViewDidLoad, I execute the following lines:
DocumentsRootViewController *rootViewController = [[[DocumentsRootViewController alloc] init] autorelease];
rootViewController.title = #"Documents";
[navigationControllerDocuments initWithRootViewController:rootViewController];
[self.view addSubview:navigationControllerDocuments.view];
It shows the table as intended, but it shows a "Back" button to the "Root View Controller" (as in picture below).
Why? Shouldn't it already know that the rootviewcontroller has been set?
Thank you in advance to the ones that clarify this doubt
Giovanni
When you add the UINavigationController via the Nib it actually creates an instance of a UINavigationController inside the nib file with a default RootViewController set (of type UIViewController) and with a default title of RootViewController.
When you load the nib, this object is being created as part of loading the nib (i.e when you initialise DocumentsViewController) - so the navigationControllerDocuments outlet is already initialised as a UINavigationController with the default ViewController already set on it.
What I think is happening is when you call 'initWithRootViewController' - you are calling this on an already initialised object - so it is running the initialisation code again - pushing the second view controller (the DocumentRootViewController) onto the stack, but the default one that was created in the nib is already there.
What you should probably do is forget about creating one in the nib and initialise the whole thing programatically.
i.e. where you do:
[navigationControllerDocuments initWithRootViewController:rootViewController];
I suggest that you do an alloc and init instead:
[[navigationControllerDocuments alloc] initWithRootViewController:rootViewController];
Since you are doing this you really don't need to have the navigation controller added to the nib so if this works you should remove it from the nib since you are replacing it with this one in code.

Reference the class that a subview was added from

I'm adding a subview to my primary iPad UIViewController, and within that subview I need to reference said view controller in order to play a video using that controller.
Can anyone help me out with the way that should be done, and possibly a code example?
Thank you in advance.
Regards,
Ed
EDIT (A LITTLE BIT MORE INFO):
This subview is a view from a uiviewcontroller class that is designed for the iPhone. It's a table that loads a video when a row is pressed. The movieplayer loads the video within the referenced viewcontroller (which is why I want to reference the iPad view controller from within the subview). The view is basically used within an iPad app in it's same form.
This sounds like an architecture problem. It's not up to your view to tell something to play a sound. That's a controller's job. It's up to your view to tell "someone" that it was touched, or slid, or whatever the user has done. "Someone" (who is watching) will then perform the correct response to that.
To do this, your view should generally take a target, and possibly and action. Look at how UIControl (for example, UIButton) informs other objects that it has been activated. The observer (controller) then reacts accordingly.
EDIT
The view should not load a video. A view controller should load the video and install it into the correct view. The only job the view has is to tell its view controller that it has been pressed. UITableView handles this automatically with the UITableViewDelegate method tableView:didSelectRowAtIndexPath:. If you're not using a UITableView, you should still follow this pattern. The view accepts has a delegate and tells the delegate (controller) that something was selected. Then the controller updates the views with the new data.
You probably already have the main view living in a property of your application delegate (it is commonly assigned via the application's .xib file, look in the app delegate's applicationDidFinishLaunching: method, where it adds the main view as a subview to the window, something like:
[window addSubview:primaryController.view];
[window makeKeyAndVisible];
).
So anywhere in your app where you need to access the main view, you can do:
[(MyAppDelegateType*)([UIApplication sharedApplication].delegate).primaryController somePrimaryControllerMethod];
Edit: while this will work, I agree with Rob Napier that this isn't the best way to do it, architecture-wise.
You could just use [yourSubview superview] to get the superview.
Can't you just add a property to the view like this:
#property (nonatomic, assign) UIViewController *parentViewController;
And on initialization of the view (from within the UIViewController), set the property:
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
customView.parentViewController = self;
And from then on you should be able to call the parentViewController from within the view.
Edit: Rob Napier has a good point, it's probably a better idea to set a target and selector from within the view instead of a view controller. This way you should be able to hook up methods directly with the view. The properties would look like this:
#property (nonatomic assign) id target;
#property (nonatmic, assign) SEL selector;
And perhaps add a designated initializer to your view:
- (id)initWithFrame:(CGRect)aFrame target:(id)aTarget selector:(SEL)aSelector
{
self = [super initWithFrame:aFrame];
if (self)
{
self.target = aTarget;
self.selector = aSelector;
}
return self;
}

UIViewTableCell didSelectRowAtIndexPath is calling but not pushing a view controller

so im having a UIViewController view with a UITableView.
So the UIViewController class name is SelectionScreen.
The UITableView class name is SelectionScreenTable.
Picture:
http://img717.imageshack.us/i/screenshot20100609atpm0.png/
I have declared a UITableView *selectionTable in SelectionScreen class and connected it to the xib file of the SelectionScreen
what the problem is , is that when i click a row in the table,it stays selected as highlighted blue, it calls the didSelectRowAtIndexPath (checked with NSLog) but not pushing a new view which is called(GraphView).
This is the code which i use to call the new controller WHICH WORKS with a normal button
GraphView *aSelectionScreenViewController = [[GraphView alloc]
initWithNibName:#"GraphView"
bundle:nil];
[self presentModalViewController:aSelectionScreenViewController animated: YES];
[aSelectionScreenViewController release];
I searched around and found that I need to set a delegate for the table in the UITableView class itself on the viewload
tableview.delegate = self;
or
self.tableview.delegate = self;
But it was not working. the controller was still not being pushed, and yes i have checked the controller is not nil as i tried it with a simple button.
So i was thinking whether i should set the delegate of the UITableView at the UIViewController instead, so i tried this code
selectionTable.delegate = selectionTable.self;
but obviously it did not work =\, it messed up the whole UITableView and caused all the cells to be its predefined settings.
So does anybody have any idea on how i can get it to work.
It's a bit hard to get the full picture here, but I can try some hints.
The outlets seem to be correctly connected from the screenshot, although Selection Screen Table could probably be called Selection Screen Table Controller and the class name should be SelectionScreenTableController for less confusion.
I think the problem could be that the method presentModalViewController: must be called on an active view controller to work.
From what I can tell you have three view controllers, a SelectionScreenTableController, a GraphViewController, and then there must also be some kind of main controller, probably SelectionScreenController.
The SelectionScreenController is the active view controller, so that must be the one to have sent the presentModalViewController: message.
There are several ways you could solve this. The quick fix would be to make an outlet in SelectionScreenTableController called selectionScreenController and link it to File's Owner in the nib file (assuming your SelectionScreen class is in fact a view controller), then call:
[selectionScreenController
presentModalViewController:aSelectionScreenViewController
animated: YES];
instead in your current listing of didSelectRowAtIndexPath:
Hey guys, i solved it, in the screenshot
http://img717.imageshack.us/i/screenshot20100609atpm0.png/
The SelectionScreenTable controller in the XIB of SelectionScreen, the view outlet was not connected to the XIB in the SelectionScreen XIB, so i guess it wasn't properly configured.
i solved it instead of using
presentModalViewController.
i used an animation to bring in the view instead
More info in the link below
http://www.iphonedevsdk.com/forum/iphone-sdk-development/13427-uiview-slide-transition.html

UIViewController presentModalViewController: animated: doing nothing?

I recently started a project, using Apple's Utility Application example project. In the example project, there's an info button that shows an instance of FlipSideView. If you know the Weather.app, you know what the button acts like.
I then changed the MainWindow.xib to contain a scrollview in the middle of the window and a page-control view at the bottom of the window (again, like the Weather.app). The scrollview gets filled with instances of MainView. When I then clicked the info button, the FlipSideView would show, but only in the area that was previously filled by the MainView instance – this means that the page-control view on the bottom of the page still showed when the FlipSideView instance got loaded.
So, I thought that I would simply add a UIViewController for the top-most window, which is the one declared inside the AppDelegate created along side with the project. So, I created a subclass of UIViewController, put an instance of it inside MainWindow.xib and connected it's view outlet to the UIWindow declared as window inside the app delegate. I also changed the button's action, so that it know sends a message to the MainWindowController instance. The message does get sent (I checked with NSLog() statements), but the FlipSideView doesn't get shown. Here's the relevant (?) code:
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
Why's this not working from inside of MainWindowController, but the exact same code is working from inside of MainViewController? I've uploaded the entire project here for you to be able to see the whole thing.
Thanks for help!
-- Ry
EDIT: I think it might be related to me attaching the UIViewController's view outlet to an UIWindow instance. I now connect it to a UIView, and it's working perfectly well.
For the record, the answer has been added in the question. Ryyst said:
I think it might be related to me
attaching the UIViewController's view
outlet to an UIWindow instance. I now
connect it to a UIView, and it's
working perfectly well.