Kyle Schwarzkopf
Kyle Schwarzkopf

Reputation: 33

How do I pause 10 seconds to send input out with out losing the data iOS

I have a button in one of my programs that, when you click it, it sends a string to a UDP packet. The string needs to be sent out 10 after the input is taken. The issue I have is that when I use an NSTimer or [self performSelector:@selector(sendUDPMessage) withObject:nil afterDelay:2.0f]; the last string is what gets sent and not the intended input.

I have also tried a couple of different kinds of loops to send the next element in the array when the sendUDPMessage function called, but I have had no luck.

As of right now this is my code:

- (IBAction)RecordButton:(UIButton *)sender {

NSDateFormatter *clockFormat = [[NSDateFormatter alloc] init];
[clockFormat setDateFormat:@"kk:mm:ss:SSS"];

NSString *myT = [clockFormat stringFromDate:[NSDate date]];
NSString *Str = display.text;

_dataString = [NSString stringWithFormat:@"0, %@, %@, \"%@\"", Str, Str, myT];

//[_updArray addObject:_dataString];

[self performSelector:@selector(sendUDPMessage) withObject:nil afterDelay:2.0f];

[_tableView reloadData];

and the function I call in the perform for selector is:

-(void)sendUDPMessage {

    data = [_dataString dataUsingEncoding:NSUTF8StringEncoding];
    [udpSocket sendData:data toHost:ipSaved port:portSaved withTimeout:-1.0 tag:0];

}

I understand why it is not working. It's because the performselector pauses sending it and not the string itself. I've tried to save the string with the sendUDPMessage, but the same issue occurs.

Upvotes: 2

Views: 130

Answers (1)

rmaddy
rmaddy

Reputation: 318955

Pass the desired data as a parameter instead of relying on the current value of the instance variable:

- (void)sendUDPMessage:(NSString *)message {
    data = [message dataUsingEncoding:NSUTF8StringEncoding];
    [udpSocket sendData:data toHost:ipSaved port:portSaved withTimeout:-1.0 tag:0];
}

And call it with:

[self performSelector:@selector(sendUDPMessage:) withObject:[_dataString copy] afterDelay:2.0f];

To expand a little:

There is no reason to use an ivar for the data string. You could do:

NSString *dataString = [NSString stringWithFormat:@"0, %@, %@, \"%@\"", Str, Str, myT];

[self performSelector:@selector(sendUDPMessage:) withObject:dataString afterDelay:2.0f];

And as Martin pointed out, using GCD is even easier. You can eliminate the senUDPMessage: method and just use dispatch_after.

NSString *dataString = [NSString stringWithFormat:@"0, %@, %@, \"%@\"", Str, Str, myT];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
    [udpSocket sendData:data toHost:ipSaved port:portSaved withTimeout:-1.0 tag:0];
});

You may even want to dispatch on a background thread.

Upvotes: 3

Related Questions