I've got a Table View Cell in .xib. I've got a UILabel and UIImageView in the .xib.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
SchoolsTableViewCell *cell = (SchoolsTableViewCell *) [[[NSBundle mainBundle] loadNibNamed:#"SchoolsTableViewCell" owner:self options:nil] lastObject];
NSLog(#"Before: %#", cell.nameLabel.text);
cell.nameLabel.text = [NSString stringWithFormat:#"Name: %#", [object objectForKey:#"name"]];
NSLog(#"After: %#", cell.nameLabel.text);
PFFile *file = [object objectForKey:#"logo"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error)
{
cell.logoImageView.image = [UIImage imageWithData:data];
}];
return cell;
}
As you can see, I have 2 NSLog()s, printing the below:
2015-07-08 20:17:26.739 o [1871:108786] Before: (null)
2015-07-08 20:17:26.740 o [1871:108786] After: Name: SMSAS
That is expected.
However, on my Simulator, I can only see a blank cell with Name:. It should show SMSAS in the label, and load a logo, but it's not happening. I can pass the object to the next View Controller when the cell is tapped, and it can show in that View Controller.
This is my .m for the cell.
#implementation SchoolsTableViewCell
- (void)awakeFromNib
{
[super awakeFromNib];
self.nameLabel = [[UILabel alloc] init];
self.logoImageView = [[UIImageView alloc] init];
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.logoImageView];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
#end
I'm sure it's a simple mistake. Anyone care to open my eyes? Thanks!
Use dequeueReusableCellWithIdentifier
static NSString * CellIdentifier = #"SchoolsTableViewCell";
SchoolsTableViewCell *cell = (SchoolsTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SchoolsTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
Related
I am using the following code to have a tab view. When you click one tab it expands downwards, this is currently working okay but if I open the first tab with the indexPath of 0 which should load a separate custom opened view it will load but then when I go to the other indexPath tabs it displays the same view but if I reload the app and go to the other tabs first they load the correct view. It's nearly like the app is making a cache?
Is there any way to solve this??
Thanks
- (void)viewDidLoad {
row = 1000;
NSLog(#"row is %d", row);
[super viewDidLoad];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
infoStory = [userDefaults objectForKey:#"storyname"];
// Do any additional setup after loading the view.
numbers = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", nil];
// Initialize thumbnails
text = [NSArray arrayWithObjects: #"Arriving by Bus or Train", #"Arriving by Car (Autobahn 5)", #"Arriving by Car (Autobahn 6)", #"Wifi", #"Registration", #"Refreshments", #"Evening Event", #"Contact Information", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
if(indexPath.row == 0){
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellOPENED";
TableViewCell1 *cell2 = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell2 == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENED" owner:self options:nil];
cell2 = [nib objectAtIndex:0];
}
cell2.text.text = [text objectAtIndex:indexPath.row];
return cell2;
}
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellINFO";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellINFO" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [numbers count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
row = 1000;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
else{
row = indexPath.row;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
}
#end
I think the problem might be that you did not specify the correct reuse identifier in the attributes inspector of the cell in your XIB file(s). You should check if you use the wrong one somewhere, so dequeueing will return an unexpected cell.
You could also set the appropriate reuseIdentifier manually, with a little setValue:forKey: trick:
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell setValue:simpleTableIdentifier2 forKey:#"reuseIdentifier"];
}
and so on for the other cells and identifiers.
What I'm trying to do is load some HTML resource files in to UITableView cells. I wanted to adjust the cell heights depend on the content size of the UIWebView. Following is some of my test codes.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TableCellID";
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
cell = [nibArray objectAtIndex:0];
}
NSString *htmlFileName = [NSString stringWithFormat:#"page%ld", (long)indexPath.row];
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:htmlFileName ofType:#"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[cell.webView loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];
return cell;
}
If I describe my CustomTableViewCell.xib, it has a UIWebView inside the Content View and UIWebView has following constraints given.
ContentView.Bottom = WebView.Bottom + 8
ContentView.Top = WebView.Top +8
ContentView.Leading = WebView.Leading + 8
ContentView.Trailing = WebView.Trailing + 8
HTML fils has no JavaScript or CSS content. Simple as below.
<html>
<header>
</header>
<body>
<p>eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee</p>
</body>
</html>
Now my out put is like below image.
As I explained at top, my web pages doesn't contain any JavaScript. So I may not able to use stringByEvaluatingJavaScriptFromString method to return the text.
Try this
- (void)viewDidLoad {
[super viewDidLoad];
arrOfHTMLList= [[NSMutableArray alloc] init];
NSMutableDictionary *dic1 = [[NSMutableDictionary alloc] init];
[dic1 setObject:#"0" forKey:#"height"];
[dic1 setObject:#"aaaaaaaaaa aaaaaa aaaaaaa aaaaaaa aaaaaa aaaaaa aaaaaaaa aaaaa" forKey:#"htmlString"];
NSMutableDictionary *dic2 = [[NSMutableDictionary alloc] init];
[dic1 setObject:#"0" forKey:#"height"];
[dic1 setObject:#"abababababbabababababab ababab bababa ababababb" forKey:#"htmlString"];
NSMutableDictionary *dic3 = [[NSMutableDictionary alloc] init];
[dic1 setObject:#"0" forKey:#"height"];
[dic1 setObject:#"sdajdkjas dkasjkhd jkashjkd sakjhdkj askjdaksh dksajkdkjsah djkasjkhd kjsahjkd asjkhdk jasjkdhaskj" forKey:#"htmlString"];
NSMutableDictionary *dic4 = [[NSMutableDictionary alloc] init];
[dic1 setObject:#"0" forKey:#"height"];
[dic1 setObject:#"sdajdkjas dkasjkhd jkashjkd sakjhdkj askjdaksh dksajkdkjsah djkasjkhd kjsahjkd asjkhdk jasjkdhaskj" forKey:#"htmlString"];
[arrOfHTMLList addObject:dic1];
[arrOfHTMLList addObject:dic2];
[arrOfHTMLList addObject:dic3];
[arrOfHTMLList addObject:dic4];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UIWebView *webView = (UIWebView*)[cell viewWithTag:1];
NSString *myHTML = arrOfHTMLList[indexPath.section][#"htmlString"];
[webView loadHTMLString:myHTML baseURL:nil];
webView.delegate = self;
webView.frame = CGRectMake(0, 0, screenWidth,cell.frame.size.height);
return cell;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
for (UIView *parent=[webView superview];parent!=nil ;parent=[parent superview] )
{
if([parent isKindOfClass:[UITableViewCell class]])
{
UITableViewCell *cell=(UITableViewCell *)parent;
NSIndexPath *indexPath=[_tableView indexPathForCell:cell];
int height = webView.scrollView.contentSize.height;
[[arrOfHTMLList objectAtIndex:indexPath.section] setObject:[NSString stringWithFormat:#"%d",height] forKey:#"height"];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = [arrOfHTMLList[indexPath.section][#"height"] intValue];
return height;
}
Hope it helps.
the main issue is to get a web view's frame to adapt to its html content right away :)
and THAT only happens after it asynchronously loaded the content!
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
//TODO: update the table's height for the cell for the webview
}
a drop-in solution I wrote is a custom UITableViewCell subclass that has a webview and informs a delegate to reload the table:
https://github.com/Daij-Djan/DDUtils/tree/master/objC/DDUtils-IOS/ui/M42WebviewTableViewCell%20%5Bios%5D
the most important piece of code is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
M42WebviewTableViewCell *cell = _loadedCells[#(indexPath.row)];
if (!cell) {
cell = [[M42WebviewTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
NSString *object = _objects[indexPath.row];
cell.tag = indexPath.row;
cell.delegate = self;
[cell setHtml:object AndBaseURL:nil];
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//if a cell isnt ready, it wont be there and the method will return 0
M42WebviewTableViewCell *cell = _loadedCells[#(indexPath.row)];
return cell.height;
}
#pragma mark - M42WebviewTableViewCellDelegate
- (void)tableCellDidLoadContent:(M42WebviewTableViewCell *)cell {
if (!_loadedCells) {
_loadedCells = [[NSMutableDictionary alloc] init];
}
[_loadedCells setObject:cell forKey:#(cell.tag)];
//only refresh sizes of rows
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
I came up with my own solution. But thanks all the others who commented on this question and open my mind in different paths. So here what I did.
First added a UIWebViewDelegate to my ViewController class
#interface ViewController () <UITableViewDataSource, UITableViewDelegate, UIWebViewDelegate> {
Then loading HTML pages and adding delegate is done inside following method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TableCellID";
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
cell = [nibArray objectAtIndex:0];
}
cell.webView.delegate = self;
cell.webView.tag = indexPath.row;
cell.webView.scrollView.scrollEnabled = NO;
NSString *htmlFileName = [NSString stringWithFormat:#"page%ld", (long)indexPath.row];
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:htmlFileName ofType:#"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[cell.webView loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];
return cell;
}
After web view is loaded, calculate the size that fits to it's content and after all web views are loaded, I reload table data like below.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (webView.tag == 0) {
[cellHeightMutArray removeAllObjects];
}
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
[cellHeightMutArray insertObject:#(fittingSize.height) atIndex:webView.tag];
if (((webView.tag + 1) == dataArray.count) && !reloadedTableViewAfterLoadingWebContent) {
reloadedTableViewAfterLoadingWebContent = YES;
_tableView.hidden = NO;
[_tableView reloadData];
}
}
Then I adjust the height of the cell (which was the main issue that I had)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (cellHeightMutArray.count > 0) {
return [[cellHeightMutArray objectAtIndex:indexPath.row] intValue];
}
return 44;
}
This is my solution and it works perfectly in iPhones and iPads.
But I had different issue when I run it with more complex user interface in iPads which is in my real project. I'll update this if my solutions for those issue related to this question.
I integrate pubnative library in my project , but it load only one app in my table view and i don't want tihis. I want to populate my table view with all partener apps that i have. When i lunch the app date are diffrent every time .
-(void)viewDidLoad
{
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
PNAdRequestParameters *parameters = [PNAdRequestParameters requestParameters];
[parameters fillWithDefaults];
parameters.ad_count = #5;
parameters.app_token = #"My app token";
parameters.icon_size=#"400x400";
self.request = [PNAdRequest request:PNAdRequest_Native
withParameters:parameters
andCompletion:^(NSArray *ads, NSError *error)
{
if(error)
{
NSLog(#"Pubnative - Request error: %#", error);
}
else
{
NSLog(#"Pubnative - Request end");
weakSelf.ads = [[NSMutableArray alloc] initWithArray:ads];
weakSelf.model = [ads firstObject];
[self.tableView reloadData];
}
}];
[self.request startRequest];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[PNTableViewManager controlTable:self.tableView];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[PNTableViewManager controlTable:nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *result = nil;
PNBannerTableViewCell *bannerCell = [tableView dequeueReusableCellWithIdentifier:bannerCellID];
if(!bannerCell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PNBannerTableViewCell"
owner:self options:nil];
bannerCell = [topLevelObjects objectAtIndex:0];
}
bannerCell.model = self.model;
result = bannerCell;
return result;
}
You should then assign a different ad each time
- (UITableViewCell *)tableView:(UITableView *)tableView cell ForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *result = nil;
PNBannerTableViewCell *bannerCell = [tableView dequeueReusableCellWithIdentifier:bannerCellID];
if(!bannerCell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PNBannerTableViewCell"
owner:self options:nil];
bannerCell = [topLevelObjects objectAtIndex:0];
}
// We assign an add to the table
bannerCell.model = self.ads[indexpath.row % [self.ads count]];
result = bannerCell;
return result;
}
I am parsing JSON and storing it in an array.I have a custom cell subclass in which I am trying to set the title of a label from the content of parsed JSON.
This is the parsing process.
#implementation BlogScreenViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.jsonArray = [[NSMutableArray alloc]init];
NSError *error = nil;
NSURL *url = [NSURL URLWithString:#"http:web_services/blog.php"];
NSData *data = [NSData dataWithContentsOfURL:url];
self.jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
for (NSDictionary *obj in self.jsonArray)
{
NSLog(#"JSON string output :- %# ", [obj objectForKey:#"titre"]); // shows titles
}
In custom cell subclass
// set blog title label
UILabel *blogTitleLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 20, 200, 20)];
// blogTitleLabel.text = #"This is blog title"; // This shows properly if used.
for (NSDictionary *obj in blogScreenVC.jsonArray ) //This doesn't work.
{
blogTitleLabel.text = [NSString stringWithFormat:#"%#",[obj objectForKey:#"titre"]];
}
[blogTitleLabel setFont:[UIFont systemFontOfSize:9]];
[self addSubview:blogTitleLabel];
Instead of Setting lebel.text in customcell class add it in the cellForRowAtIndexPath.
Create Property of label in customcell.h file
#property (nonatomic, weak) IBOutlet UILabel *label;
And in customcell.m file synthesys it.
#synthesize label = _label;
And in you viewcontroller.m file
#import "CustomCell.h"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.jsonArray.count !=0) {
NSMutableDictionary * tmpDictn = [self.jsonArray objectAtIndex:indexPath.row];
if ([tmpDictn objectForKey:#"titre"] != nil)
{
cell.label.text = [tmpDictn objectForKey:#"titre"];
}else{
cell.label.text = #"tmpDictn does not contain data";
}
}else{
cell.label.text = #"jsonArray does not contain data";
}
return cell;
}
How wrong could it be the code bellow:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *array = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id currentObject in array) {
if ([currentObject isKindOfClass:[self class]]) {
self = [currentObject retain];
}
}
return self;
}
I'm trying to bring up a custom UITableViewCell from nib file, the problem is that Leaks Instruments says there's a leak inside:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CPVideoGenTVCell *cell = (CPVideoGenTVCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CPVideoGenTVCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.delegate = self;
cell.titleLbl.textColor = [UIColor colorWithRed:0.992 green:0.933 blue:0.0 alpha:1.0];
}
CPTempVideo *aVideo = [self.videos objectAtIndex:indexPath.row];
cell.seasonLbl.text = [NSString stringWithFormat:#"Season %#", [self romanNumberFromArabic:aVideo.season]];
cell.titleLbl.text = [NSString stringWithFormat:#"%2i - \"%#\"",aVideo.idVideo, aVideo.chapterName];
cell.managedImg.url = aVideo.thumbnail;
[[CPDataManager sharedDataManager] manageImage:cell.managedImg];
return cell;
}
think the problem is with retain, but don't understand why are you doing this crazy stuff with initWithStyle..
if ([currentObject isKindOfClass:[self class]]) {
self = currentObject;
}
There's an alternative I've found:
+ (id)cellWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *array = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id currentObject in array) {
if ([currentObject isKindOfClass:[self class]]) {
return currentObject;
}
}
return nil;
}
just return an autoreleased object and take care of that inside cellForRowAtIndexPath:
CPTempHeadCell *headCell = (CPTempHeadCell *)[tableView dequeueReusableCellWithIdentifier:HeadCellIdentifier];
if (headCell == nil) {
headCell = [CPVideoGenTVCell cellWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];