I want to save the switch state. I created custom cell class witch print one Switch on label but there is problem that if i search some text then Table View reload and my selected switch State is going to change, Is it possible to Maintain that state ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
....
selectionStyle = UITableViewCellSelectionStyleNone;
CfResultFatch *temp = [result objectAtIndex:indexPath.row];
NSLog(#"%#",temp.complanName);
//[cell.switchOnOff setOn:NO];
[cell.switchOnOff setTag:indexPath.row];
[cell.switchOnOff addTarget:self action:#selector(selectUser:)forControlEvents:UIControlEventValueChanged];
[cell.switchOnOff setTag:indexPath.row];
cell.lblUserName.text = temp.complanName;
cell.textFld.text = temp.cipd;
return cell;
}
//selectUser which is call when switch state change
-(IBAction)selectUser:(UISwitch*)sender{
if(sender.on)
{
[selectedpet addObject:[result objectAtIndex:sender.tag]];
}else{
NSLog(#"%#",sender);
for(int j=0;j<[selectedpet count]; j++)
{
CfResultFatch *temp = [result objectAtIndex:sender.tag];
CfResultFatch *temp1= [selectedpet objectAtIndex:j];
if([(temp.complanName)isEqualToString:(temp1.complanName)]) {
[selectedpet removeObjectAtIndex:j];
}
}
}
}
//and Search in searchBar this methode is call when search some text and the data is change from data base problem is here is i select 0 and 1 index switch on and then search some text, the new data in table view come with 0 and 1 index ON,how to maintain it and how to get my previous state of Switch
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
NSString *weburl = [NSString stringWithFormat:#"%#%#", #"http://192.168.1.196/ravi/searchUser.php?mname=",searchText];
NSURL *url = [NSURL URLWithString:weburl];
NSData *data =[NSData dataWithContentsOfURL:url];
[self getData:data];
[temptab reloadData];
}
And ya. sorry for my poor english
You should store the state of the UISwitch when it is changed. It might not be the best way to do this, but you could store the states in a dictionary like this:
NSMutableDictionary *states = [NSMutableDictionary alloc] init];
[states setObject:[NSNumber numberWithBool:sender.on] forKey:[NSNumber numberWithInt:sender.tag]]
Then, when showing the UITableViewCell:
if ([states objectForKey:[NSNumber numberWithInt:indexPath.row]] != nil)
cell.switchOnOff.on = [[states objectForKey:[NSNumber numberWithInt:indexPath.row]] boolValue]
else
cell.switchOnOff.on = NO;
Related
I have a UITableView with a UISwitch as the accessoryView. My problem is that if I toggle one of the switches then scroll so the switch it out of view it returns to its previous state.
Please see video.
Does anyone know why this might be and how to solve it?
Here is the code that adds the switch view and deals with its action.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"POICell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier ];
//set the cell text to the
cell.textLabel.text = [self.catNames objectAtIndex:[indexPath row]];
NSString *toggle = [self.toggleArray objectAtIndex:[indexPath row]];
//add switch
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//create an instance of the database oject
DataBase * dataBase = [[DataBase alloc] init];
//open the database connection
[dataBase openDB];
NSString *imageName = [dataBase getPinImageNameFromCatID:[self.catIDs objectAtIndex:[indexPath row]]];
//get the root file path for the images
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/pinImages/%#",documentsDirectory, imageName];
//add image
NSURL *imageURL = [NSURL fileURLWithPath:filePath];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
cell.imageView.image = image;
NSLog(#"%#",[self.catIDs objectAtIndex:[indexPath row]]);
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
[switchView addTarget:self action:#selector(switchChanged: ) forControlEvents:UIControlEventValueChanged];
if ([toggle isEqualToString: #"OFF"]) {
[switchView setOn:NO animated:NO];
}else{
[switchView setOn:YES animated:NO];
}
return cell;
}
- (void) switchChanged:(id)sender {
//get the switch that it was sent from
UISwitch *switchInCell = (UISwitch *)sender;
//get the cell it was sent from
UITableViewCell * cell = (UITableViewCell *) switchInCell.superview;
//get the row it was sent from
NSIndexPath * indexpath = [self.inputTableView indexPathForCell:cell];
//cast the indexpath to int
NSInteger variable = indexpath.row;
//set the filter as off in the user defualts.
[self.filterDic setValue:switchInCell.on ? #"ON" : #"OFF" forKey:[self.catIDs objectAtIndex:variable]];
//store the newdic in the user defualts
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
//save the dic to user defaults
[prefs setObject:self.filterDic forKey:#"pinFilters"];
}
Thanks for any help.
There are two issues with your code (at least :)
Let me start with the one that is confusing you.
You set the status of each witch based on toggle. And the value of toggle is tanken from an array self.toggleArray.
Fine so far.
But when a value changes and the action switchChanged is called then you update self.filterDic but you do not update self.toggleView.
And this causes the problem:
Next time when a cell becomes visible cellForRowAtIndexPath is called again and will set the value based on toggle wich is based on self.toggleArray. And that still has the old values in it ... you see?
You are making this mistake probably because you have not yet fully understood the cell recycle mechanism. And that is probably what causes the second issue that I identified. Let me try to explain.
iOS or cocoa respectively tries to allocate as view cell objects as nessessary. That means that a cell wich scrolls off the creen is added to a pool from which it can be re-used the next time when a (similar) sell is required. So each time when there is a need for a new cell (one that becomes visible) cellForRowAtIndexPath is called. Wihin that you fetch a cell using dequeueReusableCellWithIdentifier. If there is a cell in that pool that was initialized with the same re-use identfier then that one (or one of those) is returned to the caller.
In recent iOS (respectively SDK versions) versions a new cell will be allocated and returned if none of these cells exists. (And that is why Murali's suggestion would not work perfectly either)
In older versions you had to check cell for nil and alloc/init a new on in those cases.
After that you freely allocate new subview objects regardless whether the cell was re-cycled and already has those subviews or not. Then you add and add and add the same subviews again and again.
How can you solve this? There are, as usual, several ways of dealing with that:
First - Check whether the cell was re-used or not. Just check if the Switch is already there or not. For doing that you could tag it with some value different from 0 and fetch the subview with this tag. If you dont't get it then the cell is new and you have to create all the additional subvies.
Second - You could always erase all subviews from the cell right after fetching the cell with dequeueReusableCellWithIdentifier. That is the easiest solultion because you do not have to change mutch to your existing code. It is not the most performant solution though.
Third - The most elegant solution is probably to subclass UITableViewCell every time when you want to add custom elements to a cell. In that case its init method would be called only once upon creation (and not upon re-usage) and there you can programmatically add all the custom subviews. You can, of course, design the cell and add all subviews in IB as you can with every UIView object. Witin cellForRowAtIndexPath you would only have to care for setting the appropriate values.
Perhaps your cells are being recycled.
Have a look at the accepted answer here:
iphone : uitableview : contents of a cell change on scrolling
Please use this method..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"POICell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UISwitch *switchView;
if (cell == nil)
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier ];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
switchView = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];//Change the frame
cell.accessoryView = switchView;
}
//set the cell text to the
cell.textLabel.text = [self.catNames objectAtIndex:[indexPath row]];
NSString *toggle = [self.toggleArray objectAtIndex:[indexPath row]];
//add switch
//create an instance of the database oject
DataBase * dataBase = [[DataBase alloc] init];
//open the database connection
[dataBase openDB];
NSString *imageName = [dataBase getPinImageNameFromCatID:[self.catIDs objectAtIndex:[indexPath row]]];
//get the root file path for the images
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/pinImages/%#",documentsDirectory, imageName];
//add image
NSURL *imageURL = [NSURL fileURLWithPath:filePath];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
cell.imageView.image = image;
NSLog(#"%#",[self.catIDs objectAtIndex:[indexPath row]]);
[switchView addTarget:self action:#selector(switchChanged: ) forControlEvents:UIControlEventValueChanged];
if ([toggle isEqualToString: #"OFF"]) {
[switchView setOn:NO animated:NO];
}else{
[switchView setOn:YES animated:NO];
}
return cell;
}
If this is a repost, I apologize, but I have been scouring the net and cant seem to find anything that works. I have a list of workouts that I display in a tableview that are gathered in plists in the bundle. There is a also a separate tab that I have that allows a user to build their own workouts and save them in the documents folder plist file. Once they are saved, they are added to the table view. In the simulator, everyuhting works fine. But on the actual device, it is not updated unless I close the program for an extended period of time, reload the program from xcode, or turn the phone off. I have tried adding [[self tableview] reload] to "viewDidLoad", "viewWillappear", and "viewDidAppear" and none of them work. Once again, the file is saved, the updating does work in the simulator, and it doesn't update in the phone right away. Any suggestions? Thanks.
Edit: i know it is a long piece of code, but should be straight forward (hopefully lol)
#import "BIDWODList.h"
#import "BIDWODDetails.h"
#define kFileName #"SavedDFWorkouts.plist"
#interface BIDWODList ()
#end
#implementation BIDWODList
#synthesize names;
#synthesize savedNames;
#synthesize keys;
#synthesize details;
#synthesize wodType;
#synthesize benchmarkGirls;
#synthesize theNewGirls;
#synthesize heroes;
#synthesize savedDFGWorkouts;
#synthesize chosenWOD;
#synthesize chosenDetails;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *buildBenchmarkGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildTheNewGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildHeroes = [[NSMutableArray alloc] init];
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
self.benchmarkGirls = [buildBenchmarkGirls sortedArrayUsingSelector:#selector(compare:)];
self.theNewGirls = [buildTheNewGirls sortedArrayUsingSelector:#selector(compare:)];
self.heroes = [buildHeroes sortedArrayUsingSelector:#selector(compare:)];
//[[self tableView] reloadData]; //reloads the data in case a DFG workout was saved
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.names = nil;
self.keys = nil;
self.benchmarkGirls = nil;
self.theNewGirls = nil;;
self.heroes = nil;
self.details = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSString *)dataFilePath {
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFileName];
}
-(void)viewDidAppear:(BOOL)animated{
[[self tableView] reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0) {
return [benchmarkGirls count];
}else if (section == 1){
return [theNewGirls count];
}else if (section == 2){
return [heroes count];
}else{
return [savedDFGWorkouts count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];
}
if (section == 0) {
cell.textLabel.text = [benchmarkGirls objectAtIndex:row];
}else if (section == 1) {
cell.textLabel.text = [theNewGirls objectAtIndex:row];
}else if (section == 2) {
cell.textLabel.text = [heroes objectAtIndex:row];
}else{
cell.textLabel.text = [savedDFGWorkouts objectAtIndex:row];
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #" The Benchmark Girls";
}else if (section == 1){
return #"The New Girls";
}else if (section ==2){
return #"The Heroes";
}else{
return #"Saved DFG Workouts";
}
}
#pragma mark - Table view delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BIDWODDetails *destination = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
if (section == 0) {
self.chosenWOD = [self.benchmarkGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section == 1) {
self.chosenWOD = [self.theNewGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section ==2) {
self.chosenWOD = [self.heroes objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else {
self.chosenWOD = [self.savedDFGWorkouts objectAtIndex:row];
self.chosenDetails = [savedNames objectForKey:chosenWOD];
}//end if
//self.chosenDetails = [names objectForKey:chosenWOD];
//[destination setValue:chosenWOD forKey:#"chosenWOD"];
//[destination setValue:chosenDetails forKey:#"chosenDetails"];
destination.chosenWOD = self.chosenWOD;
destination.chosenDetails = self.chosenDetails;
}
#end
Different behaviour between the simulator and the device is often related to incorrect case being used in filenames - the simulator isn't case sensitive, and the device is. Check that you have the correct case used everywhere you reference the plist file.
Alternatively, on the simulator you are able to write directly to the application bundle, but on the device this is not possible and you can only write to certain directories in your application's sandbox, typically the documents directory. You would normally copy a plist to the documents directory on first run, and use that file thereafter.
If I understand right your code you load plist file only in viewDidLoad, but most likely this function called only when you first time load your view. To make it work you should load plist
in viewDidAppear. Something like this:
- (void)viewDidAppear {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
[self.tableView reloadData];
}
If it works in the Simulator and does not on the phone, almost for sure the problem is a timing issue. Saving files on a real phone takes much longer than on the simulator.
You should do the following:
when you save a file, log it, and log the return code from the save. If the way you save does not provide a return code, use NSFileManager to verify the file is in fact where it should be and even the size of it. This takes time to do but you should do it.
when your table is asking for the number of this and that, log it, and lot what is returned. You may find that that this comes before the files are saved.
It takes time and effort, but if you start logging all relevant things, you can find it. I just spend 6 hours today tracking down a race condition I had thought could never happen, and it was only after looking at a huge trail of messages that I was able to see the problem.
Almost for sure you will see that either file is not saved, its not where you thought it was, or that the phone timing means some events happen later than they do in the Simulator.
In my app I am getting the data from the web-service and I have to display it in UITableView.
But the condition here is I have to display only 10 records initially,then once the user scroll down I have to load more records.I tried searching it but didn't get any useful answer.
I agree that I will use -
(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
to display the value,but how will I fetch only 10 records from the service and then other record based on scroll.
Please provide some pointers or sample code.
Thanks
In case if some one need it,i was able to solve my problem this way.
First thing is you need the server configuration in such a way so that it should return 10 data at a time based on the row which is visible in TableView.
This is the tableView delegate which get called and returns the visible cells in tableView
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
int lastRow=[nameArray count]-1;
if(([indexPath row] == lastRow)&&(lastRow<[categoryArray count]))
{
if(tableView==m_pDetailsTableView) {
savedScrollPosition=lastRow;
startCellValue=[NSString stringWithFormat:#"%d",0];
endCellValue=[NSString stringWithFormat:#"%d",[nameArray count]+10];
[self connectToServer]; //Method to request to server to get more data
}
}
}
savedscrollPosition variable stores the variable as a point where you want to scroll the table view after load of data.
You should read about lazy loading. The code is available at Apple's website. Download it here
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
check the code of
- (void)loadImagesForOnscreenRows
method.
It uses the same approach you need. It gets the current scroll position of the table view and on the basis of that, it will get the cells displayed on the screen and their indexPath. On the basis of that you will be able to show those cells which are shown in the screen.
For showing 10 rows, a simple calculation is required.
Just insert the new data into your datasource
see below
If you're using xml - check out XMLReader - turn XML into an NSDictionary
this sample code below uses AFNetworking (which is non blocking)
https://github.com/AFNetworking/AFNetworking/
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
[self fetchMoreData];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self fetchMoreData];
}
- (void)fetchMoreData
{
if ([resultArray count] > 0)
{
NSArray *visiblePaths = [myTableView indexPathsForVisibleRows];
NSIndexPath *lastRow = [visiblePaths lastObject];
// Check whether or not the very last row is visible.
NSInteger numberOfSections = [myTableView numberOfSections];
NSInteger lastRowSection = [lastRow section];
NSInteger lastRowRow = [lastRow row];
NSInteger numberOfRowsInSection = [myTableView numberOfRowsInSection:lastRowSection];
if (lastRowSection == numberOfSections - 1 &&
lastRowRow== numberOfRowsInSection - 1) {
DLog(#"it's the last row");
if ([resultArray count]%10 == 0) { // use a divider based on your pagination
[self fetchNextPage];
}
}
}
}
-(void)getFeeds{
ENTER_METHOD;
[resultArray removeAllObjects];
//reset this
NSString *url = [NSString stringWithFormat:#"/webserviceurl.xml?offset=0"];
[httpClient getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[self parseFeedsXMLString:operation.responseString];
// offset = offset + 10; // ONLY if there's results increment
} failure:^(AFHTTPRequestOperation *operation, id responseObject){
NSString *detailError=nil;
}];
}
-(void)fetchNextPage{
NSString *url = [NSString stringWithFormat:#"/webserviceurl.xml?offset=%d",offset];
[httpClient getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
DLog(#"operation.responseString:%#",operation.responseString);
[self parseNextFeedsXMLString:operation.responseString];
// offset = offset + 10; // ONLY increment if there's results
} failure:^(AFHTTPRequestOperation *operation, id responseObject){
}];
}
- (void)parseFeedsXMLString:(NSString *)xmlString
{
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:xmlString error:&parseError];
DLog(#"xmlDictionary:%#",xmlDictionary);
resultArray = [[NSMutableArray arrayWithArray:[[xmlDictionary objectForKey:#"feed"] objectForKey:#"entry"]]retain];
[myTableView reloadData];
}
-(void)parseNextFeedsXMLString:(NSString *)xmlString
{
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:xmlString error:&parseError];
DLog(#"xmlDictionary:%#",xmlDictionary);
//[resultArray insertObject:e atIndex:[resultArray count]];
NSMutableArray *results = [NSMutableArray arrayWithArray:[[xmlDictionary objectForKey:#"feed"] objectForKey:#"entry"]];
if ([results count]) {
page++;
for (NSDictionary *dict in results) {
[resultArray insertObject:dict atIndex:[results count]];
}
}
[myTableView reloadData];
}
If I correctly understand your question ,you can do the following.
1 ) implement scrollViewDidScroll
2 ) check for visible rows in that
3 ) if you found the last row just call the web service for loading
more data
4 ) on getting the data just reload the table
Try it .
You can adjust the return value of tableView:numberOfRowsInSection: method, every time you want to insert ten rows, you can plus 10 to the return value.
sorry for my poor english.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger lastSectionIndex = [tableView numberOfSections] - 1;
NSInteger lastRowIndex = [tableView numberOfRowsInSection:lastSectionIndex] - 1;
if ((indexPath.section == lastSectionIndex) && (indexPath.row == lastRowIndex)) {
i = i +10;
NSString *unescaped = mySearchBar.text;
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
[PServiceAPI searchKeyWord:escapedString withOffSet:i Handler:^(NSArray *results, NSError *error) {
if (error == nil) {
[arBase addObjectsFromArray:results];
[myTableView2 reloadData];
}
}];
}
}
I have a tableview that contains cell images and names as text. At the top i have added a searchbar. And when I search i am able to do the search for names, but the images are still the same. How can change the images also, as per the changes in names when search?
this code in the tableview delegate, and i'm using some search delegate methods also. I haven't done anything to arrange the images with respect to the names. I need help to implement that.
if(searching)
cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
else {
[cell.imageView setImageWithURL:[NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:#"defaultPerson.png"]];
cell.textLabel.text = [friendsList objectAtIndex:indexPath.row];
}
Here is few more code:
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSString *sTemp in friendsList)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
Thanks.
It seems to me that you are not updating your cells correctly.
A simple [myTableView reloadData]; might help, but you might also want to consider looking into the way you are adding the imageViews to you cells. You might not have removed(/released/nilled) the imageViews you place on top of your cells correctly. You have to do this everytime you update your cells as well since the imageViews won't do this themselves unless you specifically told them so.
When you updated your question with some helpful code I can be more specific about this concerning your problem.
Now that you did edit your post with some (although very little amount of) code I can see from this snippet that you are not updating your cell.imageViews to the new list of objects.
You updated your uitableview with the new "copyListOfItems" but you didn't do that same thing for your images resulting in the display of the old content which are the images from "imageArray"
You need to make a similar array for your images as you did with the text.
if(searching)
{
cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
[cell.imageView setImageWithURL:[NSURL URLWithString:[searchedArrayOfImages objectAtIndex:indexPath.row]];
}
else {
[cell.imageView setImageWithURL:[NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:#"defaultPerson.png"]];
cell.textLabel.text = [friendsList objectAtIndex:indexPath.row];
}
A better way (i.m.o.) to save images to names is making a NSDictionary for them so when you pick a record your name always fits your image.
In regards of the comments below:
At the moment you search, mostlikely in the textDidChange delegate method, you mostlikely pick the indexrows of all your search matches. At the moment you pick the index of a hit from "friendlist" and put it into "copyListOfItems" you also need to use the very same index and take the image from "imageArray" and put them into "searchedArrayOfImages". This way you build both your text- and image array the same way. Then when you reload your tableview you can take the same index from "copyListOfItems" and from "searchedArrayOfImages" and populate your cell properly.
It would look something like this:
- (void) searchTableView
{
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
int indexCount = 0; //keeps track of which index you are at.
for (NSString *sTemp in friendsList)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
[copyListOfItems addObject:sTemp]; //this is your name result
[searchedArrayOfImages addObject:[imageArray objectAtIndex:indexCount]]; //adds image that fits with the nameresult to array of searched images
}
indexCount++;
}
[searchArray release];
searchArray = nil;
}
When you are done searching the cells will be updated like this (according to your snippet)
if(searching)
{
cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
[cell.imageView setImageWithURL:[NSURL URLWithString:[searchedArrayOfImages objectAtIndex:indexPath.row]];
}
else
{
[cell.imageView setImageWithURL:[NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:#"defaultPerson.png"]];
cell.textLabel.text = [friendsList objectAtIndex:indexPath.row];
}
This should suffice^^ good luck.
I have a UITable with a datasource that is set to a 'copy' of the original data. I use this copy to displayed filtered results (either 'All' or only those that are 'checked' with a UISwitch in each row). My logic for doing the filtering is here:
-(void)filterItems {
[tableData removeAllObjects];
if (checkedOrNotSwitch.selectedSegmentIndex == 0) {
[tableData addObjectsFromArray:self.defaultChecklistItemsArray];
} else {
for (NSMutableDictionary *sectionDict in self.defaultChecklistItemsArray) {
NSMutableArray *newItemsArray = [[NSMutableArray alloc] init];
[newItemsArray removeAllObjects];
for (NSMutableDictionary *itemDict in [sectionDict objectForKey:#"categoryItems"]) {
if ([[itemDict objectForKey:#"isComplete"] boolValue]) {
[newItemsArray addObject:itemDict];
}
}
if ([newItemsArray count] > 0) {
NSMutableDictionary *newSectionDict = [[NSMutableDictionary alloc] initWithDictionary:sectionDict];
[newSectionDict setObject:newItemsArray forKey:#"categoryItems"];
[tableData addObject:newSectionDict];
[newSectionDict release];
}
}
}
[checklistTable reloadData];
}
The filtering itself now works correctly. In my custom cell, each row has a UISwitch. The switch runs this function when its changed:
-(IBAction) switchValueChanged{
NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell: self];
[self.parentController updateCompletedStatusAtIndexPath:indexPath toStatus:isCompleted.on];
}
The function above is in the class for the tableviewcell itself. The function I call in the superview is this:
-(void)updateCompletedStatusAtIndexPath:(NSIndexPath *)indexPath toStatus:(BOOL)status{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSMutableDictionary *currentsection = [[NSMutableDictionary alloc] initWithDictionary:[tableData objectAtIndex:section]];
NSMutableArray *itemsArray = [[NSMutableArray alloc] initWithArray:[currentsection objectForKey:#"categoryItems"] copyItems:YES];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithDictionary:[itemsArray objectAtIndex:row]];
NSLog(#"BOOL = %#\n", (status ? #"YES" : #"NO"));
[tempDict setValue:[NSNumber numberWithBool:status] forKey:#"isComplete"];
[itemsArray replaceObjectAtIndex:row withObject:tempDict];
[currentsection setValue:itemsArray forKey:#"categoryItems"];
[tableData replaceObjectAtIndex:section withObject:currentsection];
[tempDict release];
[itemsArray release];
[currentsection release];
[checklistTable reloadData];
}
Before I implemented the filtering and used the logic above on self.defaultChecklistItemsArray directly, it worked and saved the data when the switch was flipped.
Now when I first enter the app, it loads the array of data from nsuserdefaults. I navigate to the view with the table and it displays the data correctly there with the UISwitches all in the correct position given the data (some on, some off). When I tap one of the switches, then click the segmentedcontrol that does the filtering, the data reverts back to the state it was loaded in, implying that the flipping of the switch did not actually effect the data at all (even though I don't think I did a deep copy anywhere here so I figured it should be doing the right thing). Any suggestions?