TablewView Cell all cell in the same row - ios

No storyboard involve in this project
The most problematic part i cant figure out where to solve this.
Im Using SDK.
_msgTableView = [[UITableView alloc] init];
_msgTableView.backgroundColor = [UIColor blackColor];
_msgTableView.delegate = self;
_msgTableView.dataSource = self;
_msgTableView.separatorInset = UIEdgeInsetsZero;
_msgTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_msgTableView.showsVerticalScrollIndicator = NO;
[self.view addSubview:_msgTableView];
this function are called on NSNotification
CGRect moveToRect = CGRectMake(-(msgFrame.origin.x+ msgFrame.size.width), msgFrame.origin.y, msgFrame.size.width, msgFrame.size.height);
[_msgTableView setFrame:moveToRect];
this is called in extended view
[_msgTableView sizeWith:CGSizeMake(screenW, 250)];
[_msgTableView layoutAbove:_bottomView margin:kDefaultMargin];
this is called when new message notify by Notification
[_msgDatas addObject:msg];
if (_msgDatas.count >= 500)
{
NSRange range = NSMakeRange(_msgDatas.count - 100, 100);//只保留最新的100条消息
NSArray *temp = [_msgDatas subarrayWithRange:range];
[_msgDatas removeAllObjects];
[_msgDatas addObjectsFromArray:temp];
[_msgTableView reloadData];
}
else
{
[_msgTableView beginUpdates];
NSIndexPath *index = [NSIndexPath indexPathForRow:_msgDatas.count - 1 inSection:0];
[_msgTableView insertRowsAtIndexPaths:#[index] withRowAnimation:UITableViewRowAnimationAutomatic];
[_msgTableView endUpdates];
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_msgDatas.count-1 inSection:0];
if (indexPath.row < [_msgTableView numberOfRowsInSection:0])
{
[_msgTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
this is the Cell For row at function
MsgTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"LiveTextMessageCell"];
if (cell == nil)
{
cell = [[MsgTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"LiveTextMessageCell"];
}
id msg = _msgDatas[indexPath.row];
if ([msg isKindOfClass:[ILVLiveTextMessage class]])
{
ILVLiveTextMessage *textMsg = (ILVLiveTextMessage *)msg;
[cell configMsg:textMsg.sendId ? textMsg.sendId : [[ILiveLoginManager getInstance] getLoginId] msg:textMsg.text];
}
if ([msg isKindOfClass:[ILVLiveCustomMessage class]])
{
ILVLiveCustomMessage *customMsg = (ILVLiveCustomMessage *)msg;
[cell configTips:customMsg.sendId];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
this is the ConfigWith function
CGFloat selfW = [UIScreen mainScreen].bounds.size.width ;
CGFloat selfH = 30;
UIFont *msgFont = [UIFont fontWithName:#"Superclarendon" size:12];//Helvetica-Bold
_nickname = profile.nickname;
NSString *showInfo = [NSString stringWithFormat:#"%#: %#",profile.nickname, text];
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:showInfo];
[attrStr addAttribute:NSForegroundColorAttributeName value:kColorGreen range:NSMakeRange(0, profile.nickname.length+1)];//+1是因为有个冒号
[attrStr addAttribute:NSForegroundColorAttributeName value:kColorWhite range:NSMakeRange(profile.nickname.length+1, text.length+1)];//+1是因为有个空格
[attrStr addAttribute:NSFontAttributeName value:msgFont range:NSMakeRange(0, showInfo.length)];//加粗
_msgLabel.attributedText = attrStr;
CGSize labelsize = [self textHeightSize:showInfo maxSize:CGSizeMake(selfW - kDefaultMargin*2, selfH * 3) textFont:msgFont];
[_msgLabel setFrame:CGRectMake(_msgLabel.frame.origin.x, _msgLabel.frame.origin.y, labelsize.width + kDefaultMargin, labelsize.height)];
[self setFrame:CGRectMake(0, 0, selfW, labelsize.height)];
_height = labelsize.height;
_msgLabel.hidden = NO;
_tipsLabel.hidden = YES;

As per my understanding when a new message notification has come, you are not maintaining the height of the cells according to the data. Hence they seem to be overlapped.
Now you have to maintain the height of the new notification, And the data is obtained should be added to your main array(data source). And hence can be easily coordinated.and cells are not get overlapped.
For maintaining the height of the cells, use "heightForRowAtIndexPath "delegate functions of the table view and Maintain the height of a particular cell accordingly.
And one more thing, please be sure that single message will be in the single cell. This will manage accordingly.

Please make sure that a single message was loaded by a single cell,and the height of cell is correct. It looks like you created lots of UILabels in the same cell.

Try using visual constraints instead of setFrame may help!

I found the solution.
i create a nib file as an extension to tableview cell and i register as nib
but im accepting #mayanksengar answer for giving me good insight
I just created a xib file and .h and .m
register xib to table view
[_msgTableView registerNib:[UINib nibWithNibName:#"customCell2" bundle:nil] forCellReuseIdentifier:#"customCell2"];
finally used it
NSString *cellIdentifier = #"customCell2";
customCell2 *cell= [_msgTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){
[_msgTableView registerNib:[UINib nibWithNibName:#"customCell2" bundle:nil] forCellReuseIdentifier:#"customCell2"];
}

Related

UISegment Control in UITableView Prototype cell, when value is changed in Segment control the scroll is moved to top

I have a screen, where we are displaying questions with YES or NO. For Yes Or No we have used UISegment Control.
When a value is changes in the UISegment Control the scroll is moved to Top of the screen, when we have more questions and when we select last or but last as shown in the image.
Below is the code used to render the controls.
Link to the videos how the output looks https://imgur.com/nvn1Exw .
Please help me how can i remove the scroll movement on selection of new value in segment control.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return timeOutQuestions.count;
}
- (UITableViewCell* )tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
static NSString* questionTableIdentifier=#"SegmentCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier: questionTableIdentifier];
if(cell == nil){
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:questionTableIdentifier];
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.numberOfLines = 0;
}
cell.separatorInset = UIEdgeInsetsMake(0.0 , cell.bounds.size.width , 0.0, -cell.bounds.size.width);
Question* currentQuestion=[[shared getQuestions:questionSet] objectAtIndex:indexPath.row];
#try{
UISegmentedControl *segment = [[cell.contentView subviews] objectAtIndex:0];
segment.selectedSegmentIndex = [[questionSegmentControl objectAtIndex:indexPath.row] integerValue];
[segment addTarget:self action:#selector(segmentSwitch:) forControlEvents:UIControlEventValueChanged];
UILabel *label = [[cell.contentView subviews] objectAtIndex:1];
label.text = currentQuestion.questionText;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}#catch(NSException* ex){
NSLog(#"%#",ex.reason);
}
if(changeOffSet && indexChangedValue.row > 2){
[self.questionTableView setContentOffset:tableContentOffSet animated:NO];
[UIView setAnimationsEnabled:true];
changeOffSet = false;
}
return cell;
}
- (IBAction)segmentSwitch:(UISegmentedControl *)sender {
NSInteger selectedSegment = sender.selectedSegmentIndex;
CGPoint senderOriginInTableView = [questionTableView convertPoint:CGPointZero fromView:sender];
NSIndexPath *indexPath = [questionTableView indexPathForRowAtPoint:senderOriginInTableView];
indexChangedValue = indexPath;
tableContentOffSet = self.questionTableView.contentOffset;
[UIView setAnimationsEnabled:false];
changeOffSet = true;
}
https://imgur.com/nvn1Exw
I think you are doing the scrolling programatically with this
[self.questionTableView setContentOffset:tableContentOffSet animated:NO];
I think you need to rework it a bit. Stop changing the content offset and see how it goes. Also, maybe you need to get rid of this line
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
which I think also interferes with the scrolling.

tableview update with new row keeping previous rows at first

After searching a lot did not found a proper solution to update a tableview
i want to update my tableview like a new coming record should place just below the previously updated records.
this is my code
if (sqlite3_open(myDatabase, &myConnection) == SQLITE_OK)
{
sqliteQuery = [NSString stringWithFormat: #"SELECT Description, SalePrice FROM ProductDetails WHERE Barcode = \'%#\'", barcode];
if (sqlite3_prepare_v2(myConnection, [sqliteQuery UTF8String], -1, &sQLStatement, NULL) == SQLITE_OK)
{
if(sqlite3_step(sQLStatement) == SQLITE_ROW)
{
temp = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(sQLStatement, 0)];
}
temp1 = [NSString stringWithFormat:#"%d", value];
if ([temp1 isEqualToString:#"0"])
{temp1 = #"1";}
temp2 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(sQLStatement, 1)] }
}
[description addObject: temp];
[qty addObject: temp1];
[price addObject:temp2];
}
sqlite3_finalize(sQLStatement);
}
sqlite3_close(myConnection);
}
myTable.hidden = NO;
myTable.delegate = self;
myTable.dataSource = self;
[myTable reloadData];
[self.view endEditing:YES];
and the tableview data source delegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [description count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
// Configure the cell in each row
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [self getCellContentView:CellIdentifier];
UILabel *lbl11 = (UILabel *)[cell viewWithTag:1];
[lbl11 setText:#"Label1"];
UILabel *lbl21 = (UILabel *)[cell viewWithTag:2];
[lbl21 setText:#"Label2"];
UILabel *lbl31 = (UILabel *)[cell viewWithTag:3];
[lbl31 setText:#"Label3"];
lbl11.text = [description objectAtIndex:indexPath.row];
lbl21.text = [qty objectAtIndex:indexPath.row];
lbl31.text = [price objectAtIndex:indexPath.row];
return cell;
}
- (UITableViewCell *)getCellContentView:(NSString *)cellIdentifier
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
cell.backgroundColor=[UIColor clearColor];
CGRect lbl11Rect = CGRectMake(20, 5, 450, 30);
CGRect lbl21Rect = CGRectMake(545, 5, 150, 30);
CGRect lbl31Rect = CGRectMake(795, 5, 150, 30);
UILabel *lbl11 = [[UILabel alloc] initWithFrame:lbl11Rect];
lbl11.tag=1;
lbl11.font=[UIFont fontWithName:#"Superclarendon" size:15];
lbl11.backgroundColor=[UIColor clearColor];
//lbl11.layer.borderWidth = 1.0f;
[cell.contentView addSubview:lbl11];
UILabel *lbl21 = [[UILabel alloc] initWithFrame:lbl21Rect];
lbl21.tag=2;
lbl21.font=[UIFont fontWithName:#"Superclarendon" size:15];
lbl21.backgroundColor=[UIColor clearColor];
//lbl21.layer.borderWidth = 1.0f;
[cell.contentView addSubview:lbl21];
UILabel *lbl31 = [[UILabel alloc] initWithFrame:lbl31Rect];
lbl31.tag=3;
lbl31.font=[UIFont fontWithName:#"Superclarendon" size:15];
lbl31.backgroundColor=[UIColor clearColor];
//lbl31.layer.borderWidth = 1.0f;
[cell.contentView addSubview:lbl31];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
return cell;
}
for first value search it showed the data in tableview…. how can i update tableview properly
i have found that for update
[myTable beginUpdate]
function will be used… and there is also
insertRowsAtIndexPaths: withRowAnimation
but unfortunately didn't find any good help that how to use this.
any help will be appreciated ….
First update your data source so numberOfRowsInSection and cellForRowAtIndexPath will return the correct values for your post-insert data. You must do this before you insert or delete rows.
Then insert your row:
// First figure out how many sections there are
NSInteger lastSectionIndex = [tableView numberOfSections] - 1;
// Then grab the number of rows in the last section
NSInteger lastRowIndex = [tableView numberOfRowsInSection:lastSectionIndex];
// Now just construct the index path
NSIndexPath *pathToLastRow = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];
//Adding new data row to last index position:
[myTable beginUpdates];
[myTable insertRowsAtIndexPaths:[NSArray arrayWithObject: pathToLastRow] withRowAnimation:UITableViewRowAnimationNone];
[myTable endUpdates];
There are different variants for animation:
UITableViewRowAnimationBottom
UITableViewRowAnimationFade
UITableViewRowAnimationMiddle
UITableViewRowAnimationNone
UITableViewRowAnimationRight
UITableViewRowAnimationTop
From iOs Developer Library:
beginUpdates
Begin a series of method calls that insert, delete, or select rows and sections of the receiver.
Discussion
Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously. This group of methods must conclude with an invocation of endUpdates. These method pairs can be nested. If you do not make the insertion, deletion, and selection calls inside this block, table attributes such as row count might become invalid. You should not call reloadData within the group; if you call this method within the group, you will need to perform any animations yourself.
The example of using this method you can find in Related Sample Code: iPhoneCoreDataRecipes

UITextView in UITablecell fill TextView text on custom cell

I am working with Custom UITableCell and dynamic UITextView in my application.
I have one issue regarding ios7 which i explain as follows:
i have created one view on UITable Cell Custom Button click like as follows. this view contains UITextView to input the text and fell it on cell later as on comment table.
// For iOS7
UITableView *table = nil;
if([CommonFunction isiOS7]){
table = (UITableView*)[[[[[sender superview] superview] superview] superview] superview];
indexPath=[[NSIndexPath alloc] init];//
indexPath = [table indexPathForCell:self];
}
else {
indexPath=[[NSIndexPath alloc] init];//
indexPath = [(UITableView *)self.superview indexPathForCell: self];
}
NSLog(#"indexPath:%#",indexPath);
if (appDelegate.dictLogedInUserData) {
//[(UITableView*)self.superview scrollToRowAtIndexPath:[(UITableView *)self.superview indexPathForCell:self] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[table scrollToRowAtIndexPath:[table indexPathForCell:self] atScrollPosition:UITableViewScrollPositionTop animated:YES];
TextInputView *txtInput = [[TextInputView alloc] init];
txtInput.delegate=self;
if ([btnAddComment.titleLabel.text length]>0) {
if (![btnAddComment.titleLabel.text isEqualToString:#"Add Comment"]) {
txtInput.txtComments.text = btnAddComment.titleLabel.text;
}
}
txtInput.backgroundColor = [UIColor clearColor];
//[(UITableView*)[self superview] setScrollEnabled:NO];
[table setScrollEnabled:NO];
[self addSubview:txtInput];
[self bringSubviewToFront:txtInput];
}
When use enter some text i need to fill this UITextView text value to my UITableCell CustomView which code is as follows,This is delegate method:
//InputText Delegates
- (void)didFinishInput:(NSString *)inputedText {
btnAddComment.titleLabel.text = inputedText;
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:indexPath, #"indexPath",
[NSString stringWithFormat:#"%#",inputedText],#"commentText",nil];
NSLog(#"dict:%#",dict);
topic *t = [appDelegate.arrayTopicsData objectAtIndex:indexPath.row];
t.user_comment = inputedText;
[appDelegate.arrayTopicsData replaceObjectAtIndex:indexPath.row withObject:t];
[self LoadDataForIndex:indexPath];
[delegate didAddComment:dict];
[(UITableView*)[self superview] setScrollEnabled:YES];
if ([inputedText length]<=0) {
btnAddComment.titleLabel.text = #"Add Comment";
}
}
In the above code it always crash when i enter text on UITextView and press Done button of key board. it gives EXE-BAD-Access on indexPath in iOS7.
Please help me how to get Indexpath on UITextView delegate method when i am passing NSString to the Method.
Please help me.

Table View troubles with dequeue cell

So I am having trouble showing my data in a UITableView. I do believe it has something to do with reusing the cells. I have checked online and here at SO but have not found a solution that works for me. Any help would be appreciated.
I have an Array that is populated by text and pictures. I am then showing the information in a tableView. If I were to use static sized cells everything works out fine, but the amount of text changes, so I have also implemented the heightForRowAtIndexPath method. This works as well, until I scroll all the way down to the bottom.
After that, when I scroll back up, all the cell heights change and the display gets all jumbled. Some text gets cut off, pictures get chopped and some of the cells only have the last portion of text. I really think it has something to do with reusing the cells, but I don’t know how to attack this problem. Below is my code for cellForRowAtIndexPath and heightForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSString *label = [_theBigArray objectAtIndex:indexPath.row];
CGSize stringSize = [label sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
UITextView *textV = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height +50)];
textV.font = [UIFont systemFontOfSize:15];
textV.text = [_theBigArray objectAtIndex:indexPath.row];
textV.textColor = [UIColor blackColor];
textV.editable = NO;
[cell.contentView addSubview:textV];
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 290, 100)];
imageV.contentMode = UIViewContentModeScaleAspectFit;
imageV.image = [_theBigArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageV];
}
return cell;
[tableView reloadData];
}
For heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
int rowHeight = 0.0f;
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
NSString *temp = [_theBigArray objectAtIndex:indexPath.row];
CGSize size = [temp sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
rowHeight = size.height+50;
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
rowHeight = 115.0f;
}
//NSLog(#"rowHeight is %i", rowHeight);
return rowHeight;
[tableView reloadData];
}
I even tried to make two different cells and call them separately, but the same thing happens. I did still use the same heightForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *newCell = [[UITableViewCell alloc] init];
if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[NSString class]])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
NSString *label = [_theBigArray objectAtIndex:indexPath.row];
CGSize stringSize = [label sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:NSLineBreakByWordWrapping];
UITextView *textV = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height +50)];
textV.font = [UIFont systemFontOfSize:15];
textV.text = [_theBigArray objectAtIndex:indexPath.row];
textV.textColor = [UIColor blackColor];
textV.editable = NO;
[cell.contentView addSubview:textV];
newCell = cell;
}
else if ([[_theBigArray objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]])
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PictureCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"PictureCell"];
}
UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 290, 100)];
imageV.contentMode = UIViewContentModeScaleAspectFit;
imageV.image = [_theBigArray objectAtIndex:indexPath.row];
[cell.contentView addSubview:imageV];
newCell = cell;
}
return newCell;
[tableView reloadData];
}
Any ideas?
The main problem is that you're adding subviews to cells every time they scroll in, but when a cell is reused, it will already have those subviews added. (That is, when a cell is reused, it will already have a UITextView or UIImageView depending on the reuse identifier.)
You need to check if these subviews exist first; this is commonly done by using the -[UIView viewWithTag] method, or by subclassing UITableViewCell and assigning each view as a property.
(You can take a look at the SO question How to get other control value from UITableViewCell? to see how to use viewWithTag. I would avoid subclassing UITableViewCell until you're more comfortable with the out-of-the-box implementation.)
Also, this line of code:
UITableViewCell *newCell = [[UITableViewCell alloc] init];
is a terrible idea, because you are creating a new UITableViewCell without checking to see if you can reuse one first. This defeats the entire purpose of reusing cells, which is fast scrolling performance. Instead, just declare it without initializing it:
UITableViewCell *newCell;
Also, in heightForRowAtIndexPath, you are
declaring rowHeight as an int (it should be a CGFloat)
trying to call reloadData after the method returns (which will never happen, but you should never try to call reloadData from this method)

Uiswitch in uitableviewcell reset when scroll up or down?

I have a problem with my UISwitch inside a UITableViewCell. When I change the value of one switch then scroll up or down all switches are messed up. I use an array to store state for each switch due to reusability they are still messed up every time.
Here is cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
CGRect switchFrame = switchController.frame;
[switchController setOn:YES animated:NO];
//set its x and y value, this you will have to determine how to space it on the left side
switchFrame.origin.x = 50.0f;
switchFrame.origin.y = 10.0f;
switchController.frame = switchFrame;
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:switchController ];
UILabel *label ;
label=(UILabel *)[cell viewWithTag:1];
NSString *value = [[mainArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
label.text = value;
label.textAlignment = NSTextAlignmentRight;
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
//This for persist switch state when scroll up or down
if ([[[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row ]isEqualToString:#"ON"])
{
switchController.on=YES;
}
else
{
switchController.on=NO;
}
return cell;
}
Here is SwitchChanged event :
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *index=[mainTableView indexPathForCell:cell];
if (sender.on)
{
[[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:#"ON"];
NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];
}
else
{
//call the first array by section
[[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:#"OFF"];
NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];
}
[padFactoids setObject:[NSKeyedArchiver archivedDataWithRootObject:SwitchArray] forKey:#"savedArray"];
[padFactoids synchronize];
}
I will appreciate your help so much.
In your header file declare an NSMutableArray, let's name it switchStates.
In your viewDidLoad, allocate memory and add object with the string "OFF" according to number of switches:
switchStates = [[NSMutableArray alloc] init];
for (int i; i <= switchesArray.count; i++) {
[switchStates addObject:#"OFF"];
}
In your method which runs when the switch is triggered:
NSString *theSwitchPosition = [NSString stringWithFormat:#"%#", switchControl.on ? #"ON" : #"OFF"];
[switchStates replaceObjectAtIndex:aPath.row withObject:theSwitchPosition];
After that, in the method where you create your switches:
if ([[switchStates objectAtIndex:indexPath.row] isEqualToString:#"ON"]) {
mySwitch.on = YES;
} else {
mySwitch.on = NO;
}
This worked for me, good luck..
I am not sure whether this causes your problem, but it will certainly cause other related problems.
Each time when a cell was moved off screen and a next one appears, the one that just moved off screen will be reused.
But you add a new switch object every time to the cell. You are far better off creating those only within the cell==nil block. Give it a tag and use the tag to fetch the object upon reusage as you do with the lable object.
You're creating a new switch every time the tableView is asking for a cell. You only want to create the switch once for each cell:
UISwitch *switchController;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
CGRect switchFrame = switchController.frame;
[switchController setOn:YES animated:NO];
//set its x and y value, this you will have to determine how to space it on the left side
switchFrame.origin.x = 50.0f;
switchFrame.origin.y = 10.0f;
switchController.frame = switchFrame;
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:switchController ];
switchController.tag = 123; //Arbitrary number...can be anything
}
else {
switchController = (UISwitch *)[cell.contentView viewWithTag:123];
}
//Now set the switch state according to your data model array
It's also generally a better practice to add subviews to the cell's contentView rather than the cell itself.

Resources