I am using the following function to do a search using a SearchDisplayController
- (void)handleSearchForTerm:(NSString *)searchTerm{
[self.searchResults removeAllObjects]; // First clear the filtered array.
FMDatabase *db = [FMDatabase databaseWithPath:[Utility getDatabasePath]];
[db open];
FMResultSet *results = [db executeQuery: [NSString stringWithFormat:#"SELECT * FROM periods where (searchstartyear <= %#) AND (searchendyear >= %#)", searchTerm, searchTerm]];
NSMutableArray *array = [[NSMutableArray alloc] init ];
[array removeAllObjects];
while ([results next]) {
Periods *searchPeriod = [[Periods alloc] init];
searchPeriod.periodname = [results stringForColumn:#"PeriodName"];
searchPeriod.startyear = [results stringForColumn:#"StartYear"];
searchPeriod.endyear = [results stringForColumn:#"EndYear"];
searchPeriod.thumb = [results stringForColumn:#"Thumb"];
searchPeriod.childid = [results stringForColumn:#"ChildID"];
[array addObject:searchPeriod];
}
[self.searchResults addObject:array];
[db close];}
Periods is an object
#import <UIKit/UIKit.h>
#interface Periods : NSObject
#property (nonatomic,strong) NSString *periodname;
#property (nonatomic,strong) NSString *startyear;
#property (nonatomic,strong) NSString *endyear;
#property (nonatomic,strong) NSString *thumb;
#property (nonatomic,strong) NSString *childid;
#end
I get the NSInvalidArgumentException - unrecognized selector sent to instance when the following code is executed:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PeriodsCell";
UITableViewCell *cell = [self.mainTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
if (tableView != [[self searchDisplayController] searchResultsTableView])
{
NSMutableArray *array = [periodsdataarray objectAtIndex:indexPath.section];
NSMutableDictionary *dictionary = [array objectAtIndex:indexPath.row];
UILabel *childIDLabel = (UILabel *)[cell viewWithTag:999];
childIDLabel.text = [dictionary valueForKey:#"ChildID"];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
titleLabel.text = [dictionary valueForKey:#"PeriodName"];
UILabel *previewLabel = (UILabel *)[cell viewWithTag:101];
previewLabel.text = [NSString stringWithFormat:#"%# - %#",[dictionary valueForKey:#"StartYear"],[dictionary valueForKey:#"EndYear"]];
UIImageView *imageview = (UIImageView *)[cell viewWithTag:102];
[imageview setImage:[UIImage imageNamed:[dictionary valueForKey:#"Thumb"]]];
}
else
{
Periods *periodcell = [self.searchResults objectAtIndex:indexPath.row];
cell.tag = 666;
UILabel *childIDLabel = (UILabel *)[cell viewWithTag:999];
childIDLabel.text = periodcell.childid;
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
titleLabel.text = periodcell.periodname;
UILabel *previewLabel = (UILabel *)[cell viewWithTag:101];
previewLabel.text = [NSString stringWithFormat:#"%# - %#",periodcell.startyear,periodcell.endyear];
UIImageView *imageview = (UIImageView *)[cell viewWithTag:102];
[imageview setImage:[UIImage imageNamed:periodcell.thumb]];
}
return cell;
}
...and more specifically when this line is executed:
childIDLabel.text = periodcell.childid;
What I am doing wrong?
The error I was making was at the handleSearchForTerm function.
I was using the NSMutableArray *array to hold the values of my Periods object and then I was adding the array to my searchResults array (expecting that the searchResults was holding Periods). The solution was as simple as adding Periods directly to my searchResults array and ditching array at all...
Related
working as a new person in json i want to show data in tableview cell but when i am populating my table view cell it is giving an exception mentioned above. i had asked this question previously but not get exact solution
i am getting response like this in view did load
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
NSLog (#"Count %d", [[response objectForKey:#"messageResponse"] length] );
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSArray *firstarray=[[[response objectForKey:#"messageResponse"] objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
// [self.inboxmessagesarray addObject:messages];
}
[self.activitiesTableView_ reloadData];
}
but when i populate my cell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *tableviewidentifier = #"cell";
tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1){
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"messageId"];
return cell;
}
it is giving an exception . thanx in advance really stuck in it for many days.
Change your self.lblArray for loop into inboxmessagesGetSuccess method
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSArray *firstarray=[[[response objectForKey:#"messageResponse"] objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
[self.inboxmessagesarray addObject:messages];
}
for (int i=0; i<self.inboxmessagesarray.count; i++)
{
[self.lblArray addObject:[NSString stringWithFormat:#"cell Number %d",i]];
}
[self.activitiesTableView_ reloadData];
}
Try this
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
if(response && response[#"messageResponse"])
{
NSArray *messageResponseList = response[#"messageResponse"];
if(messageResponseList && [messageResponseList count]>=1)
{
NSLog (#"Count %lu", (unsigned long)[messageResponseList count]);
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSDictionary *message = [messageResponseList objectAtIndex:1];
if(message && message[#"messages"])
{
NSArray *firstarray=[[messageResponseList objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
[self.inboxmessagesarray addObject:messages];
}
}
}
}
[self.activitiesTableView_ reloadData];
}
instead of having:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.lblArray.count;
}
u should probably have:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.inboxmessagesarray.count;
}
As it is now, your tableview tries to populate when app loads before -(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response method gets called, so your inboxmessagesarray is empty at this point, but your datasource is telling uitableview that it should have lblArray.count cells, and that array isn't empty.
When trying to get a object from an mutable array to et the values for that row in a tableview I get the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[KCNote copyWithZone:]:
unrecognized selector sent to instance 0x15589f60'
Below is my code, I had a look about this error and most places talk about issues copying data structures from the object to the new one however the objects contents is just intergers and strings as you can see below.
KCNote.h
#import <Foundation/Foundation.h>
#interface KCNote : NSObject
#property (nonatomic) NSInteger NoteID;
#property (nonatomic, strong) NSString *Note;
#property (nonatomic, strong) NSString *Author;
#property (nonatomic, strong) NSString *Date;
#end
Code in my view controller for the table.
NSMutableArray *Notes;
- (void)viewDidLoad
{
Notes = [[NSMutableArray alloc] init];
...
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"notecell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
// Configure the cell...
KCNote *note = [Notes objectAtIndex:indexPath.row];
UILabel *Author =(UILabel *) [cell viewWithTag:1];
UILabel *Date = (UILabel *) [cell viewWithTag:2];
UILabel *Note = (UILabel *) [cell viewWithTag:3];
Author.text = note.Author;
Date.text = note.Date;
Note.text = note.Note;
return cell;
}
Notes are added to the array using:
-(void)getNotes:(NSInteger)courseid{
[Notes removeAllObjects];
FMResultSet *s;
s = [db executeQuery:#"SELECT * FROM notes WHERE CourseID =?;", [NSString stringWithFormat:#"%d", courseid]];
//s = [db executeQuery:#"SELECT * FROM notes;"];
if ([db hadError]) {
NSLog(#"DB Error %d: %#", [db lastErrorCode], [db lastErrorMessage]);
}
while ([s next]) {
NSInteger NoteID = [s intForColumnIndex:0];
NSString *Note = [s stringForColumnIndex:2];
NSString *Author = [s stringForColumnIndex:3];
NSString *date = [s stringForColumnIndex:4];
KCNote *note = [KCNote new];
note.NoteID = NoteID;
note.Note = note;
note.Author = Author;
note.Date = date;
[Notes addObject:note];
}
[self.tbl_notes reloadData];
}
I use a custom tablecell, labels and images are connected with tags.
If i add
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]
it destroys my tableview. the image destroys and the background-color.
here are the differences:
Does anyone have any idea where the problem could be?
Thanks
EDIT:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if ([self labelCellNib]) {
[[self labelCellNib] instantiateWithOwner:self options:nil];
} else {
[[NSBundle mainBundle] loadNibNamed:#"LabelCell" owner:self options:nil];
}
cell = self.labelCell;
self.labelCell = nil;
}
static NSDateFormatter *dateFormatter = nil;
if (dateFormatter == nil)
dateFormatter = [[NSDateFormatter alloc] init];
static NSCalendar *calendar;
if(calendar == nil)
calendar= [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSString * timeStampString = [sqlTime objectAtIndex:indexPath.row];
NSTimeInterval _interval=[timeStampString doubleValue];
NSDate *createdAt = [NSDate dateWithTimeIntervalSince1970:_interval];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
// Datum in die Tabellen-Zelle einfügen
UILabel *label4 = (UILabel *)[cell viewWithTag:LABEL4];
label4.text = [NSString stringWithFormat:#"%#", [dateFormatter stringFromDate:createdAt]];
// Configure the cell...
UILabel *label1 = (UILabel *)[cell viewWithTag:LABEL1];
label1.text = [NSString stringWithFormat:#"%# %#", [sqlData objectAtIndex:indexPath.row], sonderzeichen];
UILabel *label2 = (UILabel *)[cell viewWithTag:LABEL2];
label2.text = [NSString stringWithFormat:#"Preis pro %#: %# €", sonderzeichen, [sqlPreis objectAtIndex:indexPath.row]];
UILabel *label3 = (UILabel *)[cell viewWithTag:LABEL3];
UIImageView *image = (UIImageView *)[cell viewWithTag:IMAGE_TAG];
if (indexPath.row==[itemsArray count]-1) {
image.image = [UIImage imageNamed:#"default.png"];
label3.text = #"-";
} else if ([itemsArray count]>1) {
int data_old = [[NSString stringWithFormat:#"%#", [sqlData objectAtIndex:indexPath.row]] intValue];
int data_new = [[NSString stringWithFormat:#"%#", [sqlData objectAtIndex:indexPath.row+1]] intValue];
label3.text = [NSString stringWithFormat:#"%i", data_old-data_new];
NSLog(#"%d -- %d", data_old, data_new);
if (data_new>data_old) {
image.image = [UIImage imageNamed:#"pfeil_runter.png"];
} else if (data_new<data_old) {
image.image = [UIImage imageNamed:#"pfeil_hoch.png"];
} else {
image.image = [UIImage imageNamed:#"minus.png"];
}
}
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
cell.contentView.backgroundColor = indexPath.row % 2? [UIColor colorWithRed:228.0/255.0 green:244.0/255.0 blue:199.0/255.0 alpha:1]:[UIColor whiteColor];
return cell;
}
You need to set the background color of the cell, rather than the contentView, but this doesn't work in cellForRowAtIndexPath. It needs to be in willDisplayCell:forRowAtIndexPath:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = indexPath.row % 2? [UIColor colorWithRed:228.0/255.0 green:244.0/255.0 blue:199.0/255.0 alpha:1]:[UIColor whiteColor];
}
As far as the images getting squashed, that has to do with the size of your subviews, and their constraints. I think you can fix those by giving width constraints to two of your labels (a pair over and under each other), but make their priority <1000, so when the accessory view is added, the width of those labels will get smaller. Also give the image view on the left a fixed width.
I am using asyncimageview classes nicely provided by: http://www.markj.net/iphone-asynchronous-table-image/
I am getting image urls from a json file and loading each image to a cell.
Problem:
When i scroll up, and scroll back down to the same cell, the image reloads (disappears and appears again). I can't figure out why the image keeps reloading? Does anyone have suggestions or a solution to how I could make it stop? Thanks in advance!
// Asks the data source to return a cell to insert in a particular table view location
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Gets the current news article
NewsArticle *theCurrentArticle = [self.listofNewsArticles objectAtIndex:[indexPath row]];
//Gets the title from the current article
NSString *theTitle = theCurrentArticle.title;
//Gets the image url
NSString *imageUrl = theCurrentArticle.imageURL;
//Gets the description of the current news article
NSString *theDescription = theCurrentArticle.description;
NewsCustomCell *cell = (NewsCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"NewsContent"];
__block NewsCustomCell *aCell;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (cell == nil) {
aCell = (NewsCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"NewsContent"];
} else {
AsyncImageView* oldImage = (AsyncImageView*)
[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(5, 5, 100, 100)];
imageView.tag = 999;
dispatch_async(dispatch_get_main_queue(), ^{
[imageView loadImageFromURL:[NSURL URLWithString:imageUrl]];
[cell.contentView addSubview:imageView];
cell.titleLabel.text = theTitle;
cell.descriptionLabel.text = theDescription;
cell.imageLabel.contentMode = UIViewContentModeScaleAspectFill;
});
});
return cell;
}
Heres what the current app looks like:
Solution:
Just worked with this class I finally found.
https://github.com/rs/SDWebImage
This handles caching, async downloads. Wish I found this sooner..
I hope you have Write AsyncImageView and ImageCache and ImageCacheObject classes.
Write this code inside cellForRowAtIndexPath:
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Quest_Forum *Quest_ForumObj=[queArr objectAtIndex:i+indexPath.row];
// NSLog(#"cell for row at... i val.. %d",i+indexPath.row);
for(UIView * view in cell.contentView.subviews){
if([view isKindOfClass:[AsyncImageView class]])
{
// NSLog(#"remove old images");
[view removeFromSuperview];
view = nil;
}
}
AsyncImageView *asyncImageView = nil;
UIImageView *cellImage = (UIImageView *)[cell viewWithTag:1]; // Inside tableview i have taken tableviewcell and given tag 1 to that imageview
asyncImageView = [[AsyncImageView alloc] initWithFrame:cellImage.frame] ;
[asyncImageView loadImageFromURL:Quest_ForumObj.Quest_Image];
asyncImageView.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:asyncImageView];
UILabel *lblQuest = (UILabel *)[cell viewWithTag:2]; // Given tag 2 to the label inside tableViewCell
lblQuest.text=Quest_ForumObj.Question;
In ImageCacheObject.h
#class ImageCacheObject;
#interface ImageCache : NSObject
{
NSUInteger totalSize; // total number of bytes
NSUInteger maxSize; // maximum capacity
NSMutableDictionary *myDictionary;
}
#property (nonatomic, readonly) NSUInteger totalSize;
-(id)initWithMaxSize:(NSUInteger) max;
-(void)insertImage:(UIImage*)image withSize:(NSUInteger)sz forKey:(NSString*)key;
-(UIImage*)imageForKey:(NSString*)key;
In ImageCacheObject.m
#import "ImageCacheObject.h"
#synthesize totalSize;
-(id)initWithMaxSize:(NSUInteger) max
{
if (self = [super init])
{
totalSize = 0;
maxSize = max;
myDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
-(void)dealloc // Don't write this method if you are using ARC
{
[myDictionary release];
[super dealloc];
}
-(void)insertImage:(UIImage*)image withSize:(NSUInteger)sz forKey:(NSString*)key
{
// NSLog(#"count of insert image%d",sz);
ImageCacheObject *object = [[ImageCacheObject alloc] initWithSize:sz Image:image];
while (totalSize + sz > maxSize)
{
NSDate *oldestTime;
NSString *oldestKey;
for (NSString *key in [myDictionary allKeys])
{
ImageCacheObject *obj = [myDictionary objectForKey:key];
if (oldestTime == nil || [obj.timeStamp compare:oldestTime] == NSOrderedAscending)
{
oldestTime = obj.timeStamp;
oldestKey = key;
}
}
if (oldestKey == nil)
break; // shoudn't happen
ImageCacheObject *obj = [myDictionary objectForKey:oldestKey];
totalSize -= obj.size;
[myDictionary removeObjectForKey:oldestKey];
}
[myDictionary setObject:object forKey:key];
[object release];
}
-(UIImage*)imageForKey:(NSString*)key
{
ImageCacheObject *object = [myDictionary objectForKey:key];
if (object == nil)
return nil;
[object resetTimeStamp];
return object.image;
}
In ImageCacheObject.h
#interface ImageCacheObject : NSObject
{
NSUInteger size; // size in bytes of image data
NSDate *timeStamp; // time of last access
UIImage *image; // cached image
}
#property (nonatomic, readonly) NSUInteger size;
#property (nonatomic, retain, readonly) NSDate *timeStamp;
#property (nonatomic, retain, readonly) UIImage *image;
-(id)initWithSize:(NSUInteger)sz Image:(UIImage*)anImage;
-(void)resetTimeStamp;
In ImageCacheObject.m
#synthesize size;
#synthesize timeStamp;
#synthesize image;
-(id)initWithSize:(NSUInteger)sz Image:(UIImage*)anImage
{
if (self = [super init])
{
size = sz;
timeStamp = [[NSDate date] retain];
image = [anImage retain];
}
return self;
}
-(void)resetTimeStamp
{
[timeStamp release];
timeStamp = [[NSDate date] retain];
}
-(void) dealloc
{
[timeStamp release];
[image release];
[super dealloc];
}
My NSMutableArray seems to be releasing and I can't figure out where, here is my code:
- (void)awakeFromNib {
arrayOfData = [[NSMutableArray alloc] initWithCapacity:0];
[arrayOfData addObject:#"test"];
NSLog(#"array: %#", arrayOfData);
}
All is well here!
Then I create a UITable and add it to the view, then I request some data, everything is normal.
arrayOfData = [response objectForKey:#"results"];
NSLog(#"count: %i", [arrayOfData count]);
NSLog(#"success!");
numberOfRows = [arrayOfData count];
[self.myTableView reloadData];
Creating the number of rows works fine too:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"test: %i", numberOfRows);
return numberOfRows;
}
Now accessing my array gets a "message sent to deallocated instance" at that line.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// crashes here!
NSLog(#"array: %i", [arrayOfData count]);
if (numberOfRows){
NSString *filename = [[arrayOfData objectAtIndex:indexPath.row] objectForKey:#"filename"];
NSString *url = [NSString stringWithFormat: #"http://www.web.com/dir/%#", filename];
[cell.imageView setImageWithURL:[NSURL URLWithString:url]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
cell.textLabel.text = #"My Text";
}
return cell;
}
I have also have this in my header, and I used #synthesize as well
#property (nonatomic, retain) NSMutableArray *arrayOfData;
Any help would be appreciated!
It looks like you're reassigning arrayOfData with this line:
arrayOfData = [response objectForKey:#"results"];
If that's what you want, try this instead:
arrayOfData = [[response objectForKey:#"results"] retain];