I just want to create a UICollectionView as a linear list. That is if the user enters a 4 values in 4 repeats of the textfield, The text has to store in the MutableArray (Which determines the number of collection items).
The problem what I am facing is,
When the view appears, the collectionview starts loading. Initially, data is 0. So, after completion of inserting object in the array. The change should reflect in the Collectionview too. So, after reloading the collectionview, the first item is shown. But, from the next repeats, The data which is recently, entered in the array is inherited to all the cells. Please, help me what to do.
howmanypeople=[routescore.text intValue];
[self.collectionView reloadData]; // Reloading the view
This code is for item at indexPath :-
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cvCell2";
static BOOL nibMyCellloaded = NO;
if(!nibMyCellloaded)
{
UINib *nib = [UINib nibWithNibName:#"CustomCollectionViewCell" bundle: nil];
[collectionView registerNib:nib forCellWithReuseIdentifier:identifier];
nibMyCellloaded = YES;
}
cell = (CustomCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"cvCell2" forIndexPath:indexPath];
cell.cellimage.image=[UIImage imageNamed:#"ic_lomobile_transit_scooter_small.png"];
cell.cellabel.text=route;
cell.backgroundColor=[UIColor lightGrayColor]
return cell;
}
Related
there has a tableView Who refreshed every 0.5 seconds;
i uesd tableView reloadData or reloadSections: withRowAnimation:
Both of them cause FPS decrease
what can i do for it?
the tableView has new data every 0.5 seconds
and need display new data immediately
code:
- (void)registerTableViewCells {
[self.tableView registerClass:[UITableViewCell1 class] forCellReuseIdentifier: UITableViewCell1Identifier];
[self.tableView registerClass:[UITableViewCell2 class] forCellReuseIdentifier: UITableViewCell2Identifier];
[self.tableView registerClass:[UITableViewCell3 class] forCellReuseIdentifier: UITableViewCell3Identifier];
}
- (void)makeUpDisplaySource {
NSMutableArray *arrM = [NSMutableArray array];
[arrM addObject:#[UITableViewCell1Identifier, #(60), #(1)]];
[arrM addObject:#[UITableViewCell2Identifier, #(55), #(10)]];
[arrM addObject:#[UITableViewCell3Identifier, #(30), #(10+_fortySeat*30)]];
// _fortySeat is boolValue
self.displaySource = arrM;
}
tableView delegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *dataArr = self.displaySource[indexPath.section];
NSString *identifier = dataArr[0];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([NSStringFromClass(cell.class) isEqualToString:#"UITableViewCell1"]) {
UITableViewCell1 *newcell = (UITableViewCell1 *)cell;
[newcell updatCellUI];
}
else if ([NSStringFromClass(cell.class) isEqualToString:#"UITableViewCell2"]) {
UITableViewCell2 *newcell = (UITableViewCell2 *)cell;
[newcell updatCellUIBuy: model1 sell: model2];
}
else if ([NSStringFromClass(cell.class) isEqualToString:#"UITableViewCell3"]){
cell.backgroundColor = GL_CELL_BACKGROUD_COLOR;
[cell addSubview:self.someView];// someView is a lazy property
}
}
If you are not using reusable cells, of course, reload the data every 0.5 seconds may cause FPS problems beacause you'll reload the data of all the cells present in your TableView.
Also even if you are reloading data with reloadSections:, you'll have problems if you are reloading all the modified cells. Even those who are not visible. -- And this may cause problems.
In that case I suggest you to :
Use : [self.tableView registerNib:[UINib nibWithNibName:#"TableViewCell" bundle:nil] forCellReuseIdentifier:#"CellID"];
This will register your tableView under a xib file and the cells under an ID.
In cellForRowAtIndexPath: load your cell using this ID :
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellID"];
Using reusable cells you will increase the speed of loading your TableView and it may help you while refreshing it.
If you are already using reusable cells I suggest you to let people know it in your question.
Even if your are using reusable cells you could simply decrease a bit the interval time between 2 reloads if you still have problems with FPS.
I might not have completly understood your question and I might be wrong on certains points. Of course do not hesitate to let me know/edit my answer, I will apreciate it.
I want to call didSelectItemAtIndexPath: for particular index path but I can't call it programmatically in cellForItemAtIndexPath because collection is not yet ready, I will get cell as nil. Do we have any delegate method or any other UIView method that is called after collection view is ready?
I have tried willDisplayCell: but it is not made for relevant work, couldn't find anything else.
I want to call didSelectItemAtIndexPath:
Don't. This is a delegate method. It is called by the runtime when the user selects an item. You must never call this yourself.
You have to do it programmatically utilising your manual logics. :)
The underlying concept is that get the indexes of selected cells and reload those specific cells only.
Declare a global var
NSMutableArray array_indexpath;
in your did select method add indexes of selected cells.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
array_indexpath=[[NSMutableArray alloc]init];
[array_indexpath addObject:indexPath];
[self.myCollectionView reloadItemsAtIndexPaths:array_indexpath];
}
and in your cell for cellForItemAtIndexPath method check the indexes and reload it as required.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ShubhCalendarCollectionViewCell *cell =[collectionView dequeueReusableCellWithReuseIdentifier:#"ShubhCalendarCollectionViewCell" forIndexPath:indexPath];
cell.backgroundColor=[UIColor clearColor];
if (array_indexpath.count !=0)
{
for (int i=0; i<[array_indexpath count]; i++)
{
if ([array_indexpath objectAtIndex:i] == indexPath)
{
cell.backgroundColor=[UIColor greenColor];
}
}
}
return cell;
}
Hope it helps.. Happy Coding.. :)
I have creating a excel view using collection view. Earlier I was facing an issue while scrolling the collection view listed at :
https://stackoverflow.com/questions/27036224/scrolling-disturbs-layout-of-collectionview
I fixed that issue with the after seeing Shivam's reply in:
Collection View,with custom layouts, cells misbehave on scrolling
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellID = [NSString stringWithFormat:#"%#%d", #"cCell",indexPath.row];
[myCollectionView registerClass: [CustomCell class] forCellWithReuseIdentifier:cellID];
CustomCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
-(void)configureCell:(CustomCell*)cell forIndexPath:(NSIndexPath*)indexPath{
// configuration code
}
I don't know whether it is correct or not, but's its working.But now I am stuck in another problem related to reload of collection view.
Problem::: I have textfield in the cells for which I have implemented textFieldDidEndEditing delegate. I have also provided Next Button which provides proxy navigation to all cells in collection view as desired by me. In the clicked method of next button, I am saving the currentIndexpath, reloading the collection view, getting the next cell using saved index path, getting the textfield and making it as first responder. But next textfield never becomes first responder. I debugged the issue and find that after reload I am not able to retrieve the cell. If I remove the reload line then everything works fine.
NSIndexPath *reqIndexPath = [NSIndexPath indexPathForItem:colId inSection:currentSection];
CustomCell *cell = (CustomCell*)[self.collectionView cellForItemAtIndexPath:reqIndexPath];
I get this resolved by :
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
Thanks to Lukewar reply in
Reloading a UICollectionView using reloadData method returns immediately before reloading data
I have a UICollectionView that contains custom UICollectionViewCells (TestReceiptCell is the class name).
I was not having any problems getting the UICollectionView to appear and load the custom cells when the custom cells only contained a UILabel.
I then added a UITableView via IB into the TestReceiptCell NIB file. I set a referencing outlet in TestReceiptCell.h for the UITableView and synthesized in the .m file. I set the delegate and datasource for the UITableView to the ViewController containing the UICollectionView.
Now when running the app I get a EXC_ BAD_ ACCESS exception in this block on the third line:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"TestReceiptCell";
TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; //exception thrown here
return cell;
}
I ran the Zombie Instrument test and found that the deallocated memory call originates here. This is my first time using that instrument so I am not exactly sure how to investigate from here.
For reference, here are some more relevant parts of the code:
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.myCollectionView registerNib:[UINib nibWithNibName:#"TestReceiptCell" bundle:nil] forCellWithReuseIdentifier:#"TestReceiptCell"];
// Setup flowlayout
myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[myCollectionViewFlowLayout setItemSize:CGSizeMake(310, 410)];
[myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
self.myCollectionView.pagingEnabled = YES;
}
I am implementing the UITableView datasource and delegate methods in the ViewController.m file as well but I am not sure if the problem lies here given the origination of the EXC_BAD_ACCESS exception:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"eventCell"];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"eventCell"];
}
return cell;
}
UPDATE:
I am able to get this to run if I change cellForItemAtIndexPath to:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"TestReceiptCell";
//TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
TestReceiptCell *cell = [NSBundle.mainBundle loadNibNamed:#"TestReceiptCell" owner:self options:nil][0];
return cell;
}
However, I am not dequeuing cells and know this is not the correct way. There seems to be an issue somewhere in the initWithFrame method that gets called when dequeueReusableCellWithResueIdentifier creates a new cell. Here is that method currently:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:#"TestReceiptCell" owner:self options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) {
return nil;
}
self = [arrayOfViews objectAtIndex:0];
}
return self;
}
EDIT:
If I do not select a delegate or a datasource for the tableview, the collectionview with tableviews will load. Something in attaching the delegate/datasource to File's Owner is causing the error.
When you register a UINib for cell reuse, dequeueReusableCellWithReuseIdentifier:forIndexPath: is what calls instantiateWithOwner:options: on the UINib that you registered. Whatever it passes for owner, is what becomes the File's Owner outlet in your nib.
It appears that you are expecting the File's Owner to be the UICollectionView, but I don't think that it is.
Even if it were, I don't think you should use the UICollectionView for the delegate of the UITableView contained within each collection cell. That would require your UICollectionView to keep track of the tableViews and contents within each cell.
I'd suggest setting the delegate of the contained tableView to the collection cell itself and have each cell manage its own tableview.
EDIT:
You can define a delegate protocol for your collection view cells to communicate the relevant table view events to the collection view. With this approach, you would set the delegate property you define for each collection cell in the collectionView:cellForItemAtIndexPath method of your collection view datasource.
When the user, for example, selects an item from the table, you can call the cell delegate to inform the collection view which item was selected.
This approach allows you to abstract the fact that your collection cell is using a table view to display the cell information. Later, if you decide you want to use, for example, an embedded UICollectionView to display those items, the delegate protocol can remain unchanged and you can isolate your changes to the collection cell.
I have a problem with my cell textfield values when scrolling on a UITableView. When I scroll down and hide a custom cell, the value of the textField is deleted. The dequeueReusableCellWithIdentifier method doesn't work. I have this:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SectionsTableIdentifier = #"MyCustomCell";
MyCustomCell *cell = (MyCustomCell *) [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
cell = [objects objectAtIndex:0];
}
cell.labelCustomAttribute.text= #"Attribute Name";
cell.textFieldCustomAttribute.delegate = self;
return cell;
}
I find it easier to register the custom cell with the tableView in the viewDidLoad method and then simply use dequeueReusableCellWithIdentifier. If you register the cell, the dequeue method will automatically pick up a reusable cell OR allocate a new custom cell (if none is available).
Example:
-(void)viewDidLoad
{
[super viewDidLoad];
// Get a point to the customized table view cell for MyCustomCell
UINib *myCustomCellNib = [UINib nibWithNibName:#"MyCustomCell" bundle:nil];
// Register the MyCustomCell with tableview
[[self tableView] registerNib:myCustomCellNib forCellReuseIdentifier:#"MyCustomCell"];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SectionsTableIdentifier = #"MyCustomCell";
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
cell.labelCustomAttribute.text= #"Attribute Name";
cell.textFieldCustomAttribute.delegate = self;
return cell;
}
Normally the reuseIdentifier is assigned in the UITableViewCell's initWithStyle:reuseIdentifier: method, which you are not using because you are loading your view from a Nib.
You cannot set this property after because it is read only.
Maybe you can try instanciating the cell using the standard initWithStyle:reuseIdentifier: and add the view from your Nib as a subview of the cell's ContentView...
Now what is happening in your case is that you create a new cell every time that the Table View needs to display one. Clearly, this is not going to work. Actually, if you were reusing cells, you would have to also store the content of your text field somewhere (preferably in your data source) and put it when you reuse the cell. If you do not store it, when the cell is going to be reused, it will contain the data from the previous row in which it was displayed.