No visible #interface for 'UIWebView' declares the selector 'initWithNibName:bundle:' - interface

First I want to say you that I'm totally new in Xcode so I'm a Newbie.
Then I also want to say you that I'm not able to speak English perfect...I'm learning it.
So, my problem is that I get the following error:
No visible #interface for 'UIWebView' declares the selector 'initWithNibName:bundle:'
I don't know why, I've already searched in many other forums (and this, too) for this, but the solutions there didn't help me.
I want to create a Table View that loads an UIWebView if I push a row.
That's my Code:
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.mehrWebView == nil)
{
UIWebView *temp = [[UIWebView alloc] initWithNibName:#"MyWebView" bundle:[NSBundle mainBundle]];
self.mehrWebView = temp;
}
[self.navigationController pushViewController:mehrWebView animated:YES];
}
I'm frustrated, I don't know how to continue.
I hope you can help me with my problem.
Thanks & Best Regards

The initWithNibName:bundle: method is an initializer of UIViewController classes, not UIView classes. On the other hand, UIWebView is a UIView class, so Xcode correctly tells you that UIWebView lacks the initWithNibName:bundle: method.
Moreover, you cannot push views onto the navigation controller's stack. You need to replace UIWebView with the type of the controller of the #"MyWebView" nib to make it work.

Related

didSelectRowAtIndexPath method does not load new View in iOS app code is inside

I have my first and normal view controller with a UITableView in it. The items that need to be displayed in those rows work perfectly.
Now comes the issue, if the user selects a row, I want a new view opened.
This view is called SecondViewController. so I have the .h, .m and .xib file named that way and it is of the UIViewController class.
I am using a CustomCell for the tableview could this be the issue?
I have #imported everything normally, and this is the code I am using in the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
}
What on earth am I doing wrong? I have been looking at questions here for hours but nothing seems to be working.
Are you sure that self.navigationController is not nil?
Try to log it, From your code your problem is probably that, your self.navigationController is nil.
This class is pushed from another or are you starting the navigation in this class? If you are starting it in this class, this is your issue, you need to call the navigation that you created and not the one that is supposed to be with your viewcontroller.

How to call a detail view from a table view within a Storyboard

I have following problem.
I have created a tab based Application with three Views and Viewcontroller.
FirstView(Start screen stuff), SecondView (Detailpage), ThirdView (Table for listing items).
(Connections from storyboard were set automatically).
In the third view a table is integrated and the content is displayed fine.
Now I would like to call the SecondView , when a row in the table is selected.
I also tried to add a forth View , outside the tabBar Controller, to get the Detailview, but this also did not help.
I have tried several tutorials and forum tips, but cannot get it working.
The class is set to the right ViewController, the identifier is set to detail.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
[self.navigationController pushViewController:detail animated:YES];
detail.label1.text = #"It is working";
}
When clicking on the row, it becomes blue, but nothing happens. No error Message , nothing.
Hope that you can help :-)
OK, I have tried to "optimize" my design.
Still have the tab based Views, but when clicking on a row in the table, a new (not linked in Storyboard) view should appear to display the details of the selected quote.
I have created a view in the storyboard and called it "detailzitat"
I have created a DetailViewController.h/m as UIViewcontroller class
I have set the custom class to DetailViewController
I import the DetailViewController.h in the ThirdViewController.h
I have modified the didSelectRowAtIndexPath method in ThirdViewController.h accordingly.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC = [self.storyboard instantiateViewControllerWithIdentifier:#"detailzitat"];
[self.navigationController pushViewController:detailVC animated:YES];
}
and my DetailViewController.m looks like
#import "DetailViewController.h"
#implementation DetailViewController
#synthesize label1, labeltext;
- (void)viewDidLoad
{
[super viewDidLoad];
labeltext=#"JUHU";
label1.text=labeltext;
}
But again, nothing happens, besides the row gets blue.
I do not understand. If I am using this code in a Non-Storyboard project, it is working.
What am I doing wrong ? Is there any tutorial for this combination within Storyboards ? Have not found one for this approach yet.
Try to learn from the different tutorials on the web, but the biggest problem is, most ones are not for iOS5 and I am not so good to transfer then.
Hope to get some hints :-)
You might want to think about your design. If I am understanding your description correctly, the user will be on the third tab, tap on a row in a table, and then you will be switching them back to the second tab. A navigation controller might be a more natural, less confusing, choice there.
But in any case, something like this will work sometimes:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC = [self.tabBarController.viewControllers objectAtIndex:1];
detailVC.label1.text = #"It is working"; // <- this will not work consistently!
self.tabBarController.selectedViewController = detailVC;
}
The problem with this is that while the user is on that third tab, it's possible that the second tab view controller's view is unloaded (due to memory pressure for example).
It's also possible the user went from tab 1 to tab 3 immediately and therefore the 2nd tab's view isn't even loaded yet at all. (To even test the above code you would have to select tab 2 and then tab 3.)
If the second tab's view hierarchy is not loaded, the label1 property will be nil, and so this will not work. A better strategy would be to create a new #property of type NSString* on the DetailViewController. And set that property instead of trying to set the label1 directly.
Then in your viewWillAppear: for the DetailViewController you can update your labels as needed. At that point of course you can be sure that label1 is loaded and connected to the correct UILabel.
I hope that helps.
I think problem is at self.navigationController. If your view is not inside the navigation controller this will not work. So what you do is create a new navigation controller object there and then use it to show your detail view.

