Question

I am running a NSOperation in a separate queue which runs indefinitely and is set up to handle web socket events. The events are handled in my - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message method in this operation

Is this the correct way to code the main method if this NSOperation?

- (void)main
{
    [self openSocket];

    while (!self.isCancelled) {
       //
    }
}

Edit

The main purpose of this NSOperation is to handle SocketRocket messages and send requests. Handling and processing these events works fine. But how can I make my operation make run indefinitely (without using an empty while loop)?

Was it helpful?

Solution

That's what NSRunLoops are made for. As per apple's docs

A run loop is an event processing loop that you use to schedule work and coordinate the receipt of incoming events. The purpose of a run loop is to keep your thread busy when there is work to do and put your thread to sleep when there is none.

But... I see from your code that you are using Square's SocketRocket library, by looking in the source code of the library you can find out that they are already doing this, so probably you are doing something wrong. You should really expand your question to let us understand what the real problem is, since your SocketRocket object should be ALREADY running and should be ALREADY sending the right notifications when a particular event occurs.

Edit:

From what you said, you simply do NOT need an object that runs indefinitely but rather an object that stays alive as long as your application is alive.

For this you can either use the app delegate, an object being kept alive by the app delegate (aka an app's delegate's property) or a singleton object. Now, for the simplicity sake, i'll use the first example:

in your app's delegate .m file implement the SRWebSocket delegate:

@interface SRAppDelegate()<SRWebSocketDelegate>

@property (strong, nonatomic) SRWebSocket* socket;

@end

@implementation SRAppDelegate

#pragma mark - SRWebSocketDelegate

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
{

}

#pragma mark - SRWebSocketDelegate optionals

- (void)webSocketDidOpen:(SRWebSocket *)webSocket
{

}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
{

}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean
{

}

@end

Then in your - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method initialize the connection:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.socket = [[SRWebSocket alloc] initWithURLRequest:_YOUR_REQUEST_];
    self.socket.delegate = self;
    [self.socket open];
    //Enjoy!
}

Now you have a long living connection (as long as your application is alive).

OTHER TIPS

If you have your own socket mechanism, you can integrate it into NSRunLoop by making a CFRunLoopSource out of it.

Just a bit of note when doing that (my usual machine is not with me, so code snippet is largely inaccessible now) you can use CFEqual (-[NSObject isEqual:]), CFHash (-[NSObject hash]), CFCopyDescription (-[NSObject description]), CFRetain (-[NSObject retain]) and CFRelease (-[NSObject release]) against any Objective-C objects - consider it like you can toll-free bridge NSObject and CFTypeRef so you can bridge cast self to fill in the info (void * type which is exactly CFTypeRef) and use those functions as callbacks of your CFRunLoopSource and here is a quick implementation of the perform callback:

void _MSCFRunLoopPerformCallback(id self)
{
    [self runOnce];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top