How can I download set of images from server and display those images inside table cell. Could you help with completion block or delegate. Example will be really appreciated.
[tableCell.playerView addSubview:imagePlayerView];
dispatch_async(dispatch_get_main_queue(), ^{
[imagePlayerView downloadImages];
});
It's not a good way to add subview imagePlayerView in cellForRowAtIndexPath, because on reload it will again create and load, so use custom cell for arranging view.
// Not a good way to do that
[tableCell.playerView addSubview:imagePlayerView];
Create a custom cell for your table view with UIImageView on cell. Refer the link https://www.appcoda.com/customize-table-view-cells-for-uitableview/
In your view controller class:
Follow the below steps:
Import AFNetworking+UIImageView in your view controller file
Update cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static cellIdentifier = "cellidentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSURL *url = [[NSURL alloc] initWithString:"Your Url"];
[cell.imageProfPic setImageWithURL:url]; // Supposing "imageProfPic" is the UIImageView in your cell's custom class
return cell
}
Related
I am creating a tableView which has collectionView inside.
what I did :
1. Created a table view inside a controller.
2. created a custom tableViewCell with collectionView inside of that and providing it with tag
3. Created a custom collectionViewcell.
Now i made controller the delegate and datasource for both collectionView and tableView.
Now tableView should have multiple tableViewcells and each tableViewCell has CollectionView
One tableViewCell has one section.
Problem :-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
self.arrayModel = self.SlotsArray[indexPath.section];
}
But here is a catch : lets say my screen size shows two tableViewcell, then all methods of tableCells are called first and then all methods of collectionView are called instead i want that after 1st section of tableViewcell is created , it should call collectionView methods and create it. then go to tableView method make 2nd section and then create its collectionView.
Is there away to do this.
Somewhere i read on net thet i will have to subclass CollectionView and add a property index and then while setting viewcontroller as delegate and datasource , set index also.
But i have created CollectionView By nib and adding it to the tableCell class by "TAG"
self.imageCollectionView = [self.contentView viewWithTag:2511];
Can you tell how can i achieve this?
In your case, you should have one table view, having cells. Each cell will have a collection view inside it.
Number of table view cells will equal to the count of your data-source. As we all know, table view cell will be created one by one and assign each cell a data source which will be used to fill your collection view (which is inside each cell).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifierCategory forIndexPath:indexPath];
NSArray *arrVideos = [parentArray objectAtIndex:indexPath.row];
[cell setCollectionData:arrVideos];
return cell;
}
Now, inside that table view cell class, implement setCollectionData method to fill its collection view:
- (void)setCollectionData:(NSArray *)collectionData
{
self.arrCollectionData = collectionData;
[self.yourCollectioView reloadData];
}
Now, each collection cell would be feed from this array:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
VideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifierVideo forIndexPath:indexPath];
NSDictionary *_video = [self.arrCollectionData objectAtIndex:[indexPath row]];
// Use this dictionary
[cell.lblVideoTitle setText:_video.title];
––––––––––
––––––––––
return cell;
}
Refer following image:
Hope it helps you !!!
You can take a look on this, surely it will help you to implement horizontal scrolling collection view inside uitableviewcell.
https://github.com/ThornTechPublic/HorizontalScrollingCollectionView/blob/master/GithubImages/videoGrid.gif
https://github.com/agusso/ASOXScrollTableViewCell
I am working with tableviews in iOS. Reusable cells are reloaded when scrolling.
So, when updating -for example- textfields inside a cell, it disappears once scrolling over. I solved it by using an Array that saves all texts in all cells, but I wonder if there's a better way to solve this issue.
Thanks.
Using String array you have to store data of all textfields in tableview.
Use delegate methods of UITableView to implement more efficiently.
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell * mc = (MyCell *) cell;
names[indexPath.row] = mc.myTf.text;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell * mc = (MyCell *) cell;
mc.myTf.text = names[indexPath.row];
}
Here, MyCell is the custom cell which has UITextField. name[] is the NSString array declared at class scope like NSString * names[20].
What you are describing is how tableviews are meant to work! The tableView is a display, not a store, and the reusable cells are only those currently displayed
You are right to use an array (or collection) to hold the data and just use the tableView to display it
for memory management (to releasing memory) tableview remove cell memory which are not displaying in current screen its only keep those cell in memory which are currently displaying on screen so you have to store that text separate from tableview.
You issue can be because of multithreading. If you are reloading data from a GCD operation or any NSOperation(different thread), then you have to use the below code to get the handle to main thread
dispatch_sync(dispatch_get_main_queue(), ^{
//perform the reload activity
});
Yes you are doing right, as cells are reused you need to save your data, something like this -
1 . Have an array to hold your data.
2 . Update your array whenever you make any change in your textFields, so that your UI and data are in sync.
Use this array to populate your tableView.
You need to define the cellIdentifier as unique. Then each cell created with unique identifier.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%dR%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
//your logic here
}
return cell;
}
I want a tableview inside another tableviewCell like the following image.It shows one complete cell with a few details and a tableview. How can i do this?I was following this link Link.This is an old code .It is using xibs.I dont have any idea where to set the delegate for the inner tableview.Please help.Any suggestion will be realy helpfull.
My first idea would be:
Subclass UITableViewCell ("MainTableViewCell") and extend it with UITableViewDelegate and UITableViewDatasource.
Next to all the properties you need in "MainTableViewCell" add a TableView "tableViewFilms" and an array "films" for the Films. Also don't forget to add the datasource methods for a tableview to the implementation file.
To easily setup a cell I add a setup-method to the header-file. Which can be called once the cell is instantiated. You can modify it as you want, give it as many parameters as you want and in the implementation (see step 4) set datasource and delegate of your inner tableview.
- (void)setupCellWithDictionary:(NSDictionary *)dict AndArray:(NSArray *)filmsForInnerTable;
You can call this method in your datasource method, once a cell is instantiated:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MainTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainTableViewCell" forIndexPath:indexPath];
NSDictionary *dict = (NSDictionary *) allDataDictionaries[indexPath.row];
[cell setupCellWithDictionary:dict AndArray:filmsForInnerTable];
return cell;
}
Subclass UITableViewCell another time: "FilmTableViewCell"
When setting up the a Cell of "MainTableViewCell", set the delegate and the datasource of "tableViewFilms" to self (object of "MainTableViewCell").
- (void)setupCellWithDictionary:(NSDictionary *)dict AndArray:(NSArray *)filmsForInnerTable{
self.films = filmsForInnerTable;
self.tableViewFilms.dataSource = self;
self.tableViewFilms.delegate = self;
[self.tableView reload];
//more instructions
}
Populate the tableview with the data from the array "films" using "FilmTableViewCells".
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FilmTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FilmTableViewCell" forIndexPath:indexPath];
Film *film = (Film*)films[indexPath.row];
[cell setupCellWithFilm:film];
return cell;
}
Hope this helps.
Don't forget to use Outlets, the method definitions and to set the reuse-identifiers for the cells!
Check my answer in this ios 8 Swift - TableView with embedded CollectionView. You have replace that UICollectionView with UITableView.
Everything else is pretty much the same. Its just a head start with UITableView and UICollectionView created programmatically.
I can change it accordingly if you don't understand.
I have created a custom UITableViewCell using the nib file. Then when I select the my custom UITableViewCell, I want to perform a segue and pass the data to the detail view controller. I have already set the segue identifier in the storyboard, and I put the prepareForSegueWithIdentifier in the - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath However, when I perform the segue, only the first row of the table view can be shown on the detailed page.
I have three questions:
1. How to set the segue identifier for the custom UITableViewCell?
Since I create the custom UITableViewCell in the xib file, it is difficult to connect the xib file with the main storyboards with other view controllers.
2. If I change the class name of the table view cell in the storyboard, will it be my custom UITableViewCell?
Specifically, in order to replace the default UItableViewCell in the storyboard to my custom UITableViewCell, I change the name of the class of the default UITableViewCell in the storyboard, to the name of my custom UITableViewCell. Then I Control + Drag to create a push segue and set the segue identifier. But it seems this one doesn't work either.
3. Why every time I perform segue, the destination view controller only show the specific content of the first row of my table view?
That is, whenever I select the first cell, the second cell, the third cell......, all I get after segue to the destination view controller is the content of the first cell. I am wondering whether the sender is my custom UITableViewCell? Or is the indexPath is nil? I am not sure.
My code is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
customTableViewCell *cell;
cell = (customTableViewCell *) [tableView dequeueReusableCellWithIdentifier:#"myCell"];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"customTableViewCell" owner:nil options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *photo = self.recentPhotos [indexPath.row];
dispatch_queue_t queue = dispatch_queue_create("fetch photos", 0);
dispatch_async(queue, ^{
NSURL *imageURL = [FlickrFetcher URLforPhoto:photo format:FlickrPhotoFormatSquare];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
NSString *title = [photo valueForKeyPath:FLICKR_PHOTO_TITLE];
cell.cellLabel.text = title;
UIImageView *cellImageView = [[UIImageView alloc]initWithImage:image];
[cellImageView setFrame: CGRectMake(10, 5, 45, 45)];
[cellImageView.layer setCornerRadius:cellImageView.frame.size.width/2];
cellImageView.clipsToBounds = YES;
[cell addSubview:cellImageView];
});
});
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"go" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSDictionary *photo = self.recentPhotos [indexPath.row];
NSURL *imageURL = [FlickrFetcher URLforPhoto:photo format:FlickrPhotoFormatLarge];
NSString *title = [photo valueForKeyPath:FLICKR_PHOTO_TITLE];
if ([segue.identifier isEqualToString:#"go"]) {
if ([segue.destinationViewController isKindOfClass:[ViewImageViewController class]]) {
ViewImageViewController *vivc = (ViewImageViewController *) segue.destinationViewController;
vivc.imageURL = imageURL;
vivc.title = title;
}
}
}
Did you try debugging the method and looking at the value of sender? You provided the indexPath in the call to performSegueWithIdentifier:sender: but the you use the sender as a cell in indexPathForCell:.
I already see problems in your tableView:cellForRowAtIndexPath: method as well. While scrolling the cells get reused, so when you perform a async call the block can and will be executed on the wrong cell. To prevent that call the dequeueReusableCellWithIdentifier: again inside the dispatch_async callback.
Also you are adding a subview directly to the cell instead of using the contentView property.
Regarding your questions, as far as I know you cannot connect a segue from a nib file. To make it work properly you need to connect the segue from the prototype cell in the storyboard. You created a manual segue and you're calling it when the user touches the cell. I think that it'll be easier for you to understand what's happening if you don't use segues at all and just call showViewController:sender: yourself.
So I am trying to display horizontally scrollable collection view inside tableviewcell. the code i am using is
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UICollectionViewController *cv = [self.storyboard instantiateViewControllerWithIdentifier:#"collectionViewID"];
cv.view.frame = cell.contentView.bounds;
[self addChildViewController:cv];
[cell.contentView addSubview:cv.view];
[cv didMoveToParentViewController:self];
return cell;
}
I am getting error: Object can not be nil. I'd appreciate if someone can help me out understanding the error.
I have done this in my app.
I found it much easier to subclass UITableViewCell. The I could put all the UICollectionView setup and the UICollectionView datasource and delegate inside the code for the cell.
I then provided one public property of type NSArray which I pass into the cell. The cell then uses this array as the datasource for the UICollectionView that it owns itself.
Made it a lot easier to manage.
check your UICollectionViewControlle's attribute inspector for identifier value {collectionViewID}
EDIT
[self addChildViewController:cv]; --> I think you want to add cv to the cell, isn't you?