Question about the mechanics of iPhone view controllers (i.e., explain why this crashes)

I am pretty new to iPhone programming, and was playing around with an app yesterday trying different scenarios with view controllers and nib files. So, I started a new app with a FirstViewController (FVC for short) and an FVC.xib.
I layed out a quick view in FVC.xib and ran the app - view displays, great.
I now wanted to have a second view I could add on top of the main view. So I went ahead and created SecondViewController.xib (SVC) but did not create the .m and .h files. I went about trying to load both these views from the same view controller, and here is where my question lies:
I created a button in FVC.xib and created an IBAction like this:
- (IBAction)loadSVC {
FirstViewController *viewController = [[FirstViewController alloc] initWithNibName:#"SecondViewController" bundle:[NSBundle mainBundle]];
secondView = viewcontroller.view;
[viewController release];
[self.view addSubView:secondView];
}
So this works great and adds the contents of SVC.xib, but when I try and remove that view from the superview, the app crashes:
[secondView removeFromSuperview];
If I actually create a view controller for SVC, use that to instantiate my view in FVC, and move the remove code to the SVC:
[self.view removeFromSuperview];
Everything works. My question - I kind of get why my first method crashes, but I was hoping someone could explain why and what goes on behind the scenes. I'm still a noob with object oriented programming, so what is actually happening in my first case where I create a new instance of FirstViewController and add its view to self.view? Why can't I release it (I assume because the original view is associated with FirstViewController, and when I create a new instance with the second xib it messes everything up) - I'd love a more technical explanation as to what is happening...
Thanks much!!
EDIT to add more info in response to Nick's reply below
Nick - so your answer did clear my thinking a bit in regards to the retain count, etc... I did another test app trying to get this working from a single view controller - think, for example, that I wanted to display an Alert or Welcome message to the user (I know in a real app there are different methods to accomplish this, but this is more of a learning experience) -- so I have my main view # MainViewController and layout my alert message in a xib called alert.xib -- so there is no logic behind the alert message, no reason for it to have a view controller that I can see, my end goal being loading/unloading this on top of my main view from the main view's view controller (or understanding why it is impossible)
I tried this using instance variables as you recommended:
In MainViewController.h:
#import <UIKit/UIKit.h>
UIViewController *secondController;
UIView *secondView;
#interface MainViewController : UIViewController {
}
#property(nonatomic, retain) UIViewController *secondController;
#property(nonatomic, retain) UIView *secondView;
- (IBAction)loadSecond;
- (IBAction)removeSecond;
#end
In MainViewController.m:
#import "MainViewController.h"
#implementation MainViewController
#synthesize secondController, secondView;
- (IBAction)loadSecond {
secondController = [[MainViewController alloc] initWithNibName:#"alert" bundle:[NSBundle mainBundle]];
secondView = secondController.view;
[self.view addSubview:secondView];
}
- (IBAction)removeSecond {
//I've tried a number of things here, like [secondView removeFromSuperview];, [self.secondView removeFromSuperview];, [secondController.view removeFromSuperview];
}
- (void)dealloc {
[secondController release];
[secondView release];
[super dealloc];
}
So - this works to load the alert view, but the removeSecond button does nothing (I did use NSLog to verify the removeSecond method is fired) - why?
Second, and most importantly - is this even possible, or is it horrible practice? Should every nib/view I am manipulating have their own view controller? Am I wrong to think I could just make a new instance of MainViewController and use it to display and remove this no-functionality, very temporary view? (And yes, I realize I could easily create this view programatically or accomplish the end goal in many different ways which would be easier, but I'm trying to really learn this stuff and I think figuring this out will help...
Thanks for the help!
You created a view controller
You accessed its view which caused controller to create the view and call the delegates (i.e. viewDidLoad)
Controller returns the view that you asked for
Now you add the view as a subview which increases its retain count
Controller is released and it releases the view, BUT since view's retain count was increased the view is still there
You try to remove the view, it is unloaded and delegates are to be called (e.g. viewDidUnload), however that messes up since the controller who created the view is released and that piece of memory is... smth else :)
That's why the first method doesn't work.
The second method is NOT correct either but it works because:
You remove controller's view from superview but since controller itself is not released (you didn't call [self release] or anything like that, not saying that you should :), just an example), then the view didn't reach 0 (zero) retain count and is still there - which means its subviews aren't removed
The proper way to do it is to save the reference to the controller as an instance variable (usually declare a synthesized property), and release it only when you are done with the view, making sure that the view is removed from superview before hand. The default templete for a View Based App shows how view controller should be managed
Hope this helps to understand why both methods behave differently
Based on your clarifications, you don't need secondView property or iVar. Also in your loadSecond instead of secontController = bla you need self.secondController = bla, otherwise you simply assign reference to the iVar instead of going through the setter.
Yes, it's possible to load subviews/other resources from a nib without having a dedicated controller
This is how you do it (one of the approaches):
UIView *result = nil;
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:#"MyNibName" owner:owner options:nil];
for ( id o in bundle ) {
if ( [o isKindOfClass:[UIView class]] ) {
result = (UIView *)o;
break;
}
}
Here the result will contain the first UIView in MyNibName. You can use other criteria to find out whether you got the view you wanted (tags, types...)

