Cells disappear when scroll down in my UITableView - ios

When I scroll down in my tableView some contents of cells disappear (labels and imageViews).
My code:
-(void)viewWillAppear:(BOOL)animated{
[comentarios removeAllObjects];
NSString *lookup=[NSString stringWithFormat:#"http://my.url"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:lookup]];
[request setHTTPMethod:#"GET"];
NSError *error = nil; NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#",jsonDict);
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come=[[Comentario alloc] init];
come.nick=[[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment=[[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar=[[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
}
[self reloadInputViews];
[self.comentariosTableView reloadData];
}
and
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if( cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
}
// Display recipe in the table cell
UIImageView *avatar = (UIImageView *)[cell viewWithTag:100];
avatar.image = [UIImage imageNamed:[[comentarios objectAtIndex:indexPath.row] avatar]];
UILabel *nick = (UILabel *)[cell viewWithTag:101];
nick.text =[[comentarios objectAtIndex:indexPath.row] nick];
UILabel *comment = (UILabel *)[cell viewWithTag:102];
comment.text = [[comentarios objectAtIndex:indexPath.row] comment];
UIButton *sinvoto = (UIButton *)[cell viewWithTag:103];
UIButton *ticket = (UIButton *)[cell viewWithTag:104];
return cell;
}
I can't see the mistake, please help me.
Thank you in advance
EDIT Nª1
just changed this
ViewController.m
#import "ViewController.h"
#import "SimpleTableCell.h"
#interface ViewController (){
NSMutableArray *comentarios;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.comenatrioTableView.delegate=self;
self.comenatrioTableView.dataSource=self;
self.automaticallyAdjustsScrollViewInsets = NO;
UIImage *plus=[[UIImage imageNamed:#"megafono.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc] initWithImage:plus style:UIBarButtonItemStylePlain target:self action:#selector(comenta:)];
self.navigationController.navigationBar.barTintColor=[UIColor colorWithRed:204.0/255.0 green:0.0/255.0 blue:00.0/255.0 alpha:1.0f];
comentarios=[[NSMutableArray alloc] init];
[self reloadInputViews];
}
-(void)viewWillAppear:(BOOL)animated{
[comentarios removeAllObjects];
NSString *lookup=[NSString stringWithFormat:#"http://myURL"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:lookup]];
[request setHTTPMethod:#"GET"];
NSError *error = nil; NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#",jsonDict);
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come=[[Comentario alloc] init];
come.nick=[[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment=[[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar=[[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
}
[self reloadInputViews];
}
-(void)viewDidAppear:(BOOL)animated{
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [comentarios count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 110;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
Comentario *comentario=[[Comentario alloc] init];
comentario =[comentarios objectAtIndex:indexPath.row];
cell.avatar.image=[UIImage imageNamed:[comentario avatar]];
cell.nick.text=[comentario nick];
cell.comment.text =[comentario comment];
return cell;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
-(void)comenta:(id)sender{
[self performSegueWithIdentifier:#"goComment" sender:self];
}
#end
and ViewController.h
#import <UIKit/UIKit.h>
#import "Comentario.h"
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *comenatrioTableView;
#end
Edit Nª3
The proble is when I scroll down, the information of cells become nil but comentarios Array have the information.
Edit Nª4
here is the project https://github.com/QuimeraKoke/BANG-

I have a couple of other suggestions that will improve your code.
You have to call super in viewDidAppear and viewWillAppear methods:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
}
Instead of using:
Comentario *comentario = [[Comentario alloc] init];
comentario = [comentarios objectAtIndex:indexPath.row];
with:
Comentario *comentario = [comentarios objectAtIndex:indexPath.row];
Finally, you should check your dataSource:
for (int i=0; i<[jsonDict count]; i++) {
Comentario *come = [[Comentario alloc] init];
come.nick = [[jsonDict objectAtIndex:i] objectForKey:#"nick"];
come.comment = [[jsonDict objectAtIndex:i] objectForKey:#"content"];
come.avatar = [[jsonDict objectAtIndex:i] objectForKey:#"color"];
[comentarios addObject:come];
NSLog(#"nick = %#, comment = %#, avatar = %#", come.nick, come.comment, come.avatar);
}
EDIT:
Instead of using:
#interface Comentario : NSObject
#property (weak,nonatomic) NSString *nick;
#property (weak,nonatomic) NSString *comment;
#property (weak,nonatomic) NSString *avatar;
#end
you should use:
#interface Comentario : NSObject
#property (copy,nonatomic) NSString *nick;
#property (copy,nonatomic) NSString *comment;
#property (copy,nonatomic) NSString *avatar;
#en
Your problem has been resolved.
Copy
copy is required when the object is mutable. Use this if you need the
value of the object as it is at this moment, and you don't want that
value to reflect any changes made by other owners of the object. You
will need to release the object when you are finished with it because
you are retaining the copy.
Weak
weak is similar to strong except that it won't increase the reference
count by 1. It does not become an owner of that object but just holds
a reference to it. If the object's reference count drops to 0, even
though you may still be pointing to it here, it will be deallocated
from memory.
This is a good website to learn about strong and weak for iOS 5.
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1
In addition to the above problem,your constrains of the SimpleTableCell is also incorrect:
You should go to the Main.storyboard and check it.(In Interface Builder Select the Compact Width and Compact Height Size Class)

The tableView:cellForRowAtIndexPath: code you're using is pretty old.
I'd suggest creating a custom UITableViewCell class, with properties for your labels, image, and buttons.
#interface MyTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *nick;
#property (nonatomic, weak) IBOutlet UILabel *comment;
#property (nonatomic, weak) IBOutlet UIImageView *avatar;
#property (nonatomic, weak) IBOutlet UIButton *sinvoto;
#property (nonatomic, weak) IBOutlet UIButton *ticket;
#end
In your storyboard, set that cell's class to your custom tableViewCell, and connect its IBOutlets to the storyboard cell's labels, image, and buttons. This will eliminate having to use tags.
Change the dequeueReusableCellWithIdentifier: call to:
MyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
This will always return a cell, so you will never have to check for nil.
Now you can directly set the cell's properties:
cell.avatar.image = [UIImage imageNamed:[[comentarios objectAtIndex:indexPath.row] avatar]];
cell.nick.text =[[comentarios objectAtIndex:indexPath.row] nick];
cell.comment.text = [[comentarios objectAtIndex:indexPath.row] comment];
Update:
This line (has to do with changing the keyboard) is unnecessary and can be removed:
[self reloadInputViews];
Is there a reason why you are using a UIViewController (with a tableView that you added), instead of simply using a UITableViewController?
The UITableViewController knows how to adjust its insets to account for top and bottom bars (and you would set its automaticallyAdjustsScrollViewInsets to YES).
After making the changes that Banning suggests, you may be ok. I can't see any other reason why the cells would be blank after scrolling.
If it's still happening, you should post your Comentario class, so we can see if an issue with that code is affecting the stored data.

Related

UITableViewCells don't take custom value

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.

After reloadRowsAtIndexPaths Custom UITableViewCell appearance doesn't change

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.

UISlider Value Automatically assigned while scrolling in UITable View Cell

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;
}

Memory keep increasing when the UITableView scrolling

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.

Queue a NSMutableArray into a NString as a loop?

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.

Resources