iPad:Popover sample to iOS5 - iphone

I am developing an app which will be used on both iPhone and iPad.
Today I've found that I should use Popover for iPad instead of PickerView on an action sheet.
I am trying to use a sample app use it on iOS5, but I have been getting an error;
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'-[UITableViewController loadView] loaded the "2-view-5" nib but didn't get a UITableView.'
*** First throw call stack:
Do you know what exactly i need to do to fix that?
And, do you have any recommendation of popover examples for iOS5?
UYLMasterViewController.m
#import "UYLMasterViewController.h"
#import "UYLDetailViewController.h"
#implementation UYLMasterViewController
#synthesize detailViewController = _detailViewController;
#pragma mark -
#pragma mark === View Management ===
#pragma mark -
- (void)viewDidUnload
{
[super viewDidUnload];
self.detailViewController = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark -
#pragma mark === Table View Delegates ===
#pragma mark -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [NSString stringWithFormat:#"Item %u", row+1];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger item = [indexPath row] +1;
NSNumber *detailItem = [NSNumber numberWithInteger:item];
if (self.detailViewController)
{
self.detailViewController.detailItem = detailItem;
}
}
#end

If you didn't modify anything from the sample app, this is quite strange.
Anyway, I usually get this error when I forgot to set an IBOutlet connection from the table to the controller UITableViewController.
It is likely that you delete it by mistake, or Xcode lost its connection for some reason (it happens).
See if UYLMasterViewController.h is a UITableViewController. If yes, then the UITableView must be the first view in nib file, directly connected to the 'view' IBOutlet property of the controller.
Otherwise if UITableView is inside a UIView then you get the exact error you mentioned.
A probable solution, if UITableView is not the main view, would be to set UYLMasterViewController as a normal UIViewController and give it all the delegate accessor, then drag a connection from the UITableView to the controller, you will see that you have two options delegate and datasource, you need both.

Related

Set UITableView Delegate and DataSource

This is my problem:
I have this small UITableView in my storyboard:
And this is my code:
SmallTableViewController.h
#import <UIKit/UIKit.h>
#import "SmallTable.h"
#interface SmallViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITableView *myTable;
#end
SmallTableViewController.m
#import "SmallViewController.h"
#interface SmallViewController ()
#end
#implementation SmallViewController
#synthesize myTable = _myTable;
- (void)viewDidLoad
{
SmallTable *myTableDelegate = [[SmallTable alloc] init];
[super viewDidLoad];
[self.myTable setDelegate:myTableDelegate];
[self.myTable setDataSource:myTableDelegate];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Now as you can see, I want to set an instance called myTableDelegate as Delegate and DataSource of myTable.
This is the Source of SmallTable class.
SmallTable.h
#import <Foundation/Foundation.h>
#interface SmallTable : NSObject <UITableViewDelegate , UITableViewDataSource>
#end
SmallTable.m
#implementation SmallTable
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.textLabel.text = #"Hello there!";
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Row pressed!!");
}
#end
I implemented all the UITableViewDelegate and UITableViewDataSource method that the app need. Why it just crash before the view appear??
Thanks!!
rickster is right. But I guess you need to use a strong qualifier for your property since at the end of your viewDidLoad method the object will be deallocated anyway.
#property (strong,nonatomic) SmallTable *delegate;
// inside viewDidload
[super viewDidLoad];
self.delegate = [[SmallTable alloc] init];
[self.myTable setDelegate:myTableDelegate];
[self.myTable setDataSource:myTableDelegate];
But is there any reason to use a separated object (data source and delegate) for your table? Why don't you set SmallViewController as both the source and the delegate for your table?
In addition you are not creating the cell in the correct way. These lines do nothing:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.textLabel.text = #"Hello there!";
dequeueReusableCellWithIdentifier simply retrieves from the table "cache" a cell that has already created and that can be reused (this to avoid memory consumption) but you haven't created any.
Where are you doing alloc-init? Do this instead:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = // alloc-init here
}
// Configure the cell...
cell.textLabel.text = #"Hello there!";
Furthermore say to numberOfSectionsInTableView to return 1 instead of 0:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
Presumably you're using ARC? Your myTableDelegate is only referenced in a local variable in viewDidLoad -- once that method ends, it's deallocated. (In the delegate/datasource pattern, objects do not own their delegates, so the table view's references back to your object are weak.) I wouldn't expect that alone to cause a crash, but it's likely key to your problem.
setDelegate will not retain the delegate.
And
numberOfSectionsInTableView method has to return 1 instead of 0;
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
Number of sections should be set at least one
The delegate of an UITableView object must adopt the UITableViewDelegate protocol. Optional methods of the protocol allow the delegate to manage selections, configure section headings and footers, help to delete methods.


iPhone: UITableView, didSelectRowAtIndexPath called several times

I have UITableView...when user tap on row, another screen is opened. The problem is, that sometimes, I tap once, but didSelectRowAtIndexPath calls several times. How to prevent that ?
The one case how to reproduce that situation is (you even can try to reproduce that on native iPhone settings):
Tap one row but do not release finger
SLIDE few next rows from left to right or from right to left (not just tap, you should slide) next few rows in different order by other hand
Release finger
You will see that blue selection is on several rows, and what screen will be opened is random
UPDATE:
In didSelectRow I just started new controller, where in viewDidLoad synchronization begin.
And if to reproduce my scenario step by step, than synch can be started several times
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SecondViewController *secondViewController =
[SecondViewController alloc] init];
[self.navigationController
pushViewController:secondViewController animated:YES];
[secondViewController release];
}
Yes, I find the same situation.
Tap one row but do not release finger.
Keep pressing and moving the finger slightly until the row deselected.
Keep the first finger pressing, and tap the screen some times by another finger.
Release all fingers.
Then you can see didSelectRowAtIndexPath method called several times.
I created a new project for test it, and just used the following code. It was reproduced in every times.
So I think it is a bug of iOS SDK !
#import "SPViewController.h"
#interface SPViewController ()
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation SPViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 30;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"Test Cell %d", indexPath.row];
return cell;
}
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 66;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"%s %#", __FUNCTION__, indexPath);
}
#end