iOS / Xcode 4: View won't load

This is really frustrating as I've tinkered with previous versions of Xcode and have done this before but playing around with a new app now, it's not working for some reason.
I have the app open to a UITableView and want it to load to a detail UIView once I select a cell. However, when I choose a cell in the iPhone simulator, it just highlights the cell blue and doesn't load the view.
Here is the code I'm using the the RootViewController:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WorkoutViewController *workoutViewController;
workoutViewController = [[WorkoutViewController alloc] initWithNibName:#"WorkoutViewController" bundle:nil];
workoutViewController.workoutName = [workouts objectAtIndex:indexPath.row];
[self.navigationController pushViewController:workoutViewController animated:YES];
[workoutViewController release];
workoutViewController = nil;
I have the view linked to the File Owner in the WorkoutViewController.xib file. When I put in a breakpoint at #implementation WorkoutViewController, it does get to that breakpoint but it goes to the #synthesize line and then jumps right back out to [self.navigationController ...etc]; and never returns back to the WorkoutViewController.m file.
I would guess that you didn't set the ViewController to be the TableView's delegate. To check, open your ViewController xib-file and rightclick FilesOwner. Under Referencing Outlet you would usually have both delegate and data source" connected to your TableView. If that is not the case, drag New Referencing Outlet to your TableView.
If I'm wrong and they are all connected, you might want put a breakpoint at the beginning of your didSelectRowAtIndexPath method. Does the debugger stop there, once you select a row?
It might also be worth mentioning that a breakpoint at #implementation usually doesn't make much sense, you would rather want to place it in a method like init. Also, even though you are using Xcode 4 now, this is unlikely to be the cause of your problem, it looks more like an implementation issue.
Hope this helps, if you need further help just let me know!
Doh! Problem resolved. I had forgotten to actually put the RootViewController into a navigation controller on the MainWindow.xib. Appreciate the responses.

Trying to understand NavigationController retain count for ViewControllers on its stack

I have an UITableViewController as the rootViewController for my navigatorController.
When I press a table cell I do the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MessageHistory *msg = (MessageHistory *)[[self fetchedResultsController]objectAtIndexPath:indexPath];
ConversationViewController *chatController = [[ConversationViewController alloc]initWithNibName:#"ConversationView" bundle:nil andUser:msg.user];
[self.navigationController pushViewController:chatController animated:YES];
[chatController release];
But when I'm returning from the chatController (using the back button on the navbar) I get “EXC_BAD_ACCESS”
commenting
//[chatController release];
solves the problem. How? I thought when pushing to the navigationController adds a retain count and when pop from it release it?
Also I believe if I'm not including the release after pushing to the navcontroller I'm generating a leak.
Any idea what's happening here?
I've had this problem a few times, and almost went crazy trying to find the error.
In my case, I had a UIWebView in my second view with the UIViewController set as it's delegate. In my UIViewController dealloc method, I forgot to put webView.delegate = nil.
When the second UIViewController was popped and thus deallocated, the UIWebView was sending a message to it's delegate (the second UIViewController, which didn't exist anymore).
Don't know if this applies to you, but I spend days searching for this error, so perhaps it is of any help.