i am new to iphone ,my question is in one view i placed a tableview and display some data on that view,i want to add another view(same view to all cell) when select cell(suppose select first cell view will display and newly add view is used to delet that cell information based on cell index)please tell me how to display view.
In the didSelectRowAtIndexPath method in your TableView class; that is where you deal with the selected row. Here is some code that pushes a webViewController onto the screen :
webViewController = [[WebViewController alloc] init];
WebViewController *wvc = [[WebViewController alloc] init];
NSMutableArray *temp = [eventsDict objectForKey:[datesArray objectAtIndex:[indexPath section]]];
EventObject *tempEvent = [temp objectAtIndex:[indexPath row]];
NSString *eventURL = [tempEvent eventLink];
[wvc setEventWebsite:eventURL];
[self setWebViewController:wvc];
[[self navigationController] pushViewController:webViewController animated:YES];
[wvc release];
[webViewController release];
Basically I have an array of Events, it gets the event you touched using [indexPath row], gets the URL within that Event object, passes it to the webViewController, then it pushes the webViewController onto the screen loading the appropriate link. Hope this helps
If you want to display the same view for all cells - simply create one UIView object and change frame in didSelectRowAtIndexPath delegate method. It will something like this -
At first declare infoView in your .h file UIView *infoView, next steps:
- (void)viewDidLoad {
infoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
infoView.hidden = YES;
[tableView addSubview:infoView];
[super viewDidLoad]; }
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGPoint st = CGPointMake(tableView.frame.size.width/2, cell.frame.size.height*indexPath.row);
infoView.hidden = NO;
infoView.center = st;}
Don't forget to release infoView in dealloc method
Related
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"Returning num sections");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning num rows");
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Trying to return cell");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] ;
}
cell.textLabel.text = #"Hello";
NSLog(#"Returning cell");
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected row");
}
- (void)viewDidLoad
{
[super viewDidLoad];
m_titleTable = [[UITableView alloc] init] ;
m_titleTable.dataSource = self;
m_titleTable.delegate = self;
m_titleTable.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:m_titleTable];
// Do any additional setup after loading the view from its nib.
}
-(void)titleAction:(id)sender{
NSLog(#"Calling");
UIViewController* popoverContent = [[UIViewController alloc]
init];
TitleViewController *popoverView = [[TitleViewController alloc]initWithNibName:#"TitleViewController" bundle:nil];
popoverContent.view = popoverView.view;
//resize the popover view shown
//in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(150, 150);
//create a popover controller
self->popoverController = [[UIPopoverController alloc]
initWithContentViewController:popoverContent];
//present the popover view non-modal with a
//refrence to the button pressed within the current view
[self->popoverController presentPopoverFromRect:btn_title.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
The tableview Crash error message
[__NSCFType tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0x6e7dca0
2012-08-28 14:17:10.539 Demo[2790:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0x6e7dca0'
Your problem is that your view controller is being deallocated. You shouldn't be doing something like this:
UIViewController* popoverContent = [[UIViewController alloc]
init];
TitleViewController *popoverView = [[TitleViewController alloc]initWithNibName:#"TitleViewController" bundle:nil];
popoverContent.view = popoverView.view;
Assuming you are using ARC, your popoverView object will be deallocated. Also this is just incorrect. You should almost never instantiate a UIViewController, and definitely never assign one view controller's view instance to another ones!
Here's how I'd rewrite your titleAction: method:
TitleViewController *titleViewController = [[TitleViewController alloc]initWithNibName:#"TitleViewController" bundle:nil];
//resize the popover view shown
//in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(150, 150);
//create a popover controller
self.popoverController = [[UIPopoverController alloc]
initWithContentViewController:titleViewController];
//present the popover view non-modal with a
//refrence to the button pressed within the current view
[self.popoverController presentPopoverFromRect:btn_title.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
The UIPopoverController, at least, should keep a strong reference to the titleViewController and prevent it from being deallocated.
PS I changed your "self->popoverController" to self.popoverController as the -> is not really correct for what you are trying to do. Dot notation makes explicit that you are setting a property on an object.
in viewDidLoad you allocates and initiates a UITableView and connect it to self. You don't have a UITableView? defined and connect in the nib? Without seeing your whole project my guess is that you have UITableViews - this is a problem but not necessarily the crash problem. Did you inherit from UITableViewController as base class?
I've created an app using single view based.Now I have to display 15 number of menus and description about each menu.So I thought of using UITableView inserting in that.While selecting a cell it should display long text & image content.Do i have to create each ViewController for each description or any shortcuts to add description programmatically
Here is my code for table view
- (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];
}
// Set up the cell...
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15];
cell.textLabel.text = [NSString stringWithFormat:#"Cell Row #%d", [indexPath row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// open a alert with an OK and cancel button
NSString *alertString = [NSString stringWithFormat:#"Clicked on row #%d", [indexPath row]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertString message:#"" delegate:self cancelButtonTitle:#"Done" otherButtonTitles:nil];
[alert show];
[alert release];
}
This is for creating UIAlertView when cell is touched.
How can i do for long text and image display.Any ideas pls.
I think you can use a navigation controller and push tableView on it. On selection of a cell of table you should push a detailView (one detail view for all cells). This works only if you have to show same format of details data in the detailView. Else if you have to different screens for each selection, then you can design all those screens which will also make it heavy.
You can create a single ViewController wich initialize with image and text, inside view controller you should create UITextView and UIImageView. ViewController must be something like this:
#interface ViewController : UIViewController {
UIImageView *imageView;
UITextView *textView;
}
-(id)initWithText:(NSString *)text image:(UIImage *)image;
#end
#implementation ViewController
-(id)initWithText:(NSString *)text image:(UIImage *)image {
if (self = [super init]) {
//ImageView initialization
imageView.image = image;
//TextViewInitialization
textView.text = text;
}
return self;
}
#end
In view controller where table view you can create 2 arrays with corresponding images and text to cells.
Then didSelectRowAtIndexPath: must looks like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ViewController *vc = [[ViewController alloc]initWithText:[textArray objectAtIndex:indexPath.row] image:[imagesArray objectAtIndex:indexPath.row]];
[[self navigationController] pushViewController:vc animated:YES];
[vc release];
}
I can successfully push only next view in my iPhone app. However, cause the next view retrieves data to populate the UITableViews, sometimes waiting time could be a few seconds or slightly longer depending on connection.
During this time, the user may think the app has frozen etc. So, to counter this problem, I think implementing UIActivityIndicators would be a good way to let the user know that the app is working.
Can someone tell me where I could implement this?
Thanks.
pushDetailView Method
- (void)pushDetailView {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//load the clicked cell.
DetailsImageCell *cell = (DetailsImageCell *)[tableView cellForRowAtIndexPath:indexPath];
//init the controller.
AlertsDetailsView *controller = nil;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
controller = [[AlertsDetailsView alloc] initWithNibName:#"DetailsView_iPad" bundle:nil];
} else {
controller = [[AlertsDetailsView alloc] initWithNibName:#"DetailsView" bundle:nil];
}
//set the ID and call JSON in the controller.
[controller setID:[cell getID]];
//show the view.
[self.navigationController pushViewController:controller animated:YES];
You can implement this in didSelectRowAtIndexPath: method itself.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
cell.accessoryView = spinner;
[spinner startAnimating];
[spinner release];
This will show the activity indicator at the right side of the cell which will make the user feel that something is loading.
Edit: If you set the accessoryView and write the loading code in the same method, the UI will get updated only when all the operations over. A workaround for this is to just set the activityIndicator in the didSelectRowAtIndexPath: method and call the view controller pushing code with some delay.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
cell.accessoryView = spinner;
[spinner startAnimating];
[spinner release];
[self performSelector:#selector(pushDetailView:) withObject:tableView afterDelay:0.1];
}
- (void)pushDetailView:(UITableView *)tableView {
// Push the detail view here
}
How do make the individual cells go to different View Controller. Right now, using the method im using, if i click the first cell, it takes me to a view controller where i have a pic. now if i go back and click the second cell, it takes me to the same view controller. How do i change this so that all the other individual cells go to individual view controller? what do i add or what do i configure?
here my code:
// 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...
NSUInteger row = [indexPath row];
cell.textLabel.text = [breakdownArray objectAtIndex:row];
bookDetailViewController.title = [NSString stringWithFormat:#"%#" , [breakdownArray objectAtIndex:row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
NSInteger row = [indexPath row];
if (self.bookDetailViewController == nil); {
BookDetailViewController *aBookDetail = [[BookDetailViewController alloc] initWithNibName:#"BookDetailView" bundle:nil];
self.bookDetailViewController = aBookDetail;
[aBookDetail release];
}
bookDetailViewController.title = [NSString stringWithFormat:#"%#" , [breakdownArray objectAtIndex:row]];
Books2010AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.breakdownNavController pushViewController:bookDetailViewController animated:YES];
}
One fairly easy way is in your tableView:didSelectRowAtIndexPath: method. You can check the index path parameter and execute different code paths. Something like:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath {
switch(indexPath.row) {
case 1:
[self.navigationController pushViewController:someViewController animated:YES];
break;
case 2:
[self.navigationController pushViewController:someOtherViewController animated:YES];
break;
}
}
Like most design choices, this is just an example of one possible approach. That's the best I can do in this general case.
I would create a new view controller each time instead of using the same one and just changing its properties, more like the example that you have commented out in tableView:didSelectRowAtIndexPath:. This will only work if you don't access your controller from anywhere other than these methods.
First: Remove bookDetailViewController.title = [NSString stringWithFormat:#"%#" , [breakdownArray objectAtIndex:row]]; from your tableView:cellForRowAtIndexPath: method (you should do this anyway, since it is just taking more processor time)
Second: Remove the bookDetailController property from your class. You won't need it anymore.
Third: Implement tableView:didSelectRowAtIndexPath: as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
BookDetailViewController *bookDetailViewController = [[BookDetailViewController alloc] initWithNibName:#"BookDetailView" bundle:nil];
NSInteger row = path.row;
bookDetailViewController.title = [NSString stringWithFormat:#"%#" , [breakdownArray objectAtIndex:row]];
//Any other setup on view controller
Books2010AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[delegate.breakdownNavController pushViewController:bookDetailViewController animated:YES];
[bookDetailViewController release];
}
I'm trying to create the exact same effect as in the AppStore app for viewing screenshots: inside a UITableView, I have custom subclasses of UITableViewCell's. One of them is designed to show previews of some product, say 4 images. I want them to show the same way as the AppStore presents screenshots of an app : inside a horizontal UIScrollView with its attached UIPageControl.
So I add my UIScrollView and my UIPageControl to my UITableViewCell, just like that :
#implementation phVolumePreviewCell
- (id)init {
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kVolumePreviewCellIdentifier]) {
[self setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[self setSelectionStyle:UITableViewCellSeparatorStyleNone];
previews = [[NSMutableArray alloc] initWithCapacity:4];
for (int i = 0; i < 4; i++) {
[previews addObject:#"dummy"];
}
scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[scrollView setPagingEnabled:YES];
[scrollView setBackgroundColor:[UIColor grayColor]];
[scrollView setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
[scrollView setShowsHorizontalScrollIndicator:YES];
[scrollView setBounces:YES];
[scrollView setScrollEnabled:YES];
[scrollView setDelegate:self];
[self.contentView addSubview:scrollView];
[scrollView release];
pageControl = [[UIPageControl alloc] initWithFrame:CGRectZero];
[pageControl setNumberOfPages:[previews count]];
[pageControl setBackgroundColor:[UIColor grayColor]];
[self.contentView addSubview:pageControl];
[pageControl release];
}
return self;
}
(note: I'm populating "previews" with dummy data here, just in order to have a [previews count] that works ; I want to view the scrollView's scroll indicator for test purposes only, I'll hide them later on).
My problem is that I can scroll the whole UITableView containing this phVolumePreviewCell (subclass of UITableViewCell), but I can't scroll the UIScrollView. How can I achieve this?
The only information I found is there: http://theexciter.com/articles/touches-and-uiscrollview-inside-a-uitableview.html
But it talks of old SDKs (namely 2.2) and I'm sure there is a more "recent" approach to doing this.
Some precisions :
I can scroll the UIScrollView with two fingers. That's not what I want, I want it to be able to scroll with one finger only.
When I scroll with two fingers, the TableView still intercepts the touches and scroll a little bit to the top or the bottom. I'd like the TableView to stick at its position when I touch the ScrollView.
I believe I have to work out how to intercept touches on my TableView, and if the touch is on the phVolumePreviewCell (custom UITableViewCell subclass), pass it to the cell instead of handling it on the TableView.
For the record, my TableView is created programmatically in a UITableViewController subclass:
#interface phVolumeController : UITableViewController <UITableViewDelegate> {
LocalLibrary *lib;
NSString *volumeID;
LLVolume *volume;
}
- (id)initWithLibrary:(LocalLibrary *)newLib andVolumeID:(NSString *)newVolumeID;
#end
#implementation phVolumeController
#pragma mark -
#pragma mark Initialization
- (id)initWithLibrary:(LocalLibrary *)newLib andVolumeID:(NSString *)newVolumeID {
if (self = [super initWithStyle:UITableViewStylePlain]) {
lib = [newLib retain];
volumeID = newVolumeID;
volume = [(LLVolume *)[LLVolume alloc] initFromLibrary:lib forID:volumeID];
[[self navigationItem] setTitle:[volume title]];
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kVolumePreviewCellIdentifier];
if (cell == nil) {
cell = [[[phVolumePreviewCell alloc] init] autorelease];
}
[(phVolumePreviewCell *)cell setVolume:volume];
return (UITableViewCell *)cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return kVolumePreviewCellHeight;
}
Thanks for any help!
I have found a workaround.
Recreating from scratch a very simple UITableView (8 rows), and inserting a UIScrollView in just the second row, works perfectly. Nested scroll views (the TableView and the ScrollView) scroll independently as expected. All that was done in a single-file test project, in the AppDelegate.
So... first I thought "this might be a delegation problem", so I told the scrollView that its delegate was the TableView, not my custom TableViewCell subclass. To no avail.
Then instead of resorting to a custom, clean TableViewCell subclass that just adds the ScrollView and the PageControl, I resorted to creating a plain TableViewCell in the TableView's cellForRowAtIndexPath: method. Then, I create a UIScrollView right after initializing the TableViewCell, then add it to the TableViewCell, and shazam... it works!
Before:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kVolumePreviewCellIdentifier];
if (cell == nil) {
cell = [[[phVolumePreviewCell alloc] init] autorelease];
}
[(phVolumePreviewCell *)cell setVolume:volume];
// That does the job of creating the cell's scrollView and pageControl
return (UITableViewCell *)cell
After:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kvcPreviewRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kvcPreviewRowIdentifier] autorelease];
previewScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, kvcPreviewScrollViewHeight)];
[previewScrollView setContentSize:CGSizeMake(1000, kvcPreviewScrollViewHeight)];
[[cell contentView] addSubview:previewScrollView];
previewPageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, kvcPreviewScrollViewHeight, tableView.frame.size.width, kvcPreviewPageControlHeight)];
[previewPageControl setNumberOfPages:4];
[[cell contentView] addSubview:previewPageControl];
}
return (UITableViewCell *)cell;
How the heck comes that when I create my scrollView from the TVCell subclass, it doesn't play nice ; but when I create the scrollView from the TableView right after creating a "classical" TVCell, it works?
I might have found a solution, but I'm still puzzled by the reason.