UITableView error

ViewController.m
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
return cell;
}
ViewController.h
#interface PSLEViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
IBOutlet UITableView *highScoreTable;
}
#property(retain,nonatomic) UITableView *highScoreTable;
Error:
2010-12-04 02:20:15.541 PSLE[14369:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[PSLEViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x3b13080'
2010-12-04 02:20:15.542 PSLE[14369:207] Stack: (
Theres nothing wrong with that code. There may be some other underlying issues, maybe in a XIB. Are you sure the highScoreTable is connected?
Can you check the dataSource and delegate of UITableView in -(void)viewDidLoad?
They should not be nil after loaded from nib.
hai FYI are you allocate the tableView properly? check it out please
example highScoreTable = [[UITableView alloc]init];

iPhone: UITableView, Dragging Table Contents Causes Crash

I'm new to iPhone application development. I'm trying to understand how to use UITableView.
I'm wrote simple code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1 ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
cell.textLabel.text = #"Hello";
return cell;
}
UITable shows content, but if i'm drag table contents my application terminates. You can see video: http://www.youtube.com/watch?v=TucTVJVhSD0
I tried to everything with array:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1 ;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [hello count] ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
cell.textLabel.text = [hello objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSLog(#"Selected") ;
}
- (void) awakeFromNib
{
hello = [[NSArray alloc] initWithObjects:#"hello", #"world", #"end", nil];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
Content is shown and if I'm selecting item I'm getting:
[Session started at 2010-03-16 19:21:48 +0200.]
2010-03-16 19:21:52.295 ViewTest[1775:207] *** -[ViewTestViewController respondsToSelector:]: message sent to deallocated instance 0x3911ec0
I'm total new to iPhone programming. And as I see everything I do - I'm just getting application terminated ..
Your table view code looks fine. Did you implement any other delegate methods in the ViewTestViewController?
Try running the application in the debugger. When it crashes, look at the stack trace. It should give a better hint.
(1) I think you may have released your tableview controller instance and killed it while it was still in use so that when the tableview sends it one of its delegate or datasource messages it crashes.
(2) Alternatively, the error message says that you are attempting to send the respondsToSelector: message to an instance of ViewTestViewController when you should be sending it to the class. (-[ViewTestViewController respondsToSelector:] vs + [ViewTestViewController respondsToSelector:] the "-" and "+" make all the difference.)
So, somewhere in your code, probably your app delegate, you've got code that says:
ViewTestViewController *myTableViewController= //..however you setup the controller
[myTableViewController respondsToSelector:#selector(someMethod)];
...when you should have...
[ViewTestViewController respondsToSelector:#selector(someMethod)];
I think (1) the most likely.
Thanks to all. I found problem. I found i haven't connected viewController IBOutlet with App Delegate. But why View was shown ?
#interface ViewTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewTestViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ViewTestViewController *viewController;

iPhone: didSelectRowAtIndexPath not invoked

I know this issue being mentioned before, but resolutions there didn't apply. I'm having a UINavigationController with an embedded UITableViewController set up using IB. In IB the UITableView's delegate and dataSource are both set to my derivation of UITableViewController. This class has been added using XCode's templates for UITableViewController classes. There is no custom UITableViewCell and the table view is using default plain style with single title, only.
Well, in simulator the list is rendered properly, with two elements provided by dataSource, so dataSource is linked properly. If I remove the outlet link for dataSource in IB, an empty table is rendered instead.
As soon as I tap on one of these two items, it is flashing blue and the GDB encounters interruption in __forwarding__ in scope of a UITableView::_selectRowAtIndexPath. It's not reaching breakpoint set in my non-empty method didSelectRowIndexPath. I checked the arguments and method's name to exclude typos resulting in different selector.
I recently didn't succeed in whether delegate is set properly, but as it is set equivalently to dataSource which is getting two elements from the same class, I expect it to be set properly. So, what's wrong?
I'm running iPhone/iPad SDK 3.1.2 ... but tried with iPhone SDK 3.1 in simulator as well.
EDIT: This is the code of my UITableViewController derivation:
#import "LocalBrowserListController.h"
#import "InstrumentDescriptor.h"
#implementation LocalBrowserListController
- (void)viewDidLoad {
[super viewDidLoad];
[self listLocalInstruments];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [entries count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if ( ( [entries count] > 0 ) && ( [indexPath length] > 0 ) )
cell.textLabel.text = [[[entries objectAtIndex:[indexPath indexAtPosition:[indexPath length] - 1]] label] retain];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( ( [entries count] > 0 ) && ( [indexPath length] > 0 ) )
{
...
}
}
- (void)dealloc {
[super dealloc];
}
- (void) listLocalInstruments {
NSMutableArray *result = [NSMutableArray arrayWithCapacity:10];
[result addObject:[InstrumentDescriptor descriptorOn:[[NSBundle mainBundle] pathForResource:#"example" ofType:#"idl"] withLabel:#"Default 1"]];
[result addObject:[InstrumentDescriptor descriptorOn:[[NSBundle mainBundle] pathForResource:#"example" ofType:#"xml"] withLabel:#"Default 2"]];
[entries release];
entries = [[NSArray alloc] initWithArray:result];
}
#end
Apple's documentation says that didSelectRowAtIndexPath:index will not be invoked when selectRowAtIndexPath:indexPath is called. To call didSelectRowAtIndexPath use the following:
[[tableView delegate] tableView:tableView didSelectRowAtIndexPath:index];
This basically invokes the delegate.
Try didSelectRowAtIndexPath. The selector as you typed it was missing the word "At" in the selector name.
Are you calling
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition
If you are, then that will not call the delegate methods tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: You will have to call them yourself.
See the UITableView Reference.
For what it's worth I have not seen any difference in the table view behavior in the 3.0.x or 3.1.x releases.
Well, after trying to retain the delegate of UITableView instance just to check for leaking memory with success, I investigated on that issue and stumbled over some tutorials on how to combine views and controllers using detached NIBs as I do here. This tutorial finally made me do the trick:
Combining View Controllers
Focusing on error in detail there were two UITableViewControllers ... one in main NIB set as root controller for a tabbed Navigation controller and a second time in referenced NIB used to provide a raw UITableView instance instead.