I created tableview and detailviewcontroller but once I select cell for example:I select the row Dog it's not writer Dog on navigationbar. How to do it?
I use with this code
But it's a warning that says local declaration of 'tableview' hides instance variable
DVC =DetailViewController
DVC.title = [[[self tableView:tableView cellForRowAtIndexPath:indexPath] textLabel] text];
Thanks!
You need to use this method: [self setTitle:#"Dog"];
This is not standard behavior of a UITableView. It only changes the Title if you switch to another ViewController.
You need to implement the method didSelectRowAtIndexPath in the ViewController. There you manually change the title of the Navigationbar.
I'm not 100% sure, but I think with that line of code you can change the title:
[viewController.navigationItem setTitle:#"Whatever you want"];
Edit:
The warning just says, that you have an instance variable called tableview and the delegate method also passes internally a variable called tableview. So just change the instance variable name which has the reference to the UITableView.
You should set your detailviewcontroller's title. You can set in your tableView's delegate method: didSelectRowAtIndexPath.
detailViewController.navigationController.title = #"Dog";
About your warning, it's because you have declared a variable called tableView but in the method you write
DVC.title = [[[self tableView:tableView cellForRowAtIndexPath:indexPath] textLabel] text];
there is also a variable called tableView.
Related
The master-detail project created by XCode wizard contains implementation of tableView:cellForRowAtIndexPath: that calls dequeueReusableCellWithIdentifier:forIndexPath:, then calls own custom method configureCell to fill the cell controls with valid data, and then returns the cell to caller. As I understand, this is how table knows how to draw its cells content.
What I don't understand is how to use it when I want to get cell from my code. And is it even supposed to be called by my code, or is it only a callback used by table framework itself?
For example, if I just want to change text of one label in cell, I thought I can just call tableView:cellForRowAtIndexPath:, and change what I need in the resulting cell object controls. But calling tableView:cellForRowAtIndexPath: actually makes a new cell object (probably reusing one from pool of unused cell objects) and fill ALL controls like imageviews and labels in it with data. This does not look good to me regarding to performance, when I want change just one label.
So maybe I could remove configureCell out of tableView:cellForRowAtIndexPath:? But then how to ensure all cell contents will be redrawn by system when [table reloadData] is called?
P.S.
XCode 7 wizard created this kind of code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[self configureCell:cell withObject:object];
return cell;
}
// Then later in controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] withObject:anObject];
break;
configureCell is called twice here. Seems like non-sense to me. I hoped at least people who write code for wizards understand how this is supposed to be working.
There's two different methods being called here that have similar names.
tableView:cellForRowAtIndexPath: is a UITableViewDataSource method that you implement to create the cell for the table to show. The tableview calls this method when a new cell is going to come on screen.
controller:didChange:... is calling a different method called cellForRowAtIndexPath: which is a UITableView method. This method queries the table for a cell that is already being displayed after previously being created using the tableView:cellForRowAtIndexPath: datasource method and doesn't result in it being called again. It's calling this method to access the already displayed cell and update it with new info when the object changes.
Both calls to configureCell are necessary.
I have some custom tableviewcells, each with a thumbnail having a gesture recognizer on it, to open a modal box.
In each tableviewcell there's a property containing a string.
In the method called by the gesture recognizer, i'm trying to access this property, by looping the superviews of the gesture recognizer.
- (void)handleLongPress:(UILongPressGestureRecognizer *)LongPressGestureRecognizer
{
//handle press
ZoomImageViewController *zoomImage = [self.storyboard instantiateViewControllerWithIdentifier:#"zoomImage"];
UIView *subview = LongPressGestureRecognizer.view;
while (![subview isKindOfClass:[UITableViewCell self]] && subview) {
subview = subview.superview;
}
UITableViewCell *cell = (UITableViewCell *)subview;
zoomImage.filename = cell.machinePicture;
zoomImage.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:zoomImage animated:YES completion:nil];
}
In debugger the cell object is the tableviewcellcontroller containing the property i want to access.
However, on the following line i get the error "Property 'machinePicture' not found on object of type 'UITableViewCell *'"
zoomImage.filename = cell.machinePicture;
I don't get why the property cannot by found, while cell seems to be the correct object i'm looking for, containing the property i want...
The standard UITableViewCell does not contain a machinePicture property, did you extend the UITableViewCell class?
Use that custom class instead, casting accordingly:
MyUITableViewCell *cell = (MyUITableViewCell *)subview;
on UITableviewCell you wont be getting a property machinePicture since it is not a property in UITableViewCell. I think you are using a custom table view cell. So you must typecast it. Secondly you must use tableview:didSelectRowAtIndexPath: method of UITableViewDelegate to get the tableviewcell and not using gesture recognizer.
I am trying to create custom UICollectionViewCell which contains few properties, and depending on values of those properties drawing components inside cell. I am using dequeueReusableCellWithReuseIdentifier for creating cell, then I am setting some properties, and at the end calling layoutIfNeeded function which is overridden inside my custom cell. Overridden function is setting some properties of cell also for example BOOL property is set to YES, and after refreshing cell (calling reloadData on collection view) function layoutIfNeeded is called again. When I try to read my BOOL property which is set to YES, i am always getting default value which is NO for the first time i call reloadData. When I call reloadData second time, property is set to YES. Any idea what am I doing wrong? Here is code I am using:
on button click I am calling:
[myCollectionView reloadData];
method cellForItemAtIndexPath looks like:
MyCustomCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCustomCell" forIndexPath: indexPath];
cell.device = [collectionArray objectAtIndex:indexPath.row];
[cell layoutIfNeeded];
return cell;
And code of layoutIfNeeded inside MyCustomCollectionCell.m
-(void)layoutIfNeeded{
NSLog(#"bool prop: %d",changedStatus);
changedStatus = YES;
}
BOOL property is defined in MyCustomCollectionCell.h :
#property (nonatomic, assign)BOOL changedStatus;
UPDATE:
I am sorry, I made a mistake in my post. I am not refreshing collection with reloadData, but with reloadItemsAtIndexPaths; This call causes init method of my custom cell to be called again (not just when collection view is loaded for the first time) and after that layoutIfNeeded. I thing problem is that cell is not reused, but created again, causing all properties to disappear. Any idea how to fix this?
You can't use cells to store state data. Cells get used, put in the reuse queue, and then recycled. The specific cell object that stores the data for a particular indexPath may change when the table is reloaded, when a cell is reloaded, when you scroll to expose new cells, etc.
Save state data in your data model.
What is the purpose of changedStatus property ?
Try setting changedStatus = YES; in layoutSubviews instead :
- (void)layoutSubviews
{
[super layoutSubviews];
self.changedStatus = YES;
}
Set this changedStatus Bool inside your ViewController instead of UICollectionViewCell.
BOOL property is defined in YourViewController.h :
#property (nonatomic, assign)BOOL changedStatus;
When you you want to refresh the CollectionView
[myCollectionView reloadData];
changedStatus = YES;
Then inside your MyCustomCollectionCell.m create a new method like,
-(void)customLayoutIfNeeded : (BOOL)status{
NSLog(#"bool prop: %d",changedStatus);
changedStatus = YES;
}
Add this to MyCustomCollectionCell.h as well.
Then inside cellForItemAtIndexPath do this,
MyCustomCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCustomCell" forIndexPath: indexPath];
cell.device = [collectionArray objectAtIndex:indexPath.row];
[cell customLayoutIfNeeded: changedStatus];
return cell;
I have declared an array in ViewController and displaying it in table view. I am passing values for an array from EditViewController. But the values are not displaying in table view. I am using following code.
ViewController.h
#property (nonatomic, strong) NSMutableArray *tableData;
ViewController.m
ViewDidLoad:
tableData = [NSMutableArray arrayWithObjects:#"",nil];
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
EditViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewController *vc;
vc = [segue destinationViewController];
NSString *str = [NSString stringWithFormat:#"%ld", selectedRow];
[vc.tableData addObject:str];
}
Please advice.
Connect the delegate and datasource to self in the viewDidLOad of editViewController
tableView.delegete=self;
tableView.Datasource=self;
If there is no data in the tableview itself, hit a breakpoint at
cellForRowAtIndexPath,
and Still if it dsnt hits the breakpoint,connect the Delegate and Data source for the tableview with the View Controller.
[EDIT]
If it is still not called, go to storyboard, check if the bounds of the tableview, is more than that of the vc, that means, check if the tableview is inside the view controller and no part of the tableview is crossing the bounds of the view controller.
Plz make sure you have
-tableView:numberOfRowsInSection:
method defined. This method should return value greater than 0 so that
-tableView:cellForRowAtIndexPath:
gets called.
you are add string to nsarray object which is not allocated.
you have to create nssarray with string and pass to the vc.tableData.
There may be a few problems with this.
First, it's best to set a the NSMutableArray property "tableData" to an existing array passed in during the segue. Right now you're adding a single string to a mutable array which, unless you wrote a custom initializer for the ViewController in which you alloc-init'ed the NSMutableArray, it can't exist until ViewDidLoad which is after the segue is performed, so you're passing the string to black abyss of "nil".
It's best to use base types as receiving properties in prepareForSegue, and then in your case to pass the ViewController's array an already existing array from the EditViewController.
Also, you may not be telling the view controller how many cells to actually create. Make sure numberOfSectionsInTableView returns a value (in this case just 1), and that numberOfRowsInSection returns "[self.tableData count]".
And if you didn't create ViewController as inheriting from UITableViewController, you'll need to set that, and connect the delegate and datasource manually in the storyboard like Light Yagami pointed out. Though it would probably be easier to just create a new custom class file that inherits from UITableViewController because it will give you some good boilerplate code.
And also make sure that in your storyboard, your TableViewController's class is set to your custom class file.
I hope you did not pass numberOfSectionsInTableView as 0. Please check that once. It must be 1 or more based on requirement. And same for numberOfRowsInSection.
Remove this line from your ViewDidLoad Method
tableData = [NSMutableArray arrayWithObjects:#"",nil];
i am trying to put a UICollectionview inside of an expanding uitableviewcell, but i keep getting errors. the collectionview is also suppose to take pictures and store them within the collectionview. i used this code:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"myCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell addTarget:self action:#selector(uploadPicture:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (void)uploadPicture:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
the errors i am getting are "no visible #interface for UICollectionViewCell declares the selelctor addTarget:action:forControlEvents" in line 4. and line 5 "void method should not return value" and line 11 "no visible #interface for ExpandingCell declares the selector presentViewController:animated:completion"
i am desparate for help at this point. so thank you in advance if you do help.
Quite a few issues here.
Line 4 - you are in the didSelectItemAtIndexPath method, so you know the user has already touched the cell. You should not need to wire up a target action. Remove this line and call uploadPicture: directly.
Line 5 - didSelectItemAtIndexPath is a void method, so you should not try to return cell. Remove this line.
Line 11 - the error indicates your uploadPicture method is not within a view controller. Therefore it cannot present a view controller. You need to move this method to your view controller or refactor your code so that you present from within a view controller.
Looks like you want to achieve the following:
User has a tableview, and when user taps on a row in table view, app presents an image picker
User selects a number of images from library
All selected images are then shown in a collection view which is embedded within the expanded cell of the tableview
If that assumption is correct, you have to:
implement didSelectRowAtIndexPath for the tableview instead of collectionview
Within this method, call the uploadPicture method
implement didFinishPickingMediaWithInfo of imagePickerController to get selected images
call cellForRowAtIndexPath of the tableview controller to create cell with collectionview having the selected images.
Hope this helps.