After some questions here I decided to run a server like this:
@implementation Server
-(id)init
{
if (self = [super init])
{
shouldRun = true;
__block Server* blocksafeSelf = self; // should prevent retain cycle
myServer = ^() {
dispatch_async(dispatch_get_main_queue(), ^{
NSString* currentText = controller.output.text;
controller.outputTextField.text = [currentText stringByAppendingString:@"Server ready. \n"];
});
while (blocksafeSelf.shouldRun) {
int bytes_received = recvfrom(...);
if (bytes_received > 0) {
switch (TYPE OF RECEIVED PACKET) {
case 1: {
dispatch_async(dispatch_get_main_queue(), ^{
NSString* currentText = controller.outputTextField.text;
controller.outputTextField.text = [currentText stringByAppendingString:@"S: Received Typ 1 "];
});
[blocksafeSelf methodToDealWithPacket:(PACKETTYPE*) buffer];
break;
}
...
default: {
...
}
}
}
}
return self;
}
@synthesize shouldRun;
the corresponding .h file:
@interface Server : NSObject {
ServerBlock myServer;
....
}
@property BOOL shouldRun;
....
@end
Now I have a ViewController, which has the Server as a property and following method in its implementation:
// called when the user clicks the stop button
- (IBAction) clickedStop
{
if(theServer != nil) {
theServer.shouldRun = false;
}
}
When I click the stop button however, the server does not exit his while loop. Why?
edit: Here is, how the server is started in the ViewController:
// called when the user clicks the start button
- (IBAction) clickedStart
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
if (...) { // all needed data has been entered
// start server here
if(theServer == nil) {
theServer = [[SNPTServer alloc] initWithHost:serverIP.text AndPort: [serverPort.text intValue] AndViewController:self];
dispatch_async(queue, theServer.myServer);
}
}
}
As you see, I have altered the constructor above a bit.
My answer will only work if the body of your while loop looks similar to the following (I will assume it does)
In this case, just setting shouldRun to NO is not enough. That while loop is running on a different thread/runLoop so an event must happen to cause the run loop to pop so that the condition is checked again.
The easiest way to do that is to set shouldRun to NO from the thread that server is running on. I would do something like this:
And then when you want to cancel it do: