NSURLConnection - Is it possible to wait/block on a request? - macos

I need to wait for a response from a SOAP webservice, I am calling via a NSURLConnection as I need to manipulate the data being returned and then return it from my class to the calling class..
Here is my code:
#import <Foundation/Foundation.h>
#interface UsersBLL : NSObject {
NSMutableData *webData;
NSMutableString *soapResults;
NSXMLParser *xmlParser;
BOOL *recordResults;
NSNumber *EmailCount;
}
#property(nonatomic, retain) NSMutableData *webData;
#property(nonatomic, retain) NSMutableString *soapResults;
#property(nonatomic, retain) NSXMLParser *xmlParser;
-(int)checkEmailAddress:(NSString*)emailAddress;
#end
#import "UsersBLL.h"
#implementation UsersBLL
#synthesize webData;
#synthesize soapResults;
#synthesize xmlParser;
-(id)init {
self = [super init];
return self;
}
-(int)checkEmailAddress:(NSString*)emailAddress {
// Build the SOAP envelope
NSString *soapMessage = [NSString stringWithFormat:
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
"<CheckEmailAddress xmlns=\"http://tempuri.org/\">\n"
"<EmailAddress>%#</EmailAddress>\n"
"</CheckEmailAddress>\n"
"</soap:Body>\n"
"</soap:Envelope>\n", emailAddress];
NSLog(soapMessage);
NSURL *url = [NSURL URLWithString:#"http://photoswapper.mick-walker.co.uk/UsersService.asmx?op=CheckEmailAddress"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
[theRequest addValue: #"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue: #"http://tempuri.org/CheckEmailAddress" forHTTPHeaderField:#"SOAPAction"];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
else
{
NSLog(#"theConnection is NULL");
}
NSLog(#"%#", EmailCount);
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
NSLog(theXML);
[theXML release];
if( xmlParser )
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
[connection release];
[webData release];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
if( [elementName isEqualToString:#"CheckEmailAddressResult"])
{
if(!soapResults)
{
soapResults = [[NSMutableString alloc] init];
}
recordResults = TRUE;
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if( recordResults )
{
[soapResults appendString: string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"CheckEmailAddressResult"])
{
recordResults = FALSE;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
EmailCount = [formatter numberFromString:soapResults];
[formatter release];
[soapResults release];
soapResults = nil;
}
}
#end
CheckEmailAddress is declared as returning an integer value (I know it returns nothing in the sample above).
What I ideally want, is through the CheckEmailAddress method, return the value retrieved from the web service. However as the call NSURLConnection does not wait until the request has completed, I cannot do it.
I would be grateful if anyone could give me any potential ideas for workarounds.

The simplest solution would be using [NSURLConnection sendSynchronousRequest:returningResponse:error:].
It does not allow as much control as the approach you've taken, but is usually enough for most applications.

I have just posted a solution which wraps an asynchronous NSURLConnection to be able to block the calling thread. In case you need more control than the standard [NSURLConnection sendSynchronousRequest:returningResponse:error:] you can check out this link on StackOverflow:
NSURLConnection blocking wrapper implemented with semaphores

You have two choices:
Use +[NSURLConnection sendSynchronousRequest:returningResponse:error:]
Schedule the connection in a custom runloop mode, and run the loop in that mode until the data arrives or you have need to cancel the connection

It all depends on the level of asynchronism you need:
If it's OK to stay blocked during the whole request you may want to use
+[NSURLConnection sendSynchronousRequest:returningResponse:error:]
But, as suggested by Wade, be careful to add a timeout to your NSURLRequest, otherwise the connection might blocks and your application will hang.
If not, you can simply use the NSNotificationCenter. But you must be careful with race conditions over your data, specially if you are handling multiple requests

Related

NSURLConnection response not complete

I am making call to a server requesting JSON data using NSURLConnection.
For some reason I get part of the response. If I hit the url through the browser the response its correct. The weird thing is that it happens only sometime. So I'm having a hard time debugging the issue.
Then when because the response is not complete I get the following error:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0xa4634a0 {NSDebugDescription=Invalid value around character 0.} {
NSDebugDescription = "Invalid value around character 0.";
}
I guess it could also be an issue with the server it self. Here's my code:
-(void) getShareHistory:(NSString *)range paging:(NSInteger *)page{
NSString *post = [NSString stringWithFormat:#"range=%#&paging=%#",
range,
[NSString stringWithFormat:#"%ld",(long)page]];
NSString *url = [NSString stringWithFormat:#"http://www/domai.com/handle_share_links.php?action=history"];
NSData *post_data = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [post_data length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:post_data];
self.shareHistoryConn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)response{
NSString *strData = [[NSString alloc]initWithData:response encoding:NSASCIIStringEncoding];
NSLog(#"response %#",strData);
NSError *jsonParsingError = nil;
if(connection == self.shareHistoryConn)
{
NSArray *data = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingAllowFragments error:&jsonParsingError];
if(!jsonParsingError)
{
[[self delegate] onGetShareHistorySuccess:data];
}else{
[[self delegate] onGetShareHistoryFailed:jsonParsingError];
}
}
Thanks in advance.
What you're seeing is normal behavior. didReceiveData can be called any number of times. It is up to you to keep accumulating the data until you get connectionDidFinishLoading.
The standard delegate structure is like this:
- (void) connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response {
// connection is starting, clear buffer
[self.receivedData setLength:0];
}
- (void) connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
// data is arriving, add it to the buffer
[self.receivedData appendData:data];
}
- (void)connection:(NSURLConnection*)connection
didFailWithError:(NSError *)error {
// something went wrong, clean up interface as needed
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// all done, we are ready to rock and roll
// do something with self.receivedData
}
Always implement all four delegate methods.

NSURLConnection with blocks

I'm using
[NSURLConnection connectionWithRequest:req delegate:self];
and then I use
-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
-(void)connectionDidFinishLoading:(NSURLConnection *)connection;
to handle data loading. Everything is ok and working fine but I don't like the beauty of this code )
I wish to use blocks, to make my code looks like this:
[myConnection sendData:data
successBlock:^(void){NSLog(#"success");}
errorBlock:^(NSError * error){NSLog(#"error.description: %#", error.description);}];
is it possible to use NSURLConnection with blocks?
I use this class:
The MyConnection.h
#import <Foundation/Foundation.h>
#interface MyConnection : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
NSURLConnection * internalConnection;
NSMutableData * container;
}
-(id)initWithRequest:(NSURLRequest *)req;
#property (nonatomic,copy)NSURLConnection * internalConnection;
#property (nonatomic,copy)NSURLRequest *request;
#property (nonatomic,copy)void (^completitionBlock) (id obj, NSError * err);
-(void)start;
#end
And the MyConnection.m
#import "MyConnection.h"
static NSMutableArray *sharedConnectionList = nil;
#implementation MyConnection
#synthesize request,completitionBlock,internalConnection;
-(id)initWithRequest:(NSURLRequest *)req {
self = [super init];
if (self) {
[self setRequest:req];
}
return self;
}
-(void)start {
container = [[NSMutableData alloc]init];
internalConnection = [[NSURLConnection alloc]initWithRequest:[self request] delegate:self startImmediately:YES];
if(!sharedConnectionList)
sharedConnectionList = [[NSMutableArray alloc] init];
[sharedConnectionList addObject:self];
}
#pragma mark NSURLConnectionDelegate methods
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[container appendData:data];
}
//If finish, return the data and the error nil
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([self completitionBlock])
[self completitionBlock](container,nil);
[sharedConnectionList removeObject:self];
}
//If fail, return nil and an error
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if([self completitionBlock])
[self completitionBlock](nil,error);
[sharedConnectionList removeObject:self];
}
#end
to use it:
MyConnection * connection = [[MyConnection alloc]initWithRequest:req];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
//It's ok, do domething with the response data (obj)
} else {
//There was an error
}
}];
[connection start];
It's based on the code, The Big Nerd Ranch uses on his book.
I hope it will be helpful.
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(#"%#", response);
NSLog(#"%#", data);
}];

cocos2d json parsing for iphone application

Is there any good tutorial/source code to parse jSon data into the cocos2d project? I know how to parse jSon (also the XML) into the xcode and display into the tableview but I need to do that for my cocos2d project.
Here is what I was trying to do:
#import "Eighties.h"
#import "HelloWorldLayer.h"
#import "GameScene.h"
#import "JSON.h"
#define kLatestKivaLoansURL #"http://api.kivaws.org/v1/loans/search.json?status=fundraising"
#implementation Eighties
#synthesize responseData;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
Eighties *layer = [Eighties node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *bg = [CCSprite spriteWithFile:#"bg.jpg"];
[bg setPosition:ccp(winSize.width/2, winSize.height/2)];
[self addChild:bg z:0];
/*
CCMenuItem *menuItems = [CCMenuItemImage itemWithNormalImage:#"back_pink.png" selectedImage:#"back_blue.png" block:^(id sender) {
NSLog(#"Pressed");
[[SimpleAudioEngine sharedEngine] playEffect:#"tongue-clap.wav"];
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[GameScene scene] withColor:ccWHITE]];
}];
*/
CCMenuItem *menuItems2 = [CCMenuItemImage itemWithNormalImage:#"back_pink.png" selectedImage:#"back_blue.png" target:self selector:#selector(loadData)];
menuItems2.position = ccp(winSize.width/2-50, winSize.height/2-50);
CCMenu *menu = [CCMenu menuWithItems:menuItems2, nil];
menu.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:menu];
}
return self;
}
-(void)test {
NSLog(#"Success");
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"Test Method Called"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
-(void)loadData
{
self.responseData = [NSMutableData data];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kLatestKivaLoansURL]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connection release];
self.responseData = nil;
}
#pragma mark -
#pragma mark Process loan data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
self.responseData = nil;
NSArray* latestLoans = [(NSDictionary*)[responseString JSONValue] objectForKey:#"loans"];
[responseString release];
//choose a random loan
for (int i=0; i<=18; i++) {
NSDictionary* loan = [latestLoans objectAtIndex:i];
//fetch the data
NSNumber* fundedAmount = [loan objectForKey:#"funded_amount"];
NSNumber* loanAmount = [loan objectForKey:#"loan_amount"];
//float outstandingAmount = [loanAmount floatValue] - [fundedAmount floatValue];
//NSString* name = [loan objectForKey:#"name"];
//NSString* country = [(NSDictionary*)[loan objectForKey:#"location"] objectForKey:#"country"];
//set the text to the label
/*
label.text = [NSString stringWithFormat:#"Latest loan: %# from %# needs another $%.2f, please help",
name,country,outstandingAmount
];
*/
NSLog(#"%d",i);
//NSLog(#"%#",label.text);
NSLog(#"\n");
/*
UIAlertView *message = [[UIAlertView alloc] initWithTitle:name
message:country
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
*/
}
}
#end
There are a lot of ways to deserialize JSON objects, some ways are even baked into the SDK.
This question details a few ways you can approach the problem.
or you can take your JSON and have this utility generate the parsing code for you
https://itunes.apple.com/us/app/json-accelerator/id511324989?mt=12

NSXMLParser can't parse special characters (accents)

I'm using NSXMLParser to parse an xml from a url (my code is almost exactly the same as here)
Some of the elements contain special characters like "á" which causes a word lik ándre to split into two (á and ndre).
Here is my loadXMLByURL
-(id) loadXMLByURL:(NSString *)urlString{
tickets = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;}
I'm pretty sure it's because the encoding is not set (I think it needs to be NSUTF8StringEncoding) but I'm not sure where/how to apply it.
[UPDATE]
Rest of my code...
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"ticket"])
{
currentTicket = [Ticket alloc];
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementname isEqualToString:#"name"])
{
currentTicket.name = currentNodeContent;
}
else if ([elementname isEqualToString:#"title"])
{
currentTicket.title = currentNodeContent;
}
else if ([elementname isEqualToString:#"status"])
{
currentTicket.status = currentNodeContent;
}
else if ([elementname isEqualToString:#"ticket"])
{
[tickets addObject:currentTicket];
[currentTicket release];
currentTicket = nil;
[currentNodeContent release];
currentNodeContent = nil;
}
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
[UPDATE 2]
Sample xml...
<RB>
<list>
<ticket>
<name>Andrew Ford</name>
<title>3rd release</title>
<status>1</status>
</ticket>
<ticket>
<name>David Jenkins</name>
<title>3rd release</title>
<status>0</status>
</ticket>
<ticket>
<name>Luis gomez ándre</name>
<title>3rd release</title>
<status>1</status>
</ticket>
</list>
</RB>
I would load the url to an NSString and then convert like this.
-(id) loadXMLByURL:(NSString *)urlString{
tickets = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSError *error;
NSString * dataString = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;
}
EDIT:
Part of the problem may be that your parser:foundCharacters: method is assigning to your currentNodeContent instead of appending. See the Apple Doc at the following link.
http://developer.apple.com/library/ios/#documentation/cocoa/reference/NSXMLParserDelegate_Protocol/Reference/Reference.html
From the doc:
Because string may be only part of the total character content for the current element, you should append it to the current accumulation of characters until the element changes.
Found the problem! It is indeed in found characters. You should change your code to this:
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(#"found characters: %#", string);
if (!currentNodeContent) {
currentNodeContent = [[NSMutableString alloc] init];
}
[currentNodeContent appendString:string];
}
I was having the same problem before, and the above code has fixed it.
Use
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
and to get the string from it, do this:
NSString *theXML = [[NSString alloc] initWithBytes:[data mutableBytes]
length:[data length]
encoding:NSUTF8StringEncoding];
Then you can parse the xml in your NSXMLParserDelegate methods.
Hope this helps.

NSTimer wont stop [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
NSTimer doesn't stop
I am having a hard time stopping my timer, witch pings to my server.
I already searched for other answers here and on other places, but i can`t seem to find where i have gone wrong.
I decided to make an example code with the same idea, but, you click a button the timer starts, you click another the timer ends, and it worked the way it should. Please don't mind if i did something wrong (other than the timer part) i'm new in this. All i want to know is why won`t it stop..
Thanks in advance.
Connection.h
#import <Foundation/Foundation.h>
#interface Connection : NSObject
{
NSString *urlString;
NSURL *url;
NSMutableURLRequest *request;
NSURLConnection *connection;
NSURLResponse *response;
NSMutableData *receivedData;
NSData *responseData;
NSError *error;
NSTimer *timer;
}
#property (nonatomic, retain) NSTimer *timer;
-(BOOL)authenticateUser:(NSString *)userName Password:(NSString *)password;
-(BOOL)checkConnection;
-(void)ping:(NSTimer *)aTimer;
-(void)logout;
-(void)timerStart;
-(void)timerStop;
#end
Connection.m
#import "Connection.h"
#import "Parser.h"
#import "Reachability.h"
#import "TBXML.h"
#implementation Connection
#synthesize timer;
-(BOOL) authenticateUser:(NSString *)userName Password:(NSString *)password
{
BOOL success;
urlString = [[NSString alloc] initWithFormat:#"my/server/address/login"];
url =[[NSURL alloc] initWithString:urlString];
request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
error = [[NSError alloc] init];
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[responseData retain];
NSString *tempString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSMutableDictionary *tempDict= [[NSMutableDictionary alloc] init];
if (request)
{
Parser *parser = [[Parser alloc] init];
tempDict = [parser readXMLString:tempString];
for (id key in tempDict)
{
NSLog(#"%# is %#",key,[tempDict objectForKey:key]);
}
if ([[tempDict objectForKey:#"login"] isEqualToString:#"true"] )
{
success = YES;
self.timerStart;
}
else
{
success = NO;
}
}
[urlString release];
[url release];
[error release];
[responseData release];
[tempString release];
return success;
}
-(void)logout
{
self.timerStop;
}
-(void)ping:(NSTimer *)aTimer;
{
urlString = [[NSString alloc] initWithFormat:#"my/server/address"];
url =[[NSURL alloc] initWithString:urlString];
request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
NSLog(#"ping");
[urlString release];
[url release];
}
-(BOOL)checkConnection
{
Reachability *reachability = [Reachability reachabilityWithHostName:#"http://my/server/address"];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
{
return NO;
}
else
{
return YES;
}
}
-(void)timerStart
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(ping:) userInfo:nil repeats:YES];
}
-(void)timerStop
{
[self.timer invalidate];
self.timer = nil;
}
#end
In timerStart you just replace whatever is in the timer property. If you start a second timer without stopping the first one, it will run forever. So timerStart should first call timerStop before creating a new one (and should probably have a new name then as it would be silly to call timerStop from timerStart).
Use [self timerStop]; using dot syntax is ONLY for properties (and will generate a warning if you don't), not calling a method in the way you're doing it.
Edit: This won't fix your problem, but doing it the way you are is very bad coding practice
-(void)timerStart
{
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(ping:) userInfo:nil repeats:YES];
}

Resources