Ios UITABLEView重复行问题
我无法解决此问题,也不知道为什么每次单击segment控件时,UITableView都会复制行。当段控件更改时,我想用新数据刷新表视图。我尝试了很多东西,在谷歌上搜索了一下,但找不到任何解决办法。如果有人能帮助我,我将不胜感激。我还在学习xcode,还有很多东西要学。这是我的密码-Ios UITABLEView重复行问题,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我无法解决此问题,也不知道为什么每次单击segment控件时,UITableView都会复制行。当段控件更改时,我想用新数据刷新表视图。我尝试了很多东西,在谷歌上搜索了一下,但找不到任何解决办法。如果有人能帮助我,我将不胜感激。我还在学习xcode,还有很多东西要学。这是我的密码- #import "citsViewController.h" #import "citsParseOperation.h" #import "citsFuelFinder.h" #import "citsTableV
#import "citsViewController.h"
#import "citsParseOperation.h"
#import "citsFuelFinder.h"
#import "citsTableViewCell.h"
#import "citsAboutViewController.h"
#import "MBProgressHUD.h"
#import <CoreLocation/CoreLocation.h>
// this framework is imported so we can use the kCFURLErrorNotConnectedToInternet error code
#import <CFNetwork/CFNetwork.h>
#import <MapKit/MapKit.h>
@interface citsViewController ()
{
CLLocationManager *locationManager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
NSString *currentLoc;
int productName;
}
@property (nonatomic) NSMutableArray *earthquakeList;
@property (nonatomic) citsFuelFinder *currentEarthquakeObject;
@property (nonatomic, weak) IBOutlet UILabel *locationLabel;
// queue that manages our NSOperation for parsing earthquake data
@property (nonatomic) NSOperationQueue *parseQueue;
@end
#pragma mark -
@implementation citsViewController
@synthesize nomatchesView;
@synthesize footerLabel;
@synthesize headerLabel;
@synthesize fuelType;
@synthesize bannerIsVisible;
- (void)viewDidLoad {
[super viewDidLoad];
//refresh the tableview
UIRefreshControl *refreshControl=[[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
self.refreshControl=refreshControl;
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:@selector(aboutUs:) forControlEvents:UIControlEventTouchUpInside];
//add info button in the navigation controller
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton] ;
//initialize location manager
locationManager=[[CLLocationManager alloc] init];
//to get location
geocoder=[[CLGeocoder alloc] init];
//show network activity
[UIApplication sharedApplication].networkActivityIndicatorVisible = TRUE;
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
//call the location manager update function
[locationManager startUpdatingLocation];
}
-(void)refresh:(id)sender {
//update table data
[locationManager startUpdatingLocation];
[self.refreshControl endRefreshing];
[self.tableView reloadData];
}
- (void)dealloc {
// we are no longer interested in these notifications:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kAddEarthquakesNotificationName
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kEarthquakesErrorNotificationName
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSCurrentLocaleDidChangeNotification
object:nil];
}
/**
Handle errors in the download by showing an alert to the user. This is a very simple way of handling the error, partly because this application does not have any offline functionality for the user. Most real applications should handle the error in a less obtrusive way and provide offline functionality to the user.
*/
- (void)handleError:(NSError *)error {
NSString *errorMessage = [error localizedDescription];
NSString *alertTitle = NSLocalizedString(@"Error", @"Title for alert displayed when download or parse error occurs.");
NSString *okTitle = NSLocalizedString(@"OK ", @"OK Title for alert displayed when download or parse error occurs.");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle message:errorMessage delegate:nil cancelButtonTitle:okTitle otherButtonTitles:nil];
[alertView show];
}
/**
Our NSNotification callback from the running NSOperation to add the earthquakes
*/
- (void)addEarthquakes:(NSNotification *)notif {
assert([NSThread isMainThread]);
[self addEarthquakesToList:[[notif userInfo] valueForKey:kEarthquakeResultsKey]];
}
/**
Our NSNotification callback from the running NSOperation when a parsing error has occurred
*/
- (void)earthquakesError:(NSNotification *)notif {
assert([NSThread isMainThread]);
[self handleError:[[notif userInfo] valueForKey:kEarthquakesMessageErrorKey]];
}
/**
The NSOperation "ParseOperation" calls addEarthquakes: via NSNotification, on the main thread which in turn calls this method, with batches of parsed objects. The batch size is set via the kSizeOfFuelPumpBatch constant.
*/
- (void)addEarthquakesToList:(NSArray *)earthquakes {
NSInteger startingRow = [self.earthquakeList count];
NSInteger earthquakeCount = [earthquakes count];
NSMutableArray *indexPaths = [[NSMutableArray alloc] initWithCapacity:earthquakeCount];
for (NSInteger row = startingRow; row < (startingRow+earthquakeCount); row++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
[indexPaths addObject:indexPath];
}
NSLog(@"record count %d",earthquakeCount);
[self.earthquakeList addObjectsFromArray:earthquakes];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
//[self.tableView reloadData];
}
#pragma mark - UITableViewDelegate
// The number of rows is equal to the number of earthquakes in the array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.earthquakeList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kEarthquakeCellID = @"EarthquakeCellID";
citsTableViewCell *cell = (citsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:kEarthquakeCellID];
if(cell==nil)
{
cell=[[citsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kEarthquakeCellID];
}
// Get the specific earthquake for this row.
citsFuelFinder *earthquake = (self.earthquakeList)[indexPath.row];
[cell configureWithEarthquake:earthquake];
return cell;
}
/**
* When the user taps a row in the table, display the USGS web page that displays details of the earthquake they selected.
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *buttonTitle = NSLocalizedString(@"Cancel", @"Cancel");
//NSString *buttonTitle1 = NSLocalizedString(@"Show USGS Site in Safari", @"Show USGS Site in Safari");
NSString *buttonTitle2 = NSLocalizedString(@"Show Location in Maps", @"Show Location in Maps");
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:buttonTitle destructiveButtonTitle:nil
otherButtonTitles: buttonTitle2, nil];
[sheet showInView:self.view];
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 500)];
headerLabel=[[UILabel alloc] initWithFrame:CGRectMake(10, 1.0, 300, 25)];
headerLabel.numberOfLines=0;
fuelType=[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"ULP", @"PULP",@"Diesel",@"LPG", nil]];
fuelType.frame = CGRectMake(10, 30, 300,25);
//set first segment selected
[fuelType setSelectedSegmentIndex:0];
[fuelType addTarget:self action:@selector(segmentedControlHasChangedValue) forControlEvents:UIControlEventValueChanged];
headerLabel.font=[UIFont systemFontOfSize:10.0];
[headerView insertSubview:fuelType aboveSubview:headerLabel];
[headerView addSubview:headerLabel];
[headerView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"footer.gif"]]];
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 60;
}
#pragma mark -
/**
* Called when the user selects an option in the sheet. The sheet will automatically be dismissed.
*/
- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex {
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
citsFuelFinder *earthquake = (citsFuelFinder *)(self.earthquakeList)[selectedIndexPath.row];
switch (buttonIndex) {
case 0: {
// open the earthquake info in Maps
// create a map region pointing to the earthquake location
CLLocationCoordinate2D location = (CLLocationCoordinate2D) { earthquake.latitude, earthquake.longitude };
NSValue *locationValue = [NSValue valueWithMKCoordinate:location];
MKCoordinateSpan span = (MKCoordinateSpan) { 2.0, 2.0 };
NSValue *spanValue = [NSValue valueWithMKCoordinateSpan:span];
NSDictionary *launchOptions = @{ MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
MKLaunchOptionsMapCenterKey : locationValue,
MKLaunchOptionsMapSpanKey : spanValue,
MKLaunchOptionsShowsTrafficKey : @(NO),
MKLaunchOptionsDirectionsModeDriving : @(NO) };
// make sure the map item has a pin placed on it with the title as the earthquake location
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:location addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:earthquake.location];
[mapItem openInMapsWithLaunchOptions:launchOptions];
break;
}
}
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
// Regiser for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
HUD.labelText = @"Loading";
HUD.detailsLabelText = @"updating data";
HUD.square = YES;
self.earthquakeList = [NSMutableArray array];
self.currentEarthquakeObject=nil;
if([self.earthquakeList count] >0)
{
[self.earthquakeList removeAllObjects];
[self.tableView reloadData];
}
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:@selector(addEarthquakesToList:) onTarget:self withObject:nil animated:YES];
NSLog(@"didUpdateToLocation: %@", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSString *latitude=[NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
NSString *longitude=[NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
citsTableViewCell *tcell = [[citsTableViewCell alloc] init];
//set the latitude and longitude
tcell.lon =[longitude doubleValue];
tcell.lat = [latitude doubleValue];
NSLog(@"Lat:%@, Lon:%@", latitude,latitude);
}
//stop updating location
[locationManager stopUpdatingLocation];
//reverse geocoding
NSLog(@"Resolving the address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
currentLoc=[NSString stringWithFormat:@"%@",placemark.locality];
if(currentLoc == NULL)
{
currentLoc=@"N/A";
}
NSLog(@"%@",currentLoc);
//add text to headertext
NSDate *currDate=[NSDate date];
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd/MM/yy HH:mm:ss"];
NSString *dateString=[dateFormatter stringFromDate:currDate];
NSString *loc=[NSString stringWithFormat:@"Your location: %@, Updated on: %@", currentLoc, dateString ];
[dateFormatter setDateFormat:@"EEEE, dd/MM/yyyy"];
NSString *headerDate=[dateFormatter stringFromDate:currDate];
headerLabel.text=[NSString stringWithFormat:@"Prices for: %@\n%@", headerDate,loc];
//currentLoc=[NSString stringWithFormat:@"%@", placemark.locality];
currentLoc=@"Mirrabooka";
if(productName==0)
{
productName=1;
}
NSString *prdStr=[[NSString alloc] initWithFormat:@"%d", productName];
NSString *str =[currentLoc stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
NSString *feedURLString =[[NSString alloc] initWithFormat: @"http://www.fuelwatch.wa.gov.au/fuelwatch/fuelWatchRSS?Product=%@&Suburb=%@", prdStr,str ];
NSURLRequest *earthquakeURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:feedURLString]];
NSLog(@"%@",feedURLString);
// send the async request (note that the completion block will be called on the main thread)
//
// note: using the block-based "sendAsynchronousRequest" is preferred, and useful for
// small data transfers that are likely to succeed. If you doing large data transfers,
// consider using the NSURLConnectionDelegate-based APIs.
//
[NSURLConnection sendAsynchronousRequest:earthquakeURLRequest queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// back on the main thread, check for errors, if no errors start the parsing
//
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// here we check for any returned NSError from the server, "and" we also check for any http response errors
if (error != nil) {
[self handleError:error];
}
else {
// check for any response errors
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if ((([httpResponse statusCode]/100) == 2) ) {
// Update the UI and start parsing the data,
// Spawn an NSOperation to parse the earthquake data so that the UI is not
// blocked while the application parses the XML data.
//
citsParseOperation *parseOperation = [[citsParseOperation alloc] initWithData:data];
[self.parseQueue addOperation:parseOperation];
}
else {
NSString *errorString =
NSLocalizedString(@"HTTP Error", @"Error message displayed when receving a connection error.");
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : errorString};
NSError *reportError = [NSError errorWithDomain:@"HTTP"
code:[httpResponse statusCode]
userInfo:userInfo];
[self handleError:reportError];
}
}
}];
// Start the status bar network activity indicator.
// We'll turn it off when the connection finishes or experiences an error.
//
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
self.parseQueue = [NSOperationQueue new];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(addEarthquakes:)
name:kAddEarthquakesNotificationName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(earthquakesError:)
name:kEarthquakesErrorNotificationName object:nil];
} else {
NSLog(@"%@", error.debugDescription);
}
} ];
NSLog(@"%d",[self.earthquakeList count]);
}
-(void)clearData{
[self.tableView beginUpdates];
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
for (int i = [self.tableView numberOfRowsInSection:0] - 1; i >= 0; i--)
{
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:0]];
NSLog(@"Deleted: %d",i);
}
[self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationFade];
[self.earthquakeList removeAllObjects];
[self.tableView endUpdates];
//[self.tableView reloadData] ;
}
-(void)segmentedControlHasChangedValue{
int product;
product=fuelType.selectedSegmentIndex;
switch (product) {
case 0:
productName=1;
[locationManager startUpdatingLocation];
[self clearData];
break;
case 1:
productName=2;
[self clearData];
[locationManager startUpdatingLocation];
break;
case 2:
productName=4;
[self clearData];
[locationManager startUpdatingLocation];
break;
case 3:
prod![enter image description here][1]uctName=5;
[self clearData];
[locationManager startUpdatingLocation];
break;
}
NSLog(@"%d",productName);
return;
}
@end
#导入“citsViewController.h”
#导入“citsParseOperation.h”
#导入“citsFuelFinder.h”
#导入“citsTableViewCell.h”
#导入“citsAboutViewController.h”
#导入“MBProgressHUD.h”
#进口
//此框架已导入,因此我们可以使用KCFurrerRorNotConnectedPointerNet错误代码
#进口
#进口
@接口citsViewController()
{
CLLocationManager*locationManager;
CLGeocoder*地理编码器;
CLPlacemark*placemark;
NSString*currentLoc;
int产品名称;
}
@属性(非原子)NSMutableArray*地震列表;
@属性(非原子)citsFuelFinder*CurrentEarth地震对象;
@属性(非原子,弱)IBUILabel*位置标签;
//用于管理解析地震数据的NSO操作的队列
@属性(非原子)NSOperationQueue*parseQueue;
@结束
#布拉格标记-
@citsViewController的实现
@综合nomatchesView;
@综合标签;
@合成头标;
@综合燃料类型;
@合成清晰可见;
-(无效)viewDidLoad{
[超级视图下载];
//刷新表格视图
UIRefreshControl*refreshControl=[[UIRefreshControl alloc]init];
[refreshControl添加目标:自我操作:@selector(refresh:)forControlEvents:UIControlEventValueChanged];
self.refreshControl=refreshControl;
UIButton*infoButton=[UIButton按钮类型:UIButtonTypeInfoLight];
[infoButton addTarget:self action:@selector(aboutUs:)for ControlEvents:UIControlEventTouchUpInside];
//在导航控制器中添加信息按钮
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]initWithCustomView:infoButton];
//初始化位置管理器
locationManager=[[CLLocationManager alloc]init];
//获取位置
地理编码器=[[CLGeocoder alloc]init];
//展示网络活动
[UIApplication sharedApplication].networkActivityIndicatorVisible=TRUE;
locationManager.delegate=self;
locationManager.desiredAccuracy=KCallocationAccuracyBest;
//调用位置管理器更新功能
[locationManager startUpdatingLocation];
}
-(无效)刷新:(id)发件人{
//更新表数据
[locationManager startUpdatingLocation];
[自我刷新控制结束刷新];
[self.tableView重载数据];
}
-(无效)解除锁定{
//我们不再对这些通知感兴趣:
[[NSNotificationCenter defaultCenter]移除观察者:self
名称:KadderthQuakeNotificationName
对象:无];
[[NSNotificationCenter defaultCenter]移除观察者:self
名称:KerthQuakeErrorNotificationName
对象:无];
[[NSNotificationCenter defaultCenter]移除观察者:self
名称:NSCurrentLocaleDidChangeNotification
对象:无];
}
/**
通过向用户显示警报来处理下载中的错误。这是处理错误的一种非常简单的方法,部分原因是该应用程序没有任何供用户使用的脱机功能。大多数真实的应用程序应该以一种不太显眼的方式处理错误,并向用户提供离线功能。
*/
-(无效)句柄错误:(n错误*)错误{
NSString*errorMessage=[error localizedDescription];
NSString*alertTitle=NSLocalizedString(@“错误”,“下载或分析错误时显示的警报标题”);
NSString*OKTTILE=NSLocalizedString(@“OK”,出现下载或分析错误时显示的警报的@“OK Title”);
UIAlertView*alertView=[[UIAlertView alloc]initWithTitle:alertTitle消息:errorMessage委托:nil CancelButtontTitle:okTitle其他ButtontTitles:nil];
[警报视图显示];
}
/**
我们的NSNotification回调来自正在运行的NSO操作,以添加地震
*/
-(无效)添加地震:(NSNotification*)notif{
断言([NSThread isMainThread]);
[自编的ArthQuakesToList:[[notif userInfo]valueForKey:kEarthquakeResultsKey];
}
/**
发生解析错误时,从正在运行的NSO操作发出的NSNotification回调
*/
-(无效)地震错误:(NSNotification*)notif{
断言([NSThread isMainThread]);
[self-handleError:[[notif userInfo]valueForKey:KerthQuakeMessageErrorKey]];
}
/**
NSOperation“ParseOperation”通过主线程上的NSNotification调用AddArthQuakes,而主线程反过来调用此方法,并批量解析对象。批大小通过kSizeOfFuelPumpBatch常量设置。
*/
-(空白)地震列表:(NSArray*)地震{
NSInteger startingRow=[self.earthquakeList count];
NSInteger地震计数=[地震计数];
NSMutableArray*indexPaths=[[NSMutableArray alloc]initWithCapacity:earthquakeCount];
对于(NSInteger row=起始行;row<(起始行+地震计数);row++){
NSIndexPath*indexPath=[NSIndexPath indexPathForRow:row分类:0];
[indexPaths addObject:indexPath];
}
NSLog(@“记录计数%d”,地震计数);
[self.earthquakeList addObjectsFromArray:地震];
[self.tableView insertRowsAtIndexPaths:indexPaths with rownanimation:uitableview rownanimationautomatic];
//[self.tableView重载数据];
}
#pragma标记-UITableViewDelegate
//行数等于数组中的地震数。
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节{
返回[自身地震师计数];
}
-(UITableView单元格*)表格视图:(UITableView*)表格视图
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadData];