HMAccessoryDelegates not calling on Button action - ios

I am working on Homekit iOS app. I have a question that I have an accessory and When I change its power characteristic value using the HomeKit Simulator the delegates of HMAccessory are caliing but in case If I change the powr characteristic value programmatically (Using the writevalue ) the delegate methods are not being called. Please let me know any ideas of suggestions.
Code
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
selectedDevice.delegate = self;
}
HMAccessoryDelegate
- (void)accessory:(HMAccessory *)accessory service:(HMService *)service didUpdateValueForCharacteristic:(HMCharacteristic *)characteristic;
{
NSLog(#"changed");
}
Write Function
UISwitch *sw = [[UISwitch alloc] initWithFrame:CGRectMake(230, 5, 51, 31)];
[cell addSubview:sw];
sw.on = YES;
[sw addTarget:self action:#selector(updateState:) forControlEvents:UIControlEventValueChanged];
-(void)updateState:(UISwitch*)sender
{
HMCharacteristic *characteristic = self.selectedService.characteristics[tag];
[characteristic enableNotification:YES completionHandler:^(NSError *error)
{
if(!error)
{
}
}];
if([characteristic.characteristicType isEqualToString:HMCharacteristicTypePowerState])
{
id val = characteristic.value;
NSString *str = [NSString stringWithFormat:#"%#",val];
if([str isEqualToString:#"0"])
{
id a = characteristic.value;
BOOL b = [a boolValue];
NSNumber *c = [NSNumber numberWithBool:!b];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[characteristic writeValue:c completionHandler:^(NSError *error) {
if (error) {
UIAlertView *alertController = [[UIAlertView alloc] initWithTitle:#"Error" message:[appDel handleErrorCodes:error.code] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertController show];
return;
}
else
{
[serviceCharacteristicsTableView reloadData];
}
}];
}
}
Please let me know if I am not clear

The documentation says that the delegate method is not called when you set the value programatically:
This method is called as a result of a change in value initiated by
the accessory. Programmatic changes initiated by the app do not result
in this method being called.
If you want to do something after writing the characteristic's value succeeded (or failed), you can do it in the completionHandler: block of writeValue:completionHandler: method.

Related

iOS - NSURLSession not working the second time

I have a UIView that contains a progress bar. What I want to do is simple, I have a button, user clicks that button, app downloads file and show progress in progress bar. I am able to do this when the user clicks the download button the first time. But when the user clicks the second time to download again, NSURLSession delegates are not called.
My UIView .m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self configure];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self configure];
}
return self;
}
-(void)configure
{
[self createSpinner];
[self createProgressBar];
NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
self.docDirectoryURL = [URLs objectAtIndex:0];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:#"com.tinkytickles"];
sessionConfiguration.HTTPMaximumConnectionsPerHost = 1;
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
}
-(void)createSpinner
{
[self setBackgroundColor:[UIColor colorWithWhite:1.0f alpha:0.5f]];
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self addSubview:spinner];
[spinner setColor:original_new_dark_grey];
[spinner setUserInteractionEnabled:NO];
[spinner setCenter:CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2)];
[spinner setFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[spinner startAnimating];
}
-(void)createProgressBar
{
self.progressBar = [[TYMProgressBarView alloc] initWithFrame:CGRectMake(0, 0, 280, 15)];
[self.progressBar setBarBackgroundColor:[UIColor whiteColor]];
[self.progressBar setBarBorderColor:original_new_dark_grey];
[self.progressBar setBarFillColor:original_new_dark_grey];
[self.progressBar setBarBorderWidth:1.0f];
[self addSubview:self.progressBar];
[self.progressBar setCenter:CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2)];
[self.progressBar setHidden:YES];
self.label = [[UILabel alloc] initWithFrame:CGRectMake(self.progressBar.frame.origin.x, self.progressBar.frame.origin.y - 30, self.progressBar.frame.size.width, 25)];
[self.label setText:NSLocalizedString(locDownloading, nil)];
[self.label setTextAlignment:NSTextAlignmentCenter];
[self.label setTextColor:original_new_dark_grey];
[self.label setFont:quicksand_14];
[self addSubview:self.label];
[self.label setHidden:YES];
}
-(void)showProgressBarWithProgress:(CGFloat)progress withText:(NSString *)text
{
[spinner setHidden:YES];
[self.label setText:[NSString stringWithFormat:NSLocalizedString(locDownloadingAt, nil), text]];
[self.label setHidden:NO];
[self.progressBar setHidden:NO];
[self.progressBar setProgress:progress];
}
-(void)stopAnimating
{
[spinner stopAnimating];
}
-(void)startDownloadingURL:(PromoterDownloadInfo *)downloadInfo
{
info = downloadInfo;
if (!info.isDownloading)
{
if (info.taskIdentifier == -1)
{
info.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:info.downloadSource]];
info.taskIdentifier = info.downloadTask.taskIdentifier;
[info.downloadTask resume];
}
else
{
info.downloadTask = [self.session downloadTaskWithResumeData:info.taskResumeData];
[info.downloadTask resume];
info.taskIdentifier = info.downloadTask.taskIdentifier;
}
}
else
{
[info.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
if (resumeData != nil) {
info.taskResumeData = [[NSData alloc] initWithData:resumeData];
}
}];
}
info.isDownloading = !info.isDownloading;
}
-(void)stopDownload:(PromoterDownloadInfo *)downloadInfo
{
if (!info.isDownloading)
{
if (info.taskIdentifier == -1)
{
info.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:info.downloadSource]];
}
else
{
info.downloadTask = [self.session downloadTaskWithResumeData:info.taskResumeData];
}
info.taskIdentifier = info.downloadTask.taskIdentifier;
[info.downloadTask resume];
info.isDownloading = YES;
}
[self stopAnimating];
[self removeFromSuperview];
}
#pragma mark - NSURLSession Delegate method implementation
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent;
NSURL *destinationURL = [self.docDirectoryURL URLByAppendingPathComponent:destinationFilename];
if ([fileManager fileExistsAtPath:[destinationURL path]]) {
[fileManager removeItemAtURL:destinationURL error:nil];
}
BOOL success = [fileManager copyItemAtURL:location
toURL:destinationURL
error:&error];
if (success) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self stopAnimating];
[self removeFromSuperview];
}];
}
else
{
NSLog(#"Unable to copy temp file. Error: %#", [error localizedDescription]);
}
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (error != nil) {
NSLog(#"Download completed with error: %#", [error localizedDescription]);
}
else{
NSLog(#"Download finished successfully.");
}
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) {
NSLog(#"Unknown transfer size");
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
info.downloadProgress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
[self showProgressBarWithProgress:info.downloadProgress withText:info.fileTitle];
});
}
}
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
// Check if all download tasks have been finished.
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([downloadTasks count] == 0) {
if (appDelegate.backgroundTransferCompletionHandler != nil) {
// Copy locally the completion handler.
void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
// Make nil the backgroundTransferCompletionHandler.
appDelegate.backgroundTransferCompletionHandler = nil;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Call the completion handler to tell the system that there are no other background transfers.
completionHandler();
// Show a local notification when all downloads are over.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = NSLocalizedString(locDownloadComplete, nil);
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}];
}
}
}];
}
I use this UIView like this:
PromoterDownloadInfo *info = [[PromoterDownloadInfo alloc] initWithFileTitle:self.title andDownloadSource:#"https://www.mywebsite.com/file.zip"];
PromotersDownloadView *downloadView = [[PromotersDownloadView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.navigationController.view addSubview:downloadView];
[downloadView startDownloadingURL:info];
The first time I clicked the download button it works great. The second time NSURLSession only didCompleteWithError method gets called. Here is what I get from log the second time:
2016-05-12 00:50:47.440 APP[32990:1230071] A background URLSession with identifier com.app already exists!
2016-05-12 00:50:50.614 APP[32990:1230386] Download finished successfully.
What am I doing wrong? I tried to create NSURLSessionConfiguration only once but this way no delegate method gets called. What should I do?
You said:
The first time I clicked the download button it works great. ... Here is what I get from log the second time:
2016-05-12 00:50:47.440 APP[32990:1230071] A background URLSession with identifier com.app already exists!<br />
That error is pointing out that you want to instantiate only one background NSURLSession for a given identifier (and you generally only need/want a single background session). If you were going to instantiate multiple ones, you'd give them unique identifiers, but handling background sessions is complicated enough without unnecessarily having multiple sessions. I'd suggest that you only want a single background session.
You said:
I tried to create NSURLSessionConfiguration only once but this way no delegate method gets called.
Yes, you should have one session configuration. And, just as importantly, only one background session object.
I suspect that there's an issue with your delegate object not being able to keep track of which view it should be updating. Or perhaps you lost reference to your session object and your reference was nil. It could be a couple of different things, and it's hard to know without seeing how you did this.
I'd suggest moving this session configuration code out of the view, and have some shared instance that you can reference anywhere (e.g. a singleton works well, so you can instantiate it from wherever it's first needed, whether from a view or from the app delegate's handleEventsForBackgroundURLSession method).
The only challenge then is how to keep track of which views are keeping track of which network requests. Do you want to have a single view that will keep track of all incomplete requests, regardless of when this view is instantiated? If so, you can use NSNotificationCenter notifications (that way, any view that wants to be notified of progress updates can just observe your custom notification). Or does a given view only care about requests that you initiated from that view?In that case, you might maintain dictionary that maps taskIdentifier values to which view or object needs to know about the status updates (what way you can have your session object keep track of which views care about which tasks). It just depends upon your app's requirements.

Paytm sdk ios integration to open Paytm payment form?

Integrated Paytm sdk 2.1 in iOS (Xcode 7) and configured to make payment .
I have a form in which amount and other fields need to filled then there is a button for Payment .
Here is code which i am using :
//Step 1: Create a default merchant config object
PGMerchantConfiguration *mc = [PGMerchantConfiguration defaultConfiguration];
//Step 2: If you have your own checksum generation and validation url set this here. Otherwise use the default Paytm urls
mc.checksumGenerationURL = #"generate checksum url";
mc.checksumValidationURL = #"checksum validation url";
//Step 3: Create the order with whatever params you want to add. But make sure that you include the merchant mandatory params
NSMutableDictionary *orderDict = [NSMutableDictionary new];
//Merchant configuration in the order object
orderDict[#"MID"] = #"abc1111";
orderDict[#"CHANNEL_ID"] = #"WAP";
orderDict[#"INDUSTRY_TYPE_ID"] = #"Education";
orderDict[#"WEBSITE"] = #"companyname";
//Order configuration in the order object
orderDict[#"TXN_AMOUNT"] = #"100";
orderDict[#"ORDER_ID"] = [Feepayment generateOrderIDWithPrefix:#"111"];
orderDict[#"REQUEST_TYPE"] = #"DEFAULT";
orderDict[#"CUST_ID"] = #"abc7777";
PGOrder *order = [PGOrder orderWithParams:orderDict];
//Step 4: Choose the PG server. In your production build dont call selectServerDialog. Just create a instance of the
//PGTransactionViewController and set the serverType to eServerTypeProduction
[PGServerEnvironment selectServerDialog:self.view completionHandler:^(ServerType type)
{
PGTransactionViewController *txnController = [[PGTransactionViewController alloc] initTransactionForOrder:order];
//show title var
UIView *mNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,44)];
mNavBar.backgroundColor = [UIColor grayColor];
txnController.topBar = mNavBar;
//Cancel button
UIButton *mCancelButton = [[UIButton alloc] initWithFrame:CGRectMake(5, 2, 70, 40)];
[mCancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
mCancelButton.titleLabel.textColor = PURPLE_COLOR;
[mCancelButton setFont:[UIFont fontWithName:#"Helvetica-Bold" size:15.0]];
txnController.cancelButton = mCancelButton;
//add title
UILabel *mTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 - 10, 1, 100, 50)];
[mTitleLabel setText:#"Payment"];
[mTitleLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:15.0]];
mTitleLabel.textColor = [UIColor whiteColor];
[mNavBar addSubview:mTitleLabel];
if (type!=eServerTypeNone) {
txnController.serverType = type;
txnController.merchant = mc;
txnController.loggingEnabled = YES;
txnController.sendAllChecksumResponseParamsToPG = YES;
txnController.delegate = self;
[self showController:txnController];
}
}];
//show controller method
-(void)showController:(PGTransactionViewController *)controller {
if (self.navigationController != nil)
[self.navigationController pushViewController:controller animated:YES];
else
[self presentViewController:controller animated:YES
completion:^{
}];
}
//remove controller
-(void)removeController:(PGTransactionViewController *)controller {
if (self.navigationController != nil)
[self.navigationController popViewControllerAnimated:YES];
else
[controller dismissViewControllerAnimated:YES
completion:^{
}];
}
#pragma mark PGTransactionViewController delegate
- (void)didSucceedTransaction:(PGTransactionViewController *)controller
response:(NSDictionary *)response {
DEBUGLOG(#"ViewController::didSucceedTransactionresponse= %#", response);
NSString *title = [NSString stringWithFormat:#"Your order was completed successfully. \n %#", response[#"ORDERID"]];
[[[UIAlertView alloc] initWithTitle:title message:[response description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
[self removeController:controller];
}
- (void)didFailTransaction:(PGTransactionViewController *)controller error:(NSError *)error response:(NSDictionary *)response {
DEBUGLOG(#"ViewController::didFailTransaction error = %# response= %#", error, response);
if (response)
{
[[[UIAlertView alloc] initWithTitle:error.localizedDescription message:[response description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
else if (error)
{
[[[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
[self removeController:controller];
}
- (void)didCancelTransaction:(PGTransactionViewController *)controller error:(NSError*)error response:(NSDictionary *)response {
DEBUGLOG(#"ViewController::didCancelTransaction error = %# response= %#", error, response);
NSString *msg = nil;
if (!error) msg = [NSString stringWithFormat:#"Successful"];
else msg = [NSString stringWithFormat:#"UnSuccessful"];
[[[UIAlertView alloc] initWithTitle:#"Transaction Cancel" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
[self removeController:controller];
}
- (void)didFinishCASTransaction:(PGTransactionViewController *)controller response:(NSDictionary *)response {
DEBUGLOG(#"ViewController::didFinishCASTransaction:response = %#", response);
}
Here is screenshot while using staging directly showing this page :
*Note - Actually i am trying for staging not for production .
When i execute then it doesnt showing Paytm feepayment form instead it showing orderid and amount with transaction id dirctly .
How to open Paytm payment form when user enter fee amount in the form then it should calcualte the amount with extraa tax and then clicking on Fee payment button it should open PAYTM PAYMENT FORM.
PLEASE HELP ME TO SOLVE THIS PROBLEM ( I HAVE GO THROUGH THE PAYTM SDK DOC STEP BY STEP BUT DINT ABLE TO FIND IT ).
THANKS.
Important : **As far as checksumGenerationURL and checksumValidationURL is concerned , we need to create it . Initially i tried to use from Paytm but it dint work so finally our server team did it , this is most important point for Integrating Paytm
Finally , Solved by testing it on the Production and its working fine . As far as Staging server is concerned i guess there is hard coded information is in the sdk so hope in the next version of PGSDK we could test it on Staging too.
Thanks .
#Pradeep k ... thank you very much for all your valuable support .
Have you populated the mc.checksumGenerationURL and mc.checksumValidationURL properly? Also there is a 2.7 version of the SDK that you should be using. Ask your Paytm contact point for the latest iOS SDK.
Now about the amount, Paytm does not calculate the tax. You have to add it to the amount that you are sending to Paytm.

Navigation in iOS using Objective-C

i have an ios app which uses a login page and after authenticating it enters into the inbox page.But after entering the inbox page it comes back automatically to the login page
Login.m
{
if ([username length] == 0 || [password length] == 0)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"Make sure you enter a username and password!"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else
{
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Login_Info WHERE username='%#'",username]; // Execute the query.
NSLog(#" query = %#", query );
// Get the results.
if (self.arrLogin_Info != nil) {
self.arrLogin_Info = nil;
}
self.arrLogin_Info = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
[def setObject:[self.arrLogin_Info objectAtIndex:0] forKey:#"idKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:1] forKey:#"usernameKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:2] forKey:#"passwordKey"];
[def setObject:[self.arrLogin_Info objectAtIndex:3] forKey:#"emailKey"];
NSLog(#" query output = %#", self.arrLogin_Info);
NSString *val = [self.arrLogin_Info objectAtIndex:2];
// NSLog(#" val = %#",val);
if ([val isEqualToString:password] )
{
// NSLog(#" Inside if before entering app");
[self.navigationController popToRootViewControllerAnimated:YES];
}
else
{
//NSLog(#" Inside else before entering app");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sorry!"
message:#"Please ensure you have entered the correct password!"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
}
#end
Inbox.m
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
id u = [def objectForKey:#"idkey"];
if(u)
{
NSString *query = [NSString stringWithFormat:#"Select *from Messages where recipient_ID=%#",u];
self.msg = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
// [self.tableView reloadData];
}
else
{
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
// [self.tableView reloadData];
}
- (IBAction)logout:(id)sender {
//[PFUser logOut];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"showLogin" ])
{
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
}
Your Inbox view controller uses the presence of an object for the key 'idkey' in NSUserDefaults to determine whether the user is already logged in, or whether to show the login screen.
I presume that this line in login.m
[def setObject:[self.arrLogin_Info objectAtIndex:0] forKey:#"idKey"];
is supposed to be setting that key, but you don't show where you initialise def - so my guess is that this is nil and you aren't saving the data in NSUserDefaults.
Also, all of this -
if (self.arrLogin_Info != nil) {
self.arrLogin_Info = nil;
}
self.arrLogin_Info = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
can be simplified to this
self.arrLogin_Info = [self.dbManager loadDataFromDB:query];

Update ProgressView after the view controller has been changed

I currently have a progress view which shows the current amount of how much of a file has been downloaded so far. When the user clicks the download button the progress succesfully updates and when they leave the view controller and return to it while it is still downloading the progress still updates successfuly. However my problem is when the download finishes and the user has left and returned to the view the progress view no longer responds to any updates. I have did some research into multi-threading and seen that many people suggest to do any UI updates in the main thread like so:
[self performSelectorOnMainThread:#selector(progressUpdate) withObject:nil waitUntilDone:NO];
So I tried it in my code and the still got the same results (once the user leaves and returns to the view controller after the download has finished the progress view does not respond to any updates). I then added a NSLog to see if the method was being called and the debugger outputted the NSLog. So what is going on? Here is the code for the view controller:
VideoTest.m
#import "VideoTest.h"
#import "AppDelegate.h"
#import "FileDownloadInfo.h"
#interface VideoTest ()
#property (nonatomic, strong) NSURLSession *session;
#property (nonatomic, strong) NSMutableArray *arrFileDownloadData;
#property (nonatomic, strong) NSURL *docDirectoryURL;
-(void)initializeFileDownloadDataArray;
-(int)getFileDownloadInfoIndexWithTaskIdentifier:(unsigned long)taskIdentifier;
#end
#implementation VideoTest{
NSString *url;
}
#synthesize moviePlayer;
#synthesize download;
#synthesize videoAlreadyPlaying, progressView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Setting video URl
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
url = #"http://therosary.info/AppVideos/TheChaplet/Information%20on%20Divine%20Mercy.mp4";
//selectors set
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(enteredFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(exitedFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playbackFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
//Play the movie
videoAlreadyPlaying=#"TRUE";
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
[self.view addSubview:moviePlayer.view];
self.moviePlayer.view.frame = CGRectMake(0,64,320,220);
[moviePlayer play];
[self initializeFileDownloadDataArray];
NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
self.docDirectoryURL = [URLs objectAtIndex:0];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:#"com.jjdoherty98.Marion_s_Net"];
sessionConfiguration.HTTPMaximumConnectionsPerHost = 5;
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
if([appDelegate.isAlreadyDownloading isEqual:#"FALSE"] || appDelegate.isAlreadyDownloading==nil){
self.progressView.hidden = YES;
progressView.progress=0;
}
if([appDelegate.isAlreadyDownloading isEqual:#"TRUE"]){
[self performSelectorOnMainThread:#selector(progressUpdate) withObject:nil waitUntilDone:NO];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.isMovingFromParentViewController || self.isBeingDismissed) {
NSLog(#"Left View");
[moviePlayer stop];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown;
}
- (BOOL)shouldAutorotate{
AppDelegate *mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
mainDelegate.fullScreenVideoIsPlaying = #"TRUE";
return YES;
}
- (void)MPMoviePlayerPlaybackStateDidChange:(NSNotification *)notification
{
if (moviePlayer.playbackState == MPMoviePlaybackStatePlaying)
{ //playing
videoAlreadyPlaying = #"TRUE";
}
if (moviePlayer.playbackState == MPMoviePlaybackStateStopped)
{ //stopped
}if (moviePlayer.playbackState == MPMoviePlaybackStatePaused)
{ //paused
}if (moviePlayer.playbackState == MPMoviePlaybackStateInterrupted)
{ //interrupted
}if (moviePlayer.playbackState == MPMoviePlaybackStateSeekingForward)
{ //seeking forward
}if (moviePlayer.playbackState == MPMoviePlaybackStateSeekingBackward)
{ //seeking backward
}
}
- (void)willEnterFullscreen:(NSNotification*)notification {
NSLog(#"willEnterFullscreen");
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = #"TRUE";
}
- (void)enteredFullscreen:(NSNotification*)notification {
NSLog(#"enteredFullscreen");
}
- (void)willExitFullscreen:(NSNotification*)notification {
NSLog(#"willExitFullscreen");
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = #"FALSE";
}
- (void)exitedFullscreen:(NSNotification*)notification {
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSLog(#"exitedFullscreen");
if(appDelegate.CurrentProgress==0){
progressView.hidden=TRUE;
}else{
[self performSelectorOnMainThread:#selector(progressUpdate) withObject:nil waitUntilDone:NO];
}
}
- (void)playbackFinished:(NSNotification*)notification {
NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
switch ([reason intValue]) {
case MPMovieFinishReasonPlaybackEnded:
NSLog(#"playbackFinished. Reason: Playback Ended");
videoAlreadyPlaying=#"FALSE";
[moviePlayer stop];
[moviePlayer play];
break;
case MPMovieFinishReasonPlaybackError:
NSLog(#"playbackFinished. Reason: Playback Error");
videoAlreadyPlaying=#"FALSE";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Video Failed To Load!"
message:#"Unable to connect to server, please try again later!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
break;
case MPMovieFinishReasonUserExited:
NSLog(#"playbackFinished. Reason: User Exited");
videoAlreadyPlaying=#"FALSE";
break;
default:
break;
}
[self.moviePlayer setFullscreen:NO animated:YES];
}
-(IBAction)buttonPressed:(id)sender{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if([appDelegate.isThereInternet isEqual:#"TRUE"]){
if([appDelegate.isAlreadyDownloading isEqual: #"FALSE"]){
//If there is internet and not already downloading
progressView.hidden=FALSE;
progressView.progress=0;
FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:0];
fdi.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:fdi.downloadSource]];
fdi.taskIdentifier = fdi.downloadTask.taskIdentifier;
// Start the task.
[fdi.downloadTask resume];
}}
if ([appDelegate.isThereInternet isEqual:#"FALSE"]) {
//No internet available
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Unable to connect to server"
message:#"Internet connection appears to be offline, please try again later!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
if([appDelegate.isAlreadyDownloading isEqual:#"TRUE"]){
//Is already downloaing
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"File Already Downloading"
message:#"Multiple files can not be downloaded at the same time!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
-(void)initializeFileDownloadDataArray{
self.arrFileDownloadData = [[NSMutableArray alloc] init];
[self.arrFileDownloadData addObject:[[FileDownloadInfo alloc] initWithFileTitle:nil andDownloadSource:url]];
}
-(int)getFileDownloadInfoIndexWithTaskIdentifier:(unsigned long)taskIdentifier{
int index = 0;
for (int i=0; i<[self.arrFileDownloadData count]; i++) {
FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:i];
if (fdi.taskIdentifier == taskIdentifier) {
index = i;
break;
}
}
return index;
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent;
NSURL *destinationURL = [self.docDirectoryURL URLByAppendingPathComponent:destinationFilename];
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if ([fileManager fileExistsAtPath:[destinationURL path]]) {
[fileManager removeItemAtURL:destinationURL error:nil];
}
BOOL success = [fileManager copyItemAtURL:location
toURL:destinationURL
error:&error];
if (success) {
int index = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:index];
fdi.isDownloading = NO;
fdi.downloadComplete = YES;
// Set the initial value to the taskIdentifier property of the fdi object,
// so when the start button gets tapped again to start over the file download.
fdi.taskIdentifier = -1;
// In case there is any resume data stored in the fdi object, just make it nil.
fdi.taskResumeData = nil;
}
else{
NSLog(#"Unable to copy temp file. Error: %#", [error localizedDescription]);
}
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if (error != nil) {
NSLog(#"Download completed with error: %#", [error localizedDescription]);
appDelegate.isAlreadyDownloading=#"FALSE";
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Failed to download!"
message:#"Unable to connect to the server!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
});
}
else{
appDelegate.isAlreadyDownloading=#"FALSE";
NSLog(#"Download finished successfully.");
dispatch_async(dispatch_get_main_queue(), ^{
FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:0];
fdi.isDownloading = NO;
fdi.downloadComplete = YES;
fdi.taskIdentifier = -1;
fdi.taskResumeData = nil;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Download Complete!"
message:#"Go to downloads section to view the file now!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
});
}
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) {
NSLog(#"Unknown transfer size");
}
else{
int index = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:index];
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.isAlreadyDownloading=#"TRUE";
fdi.downloadProgress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
appDelegate.CurrentProgress = fdi.downloadProgress;
[self performSelectorOnMainThread:#selector(progressUpdate) withObject:nil waitUntilDone:NO];
}
}
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([downloadTasks count] == 0) {
if (appDelegate.backgroundTransferCompletionHandler != nil) {
// Make nil the backgroundTransferCompletionHandler.
appDelegate.backgroundTransferCompletionHandler = nil;
progressView.hidden=TRUE;
// Show a local notification when all downloads are over.
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"All files have been downloaded!";
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
}
}];
}
-(void)progressUpdate{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if ([appDelegate.isAlreadyDownloading isEqual:#"TRUE"]) {
progressView.progress = appDelegate.CurrentProgress;
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:#selector(progressUpdate) userInfo:nil repeats:NO];
NSLog(#"Is this method being called");
if (appDelegate.CurrentProgress==1) {
progressView.hidden=TRUE;
}
}
}
#end
Any help would be appreciated!

UITABLEView duplicate rows issue

I cannot resolve this issue and I have no idea why my UITableView duplicates rows whenever I click on the segment control. I want to refresh the table view with new data when segment control changes. I have tried many things and googled it but could not find any solution. I would appreciated if someone can help me please. I am still learning xcode and a lot to learn. here is my code -
#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
Try removing all previous object from the self.earthquakeList before adding new 1. use [self.earthquakeList removeAllObjects]
Remove this Line,
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
And uncomment,
[self.tableView reloadData];
You are Already updating the data set, So you just need to reload the tableView instead of explicitly insert row.

Resources