I'm trying to make an item feed with a UITableView and some JSON objects,
but when I try filling an instance of my custom cell with the JSON data, the UILabels won't change their text.
The JSON has been tested and works. It goes through the loop and creates the right amount of rows. But the text isn't changing to the text from the JSON file.
Here's my code:
feed.m
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *FeedURL = [NSURL URLWithString:#"http://www.personeelsapp.jordivanderhek.com/company/bijcasper/nieuws.json"];
NSData *jsonData = [NSData dataWithContentsOfURL:FeedURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", dataDictionary);
self.posts = [NSMutableArray array];
PostsArray = [dataDictionary objectForKey:#"feed"];
for (NSDictionary *bpdDictionary in PostsArray) {
// make new post object
FeedPosts *posts = [FeedPosts InitPost];
NSLog(#"feed check %#" ,[bpdDictionary objectForKey:#"name"]);
posts.postTitle = [bpdDictionary objectForKey:#"name"];
posts.postProfilepic = [bpdDictionary objectForKey:#"profilePic"];
posts.postDatum = [bpdDictionary objectForKey:#"timeStamp"];
posts.postMessage = [bpdDictionary objectForKey:#"status"];
posts.postImage = [bpdDictionary objectForKey:#"image"];
[self.posts addObject:posts];
}
}
[…]
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
return [self.posts count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Cellindentifier = #"PostCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Cellindentifier forIndexPath:indexPath];
// Configure the cell...
FeedPosts *posts = [self.posts objectAtIndex:indexPath.row];
cell.postTitle.text = #"test title";
cell.postDatum.text = posts.postDatum.text;
cell.postMessage.text = posts.postMessage.text;
return cell;
}
}
FeedPosts.h
#property (strong, nonatomic) IBOutlet UILabel *postTitle;
#property (strong, nonatomic) IBOutlet UILabel *postMessage;
#property (strong, nonatomic) IBOutlet UIImageView *postImage;
#property (strong, nonatomic) IBOutlet UIImageView *postProfilepic;
#property (strong, nonatomic) IBOutlet UILabel *postDatum;
// designated init
+ (id) InitPost;
FeedPosts.m
+ (id) InitPost {
// init new feed item
return [[self alloc]init];
}
have been getting the following error:
-[__NSCFString text]: unrecognized selector sent to instance
What am I doing wrong?
You have declared several UILabels in FeedPosts.
#property (strong, nonatomic) IBOutlet UILabel *postTitle;
In the following code, you assign NSString (text) to the label object:
FeedPosts *posts = [FeedPosts InitPost];
NSLog(#"feed check %#" ,[bpdDictionary objectForKey:#"name"]);
posts.postTitle = [bpdDictionary objectForKey:#"name"];
Instead, you should set the text for those labels:
posts.postTitle.text = [bpdDictionary objectForKey:#"name"];
Same goes for postMessage and postDatum.
I have a custom UITableViewCell created in a .xib and add it to a TableView. The cell contains a Button to download some data. On Button click the download starts and the Button disappears to show a cancel Button and a custom View with a download progress. After the download is finished I update my model and reload the rows in the visible area of the app.
When I debug, I see that the cellForRowAtIndexPath-methode get called and the model got updated. This means the cancel-Button and the progress-View get set hidden = YES; But they don't disappear. After I scroll the cell out of view and back in, the progress-View is hidden but the cancel-Button not.
The TableView Methodes:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifierHeaderCell = #"PodcastListHeaderCell";
static NSString *cellIdentifierBodyCell = #"PodcastListBodyCell";
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE, d MMM yyyy HH:mm:ss Z"];
if(indexPath.row == 0) {
MGPodcastListHeaderCell *cell = (MGPodcastListHeaderCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifierHeaderCell];
if (cell == nil)
{
...
}
return cell;
}
else {
MGPodcastListBodyCell *cell = (MGPodcastListBodyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifierBodyCell];
if (cell == nil) {
UIViewController *controller = [[UIViewController alloc] initWithNibName:#"MGPodcastListBodyCell" bundle:nil];
cell = (MGPodcastListBodyCell *)controller.view;
NSMutableDictionary *mediaIntem = self.mediaData[(NSUInteger) (indexPath.row-1)];
cell.mediaTitleLabel.text = mediaIntem[#"title"];
NSDate *date = [dateFormat dateFromString:mediaIntem[#"pubDate"]];
cell.pubDateLabel.text = [date descriptionWithLocale:[NSLocale currentLocale]];
cell.durationLabel.text = mediaIntem [#"duration"];
cell.accessoryType = UITableViewCellAccessoryDetailButton;
cell.podcastId = (NSInteger) (indexPath.row-1);
cell.cellPlayState = [[MGPlayState alloc] initWithPlayState:(NSInteger) [mediaIntem[#"playState"] integerValue]];
[cell setPodcastCellDelegate:self];
}
return cell;
}
}
-(void) downloadButtonPressedOfCell:(NSInteger)podcastId {
APConnection *con = [[APConnection alloc] init];
BOOL reachable = [con reachableHost];
if (reachable)
{
//============Get Media Item =============================
NSMutableDictionary *mediaDict = self.mediaData[(NSUInteger)podcastId];
MGPlayState *pl_state = [[MGPlayState alloc] initWithPlayState:[[mediaDict objectForKey:#"playState"] integerValue]];
NSString *urlString = [mediaDict objectForKey:#"mediaLink"];
/// Finde Pathname
NSString *fileName = [urlString lastPathComponent];
NSLog(#"LastFileComponent: %#", fileName);
NSString *pathName = [NSString stringWithFormat:#"%#/%#",
[APFilePath getMediaContentFolder],
fileName];
/// Request und Operation
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:pathName
append:NO];
//// save Operation for cancle
NSMutableDictionary *operationDict = [[NSMutableDictionary alloc] init];
[operationDict setObject:operation
forKey:#"operation"];
[operationDict setObject:[NSNumber numberWithInt:podcastId]
forKey:#"myIndexPath"];
[operationDict setObject:[mediaDict objectForKey:#"mediaLink"]
forKey:#"mediaLink"];
[[self operationDictArr] addObject:operationDict];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSIndexPath *path = [NSIndexPath indexPathForRow:podcastId+1 inSection:0];
MGPodcastListBodyCell *myCell = (MGPodcastListBodyCell *) [self.podcastListTable cellForRowAtIndexPath:path];
[pl_state setToPlayState:PlayStateDefaultDownloadFinished];
myCell.cellPlayState = pl_state;
//============ Get mediaItem =============================
self.mediaData[(NSUInteger)podcastId][#"playState"] = #4;
/// remove operation from dict
[[self operationDictArr] removeObject:operationDict];
[self.podcastListTable reloadRowsAtIndexPaths:[self.podcastListTable indexPathsForVisibleRows]
withRowAnimation:UITableViewRowAnimationNone];
[self.podcastListTable setNeedsDisplay];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog (#"Error downloadMovie: %#", error);
}];
[operation start];
}
else
{
[EZToastView showToastMessage:NSLocalizedString(#"keineVerbindungKey", "")
withAlignment:EZToastViewAlignmentCenter];
}
}
Custom Cell:
//// MGPodcastListBodyCell.h
#protocol MGPodcastCellDelegate <NSObject>
#required
-(void) downloadButtonPressedOfCell: (NSInteger) podcastId;
-(void) cancleDownloadButtonPressedOfCell: (NSInteger) podcastId;
#end
#interface MGPodcastListBodyCell : UITableViewCell
#property (nonatomic, retain) id <MGPodcastCellDelegate> podcastCellDelegate;
#property (weak, nonatomic) IBOutlet UILabel *mediaTitleLabel;
#property (weak, nonatomic) IBOutlet UILabel *durationLabel;
#property (weak, nonatomic) IBOutlet UIButton *downloadMediaButton;
#property (weak, nonatomic) IBOutlet UIButton *cancelMediaDownloadButton;
#property (weak, nonatomic) IBOutlet MGProgressDownloadView *progressDownloadView;
#property (weak, nonatomic) IBOutlet UILabel *pubDateLabel;
#property (strong, nonatomic) MGPlayState *cellPlayState;
#property (nonatomic) NSInteger podcastId;
- (IBAction) downloadButtonPressed:(UIButton *)sender;
- (IBAction) cancleMediaDownloadButonPressed:(UIButton *)sender;
#end
//MGPodcastListBodyCell.m
#implementation MGPodcastListBodyCell
#synthesize cellPlayState = _cellPlayState;
- (void)setCellPlayState:(MGPlayState *) cellPlayState {
_cellPlayState = cellPlayState;
[self playStateChanged];
}
- (void)awakeFromNib {
[self setup];
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setup];
}
return self;
}
- (void)setup
{
UIView *customBackgroundView = [[UIView alloc] init];
customBackgroundView.backgroundColor = [APAppearence sharedInstance].tableCellBackgroundColorMB;
self.backgroundView = customBackgroundView;
self.mediaTitleLabel.textColor = [APAppearence sharedInstance].tableCellMainlabelTextColorMB;
self.durationLabel.textColor = [APAppearence sharedInstance].standardDarkGrayColorMB;
self.tintColor = [APAppearence sharedInstance].tableCellMainlabelTextColorMB;
[self playStateChanged];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void) playStateChanged {
self.downloadMediaButton.hidden = self.cellPlayState.playButtonHidden;
[self.downloadMediaButton setNeedsDisplay];
self.cancelMediaDownloadButton.hidden = self.cellPlayState.cancelButtonHidden;
[self.cancelMediaDownloadButton setNeedsDisplay];
self.progressDownloadView.hidden = self.cellPlayState.progressViewHidden;
[self setNeedsDisplay];
}
- (IBAction) downloadButtonPressed:(UIButton *)sender {
[self.podcastCellDelegate downloadButtonPressedOfCell: self.podcastId];
}
- (IBAction) cancleMediaDownloadButonPressed:(UIButton *)sender {
[self.podcastCellDelegate cancleDownloadButtonPressedOfCell: self.podcastId];
}
#end
So if somebody can tell me, what to do more than reload the cell to update the View I would be very grateful. Thanks.
When you reload the cell you have code as follows...
MGPodcastListBodyCell *cell = (MGPodcastListBodyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifierBodyCell];
if (cell == nil) {
....
}
In your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
method. Because the cell is being reused the cell won't be nil the second time around and therefore isn't being updated with any new information.
You need to do something when the cell is not nil to refresh it.
I found the bug. It wasn't a problem with the reloadRowAtIndexPath method. It was a concurrency problem. The download finish state got overwritten by the download progress thread just at the end of downloading and the state was set back to download.
So, thank you all for your help.
I am Working on a Program which looks like this:
There is a Table View i that there is a Custom Table View Cell.
And there is a UISlider , Label and Button on Custom View Cell
Now the Problem is when i slide the UISlider of Cell : 0 than the UISlider at Cell : 12(or later Cell) is Automatically assigned the Cell:0's UISlider Value(Thanks To ARC..!!).
Now anyone have a solution so that the later cell's UISlider doest change while i change value of upper Cells.
P.S. When i assigned a UiSlider Value at Cell:0 and Scroll Up and Down it is automatically random Cell's UISlider Value is changing.
Google Drive Link of Project :
Slider Program
I am Using xCode 5 and iOS SDK 7.
Thanks for Reading.
Edit:
cellForRowAtIndexPath Method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableCell = #"Cell";
CustomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableCell];
if (cell == nil) {
cell = [[CustomeTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableCell];
}
NSString *strName = [NSString stringWithFormat:#"Cell : %d",indexPath.row];
// NSLog(#"strName :%# , SliderValue : %d",strName , (int)cell.mySlider.value);
for (int i = 0; i < arrSlider.count; i++) {
NSString *strTag = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"tag"]];
NSString *myIndexPath = [NSString stringWithFormat:#"%d",indexPath.row];
if([strTag isEqualToString:myIndexPath])
{
NSString *strValue = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"value"]];
cell.mySlider.value = [strValue floatValue];
NSLog(#"Tag Value : %# , value %f", strTag , [strValue floatValue]);
}
}
[cell.btnCell setTitle:strName forState:UIControlStateNormal];
cell.btnCell.tag = indexPath.row;
cell.mySlider.tag = indexPath.row;
[cell.mySlider addTarget:self action:#selector(customSliderValue:) forControlEvents:UIControlEventValueChanged];
[cell.btnCell addTarget:self action:#selector(customeBtnClicked:) forControlEvents:UIControlEventTouchDown];
return cell;
}
Use NSMutableDictionary to hold the values of slider then update it from the cellForRowAtIndexPath method i am posting the changes just make changes in your project
in ViewCOntroller.h file
#import <UIKit/UIKit.h>
#import "CustomeTableViewCell.h"
#interface ViewController : UIViewController <UITableViewDataSource ,UITableViewDelegate,SliderDelegate>//confirms to delegate
{
//NSArray *tableList;
UITableView *mytableview;
NSInteger SliderChangeValue;
}
#property (strong , nonatomic) IBOutlet UIView *tableDemo;
#property (strong , nonatomic) NSMutableArray *arrSlider;
#property (strong, nonatomic) NSMutableDictionary *sliderDicValues; //add a mutable dictionary
#property (weak, nonatomic) IBOutlet UITableView *myTableView;//add outlet to tableview
#end
in ViewController.mfile
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize arrSlider;
#synthesize sliderDicValues;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// tableList = [NSArray arrayWithObjects:
// #"Cell 1",#"Cell 2",#"Cell 3",#"Cell 4",#"Cell 5",
// #"Cell 6",#"Cell 7",#"Cell 8",#"Cell 9",#"Cell 10",
// #"Cell 11",#"Cell 12",#"Cell 13",#"Cell 14",#"Cell 15",
// #"Cell 16",#"Cell 17",#"Cell 18",#"Cell 19",#"Cell 20",
// nil];
arrSlider = [[NSMutableArray alloc]init];
sliderDicValues = [[NSMutableDictionary alloc]init]; //initilise an mutable dictionary
//[mytableview registerClass:[CustomeTableViewCell class] forCellReuseIdentifier:#"Cell"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//[tableList count]
return 15;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableCell = #"Cell";
CustomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableCell];
if (cell == nil) {
cell = [[CustomeTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableCell];
}
if([self.sliderDicValues objectForKey:[NSString stringWithFormat:#"%d",indexPath.row]]) //check if there is any slided value is present
{
NSNumber *value = [self.sliderDicValues objectForKey:[NSString stringWithFormat:#"%d",indexPath.row]];
[cell.mySlider setValue:value.integerValue]; //set the slider value
[cell.myCellLabel setText:[NSString stringWithFormat:#"%d",value.integerValue]];//and also label
}
else //set to default values
{
[cell.mySlider setValue:(NSInteger)0];
[cell.myCellLabel setText:#"label"];
}
//add a single target don't add double target to slider
cell.sliderDelegate = self;//set the delegate
return cell;
/*
NSString *strName = [NSString stringWithFormat:#"Cell : %d",indexPath.row];
NSLog(#"strName :%# , SliderValue : %d",strName , (int)cell.mySlider.value);
for (int i = 0; i < arrSlider.count; i++) {
NSString *strTag = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"tag"]];
NSString *myIndexPath = [NSString stringWithFormat:#"%d",indexPath.row];
if([strTag isEqualToString:myIndexPath])
{
NSString *strValue = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"value"]];
cell.mySlider.value = [strValue floatValue];
NSLog(#"Tag Value : %# , value %f", strTag , [strValue floatValue]);
}
if ([strTag isEqual:myIndexPath]) {
//NSString *strValue = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]objectForKey:#"value"]];
//NSLog(#"%#",strValue);
NSLog(#"Hello");
//cell.mySlider.value =
}
}
[cell.btnCell setTitle:strName forState:UIControlStateNormal];
cell.btnCell.tag = indexPath.row;
cell.mySlider.tag = indexPath.row;
[cell.mySlider addTarget:self action:#selector(customSliderValue:) forControlEvents:UIControlEventValueChanged];
[cell.btnCell addTarget:self action:#selector(customeBtnClicked:) forControlEvents:UIControlEventTouchDown];
*/
}
//delegate method called from custom cell
- (void)sliderChanged:(CustomeTableViewCell *)cell
{
NSIndexPath *path = [_myTableView indexPathForCell:cell]; //get the indexpath
if(path)//check if valid path
{
SliderChangeValue = cell.mySlider.value;
[self.sliderDicValues setObject:[NSNumber numberWithInt:SliderChangeValue] forKey:[NSString stringWithFormat:#"%d",path.row]]; //set the value in the dictionary later used in the cellForRowAtIndexPath method
}
// SliderChangeValue = (int)sender.value;
NSLog(#"%d",SliderChangeValue);
}
//dont use it
-(void)customSliderValue:(UISlider *)sender{
// NSString *value =[NSString stringWithFormat:#"%d" ,(int)sender.value];
// NSString *tag = [NSString stringWithFormat:#"%d", (int)sender.tag];
//
// NSLog(#"%# %#",value , tag);
//
// [self.dicSilder setObject:value forKey:#"value"];
// [self.dicSilder setObject:tag forKey:#"tag"];
//
// [self.arrSlider addObject:self.dicSilder];
// NSLog(#"%#",self.arrSlider);
SliderChangeValue = (int)sender.value;
NSLog(#"%d",SliderChangeValue);
}
//this is also put a delegate from the cell like slider , just add the another method in the protocol and perform action, if u don't get just comment i will update the code and u hav t modify this method according to your requirement
-(void)customeBtnClicked:(UIButton *)sender
{
NSString *value =[NSString stringWithFormat:#"%d" ,SliderChangeValue];
NSString *tag = [NSString stringWithFormat:#"%d", sender.tag];
//NSLog(#"%# %#",value,tag);
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setObject:value forKey:#"value"];
[dic setObject:tag forKey:#"tag"];
//NSLog(#"%#",dic);
[arrSlider addObject:dic];
NSLog(#"%#",arrSlider);
NSString *sliderTagAtIndexPath = #"";
//NSString *sliderValueAtindexPath = #"";
for (int i = 0; i < arrSlider.count; i++) {
NSString *strTag = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"tag"]];
if([strTag isEqualToString:tag])
{
//NSString *strValue = [NSString stringWithFormat:#"%#",[[arrSlider objectAtIndex:i]valueForKey:#"value"]];
sliderTagAtIndexPath = strTag;
//sliderValueAtindexPath = strValue;
}
}
UIAlertView *myAlertView = [[UIAlertView alloc]initWithTitle:#"Clicked"
message:[NSString stringWithFormat:#"Cell : %# Value: %d", sliderTagAtIndexPath ,SliderChangeValue]
//message:[NSString stringWithFormat:#"Cell : %# Value: %#", sliderTagAtIndexPath ,sliderValueAtindexPath]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[myAlertView show];
}
#end
in CustomeTableViewCell.h file
#import <UIKit/UIKit.h>
//add a custom delegate
#protocol SliderDelegate<NSObject>
- (void)sliderChanged:(id)self;
#end
#interface CustomeTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *myCellLabel;
#property (weak, nonatomic) IBOutlet UISlider *mySlider;
#property (weak, nonatomic) IBOutlet UIButton *btnCell;
#property (weak, nonatomic) id <SliderDelegate>sliderDelegate;
- (IBAction)sliderValuechanged:(UISlider *)sender;
#end
in CustomeTableViewCell.m file
#import "CustomeTableViewCell.h"
#implementation CustomeTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)awakeFromNib
{
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)sliderValuechanged:(UISlider *)sender
{
self.myCellLabel.text = [NSString stringWithFormat:#"%d",(NSInteger)sender.value];
//call the custom delegate each time when slider is slided
if([_sliderDelegate respondsToSelector:#selector(sliderChanged:)])
{
[_sliderDelegate sliderChanged:self]; //passing the entire cell itself
}
}
#end
Hope this helps u .. :)
You don't need to check(set) all the datasource for a Cell , I mean, No need of for loop inside the cellForRowAtIndexPath. just remove it and will work fine .
Try this code it works for me :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = [NSString stringWithFormat:#"%d",indexPath.row];
CustomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[CustomeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
// Write your rest code here
return cell;
}
there is a strange problem I have not met ever
there is an array() including some custom object named MyClass parsed by JSONKit;
when I keep scrolling the tableview the memory will keeping increasing too.
but when replace
cell.textLabel.text = myclass.name;
with
cell.textLabel.text = #"cool";
or
cell.textLabel.text = [NSString stringWithFormate:#"a-%d", indexPath.row];
it's ok the memory with keep stable
but if I use
cell.textLabel.text = [NSString stringWithFormate:#"a-%#-i",myclass.name, indexPath.row];
it also keep increasing;
It will drive my crazy!!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Singers";
OMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
MyClass *myclass = [self.data objectAtIndex:indexPath.row];
if (cell == nil){
cell = [[[OMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
cell.textLabel.text = myclass.name;
return cell;
}
MyClass
there is two class one Base another inherit
Base:
#interface OMBase : NSObject {
NSMutableDictionary *data;
NSString *name;
NSArray *keys;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, copy) NSMutableDictionary *data;
#implementation OMBase
#synthesize data, name;
- (void)setData:(NSMutableDictionary *)adata{
if (data){
[data release];
data = nil;
}
data = [adata mutableCopy];
}
- (void)dealloc{
if (keys){
[keys release];
}
[data release];
[super dealloc];
}
- (id)init{
if (self = [super init]){
self.data = [[[NSMutableDictionary alloc] initWithCapacity:20] autorelease];
}
return self;
}
inherit:
#import "OMBase.h"
#interface OMLyric : OMBase
- (NSString *)songid;
- (NSString *)content;
#import "OMLyric.h"
#implementation OMLyric
- (NSString *)songid{
return [data objectForKey:#"songid"];
}
- (NSString *)content{
return [data objectForKey:#"content"];
}
Seems like your myclass.name getter returns a new allocated object. We can't say more without seeing myclass.
If one had a NSString that needed a userid to be used as a URL for a request:
And one had a NSMutableArray that he wanted to Queue into the above call one at a time? So basically make 3 calls of NSString from the NSMutableArray .
One can check multiple UITableView cells and once completed I can index which cell rows were pushed. That is what userIDArray is used for now I want to make a call with the userID's I got back from userIDArray.
for (NSDictionary* userIDDict in userIDArray)
{
userIDArray = [[NSMutableArray alloc] init]; //I put this line in my viewdidload
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
}
UserIDArray is the NSMutableArray .
This would be the NSLog from the NSMutableArray The Integer would be 1, 2 and 3.
UserID: 1
UserID: 2
UserID: 3
So in other words I would like to take the results from my NSMultiTableArray 1,2 and 3 to use within the NSString :
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=1"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=2"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=3"];
So I would make the first call and wait for a result, and then the second and finally the third.
Can this be done? I have search this link about Queues and this one but I am unsure if those are what I need?
UserDetailViewController.h file:
#interface UserDetailViewController : UIViewController <UITableViewDelegate>{
long long expectedLength;
long long currentLength;
UITableView *userTableView;
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSArray *userIDJson;
#property (strong, nonatomic) NSDictionary *userIDDict;
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#property (nonatomic, strong) NSMutableArray *userIDArray;
#property (nonatomic) NSInteger currentUserIndex;
#end
UserDetailViewController.m file:
#interface UserDetailViewController ()
#end
#implementation UserDetailViewController
#synthesize userIDJson;
#synthesize userIDDict;
#synthesize checkedIndexPath;
#synthesize userIDArray;
#synthesize currentUserIndex;
- (void)viewDidLoad
{
[super viewDidLoad];
userIDArray = [[NSMutableArray alloc] init];
[self.navigationController setNavigationBarHidden:NO];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//return self.loadedSearches.count;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.userIDJson.count;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
}
cell.textLabel.text = self.userIDJson[indexPath.row][#"UserName"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *userStringIndex = [self.userIDJson objectAtIndex:indexPath.row];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[userIDArray addObject:userStringIndex];
}
else
{
thisCell.accessoryType = UITableViewCellAccessoryNone;
[userIDArray removeObject:userStringIndex];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < userIDArray.count) {
NSNumber* userID = [[userIDArray objectForIndex:currentUserIndex]objectForKey:#"UserID"];
//Make the actual request here, and assign the delegate.
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=%#",userID];
self.currentUserIndex++;
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:userProfile]];
NSString *userResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSURL *url = [[NSURL alloc] initWithString: userProfile];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
userIDJson = [NSJSONSerialization JSONObjectWithData:dataURL
options:kNilOptions
error:&error];
}
}
for (userIDDict in userIDArray)
{
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
NSLog(#"%#", userID);
NSArray* userName = [userIDDict objectForKey:#"UserName"];
}
NSURLConnection can take a delegate through the constructor initWithRequest:delegate:. So you need the object that makes the calls conform to that protocol, I'll assume it's a UIViewController. You can use one of the required methods in the delegate to fire up the next request.
For example, assume you have property to indicate the current index.
#property (nonatomic) NSInteger currentUserIndex;
Then in the place that will fire the first request, make the call for the first user. In some delegate method, say connectionDidFinishLoading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < self.userIDArray.count) {
NSNumber* userID = [[self.userIDArray objectAtIndex:self.currentUserIndex] objectForKey:#"UserID"];
self.currentUserIndex++;
//Make the actual request here, and assign the delegate.
}
}
Of course, if your connection calls don't have to be synchronous, you can do it in an easier way.