1

I am using CocoaHTTPServer in a MacOSX app (Server) that serves up a local directory of images. I have a corresponding iOS app (Client) that uses AFHTTPRequestOperation (AFNetworking) to retrieve an image file from the Mac over the local network. This is working well.

What I would like to do next is, when a user chooses a specific image in the Mac app the iPad app is notified to download that image and display it.

The method I currently employ is to serve a simple imageToDisplay.txt file that includes the file name of the image to display. The iPad app is constantly polling this file, and if the filename changes it downloads it, etc. It works but seems clunky. I have thought of implementing a GET method on the server that would also return the filename. This approach would still require polling by the client.

Is there a more elegant way to trigger the download (without polling) with the pieces I already have in place? Essentially sending a message from the server to the client - "download image27.jpg now"

gheclipse
  • 971
  • 8
  • 13
  • Look at WebSockets: https://github.com/robbiehanson/CocoaHTTPServer/tree/master/Samples/SimpleWebSocketServer – user523234 Aug 28 '13 at 21:16
  • @user523234 thanks for bringing that to my attention. I was practically able to drop in the SimpleWebSocketServer sample into my server app. Now, just need to determine which client code to use. – gheclipse Aug 30 '13 at 13:39

1 Answers1

1

WebSockets (SocketRocket)

There are a few ways you could implement this. As noted in the comments, WebSockets is one. The most robust freely available WebSockets library for iOS is SocketRocket (which rhymes). There is ample sample (also rhymes) code on the page I just linked to, so I won't include any here.

AFNetworking

Since you're using AFNetworking already, you could also take a look at the new AFNetworking 2.0 (to be released soon), which includes support for realtime networking via Rocket.

This would allow your app to maintain an open connection, and would look something like this:

[client SUBSCRIBE:@"/currentImage" usingBlock:^(NSArray *operations, NSError *error) {
    for (AFJSONPatchOperation *operation in operations) {
        switch (operation.type) {
            case AFJSONReplaceOperationType:
                // replace old image with new image
                break;
            default:
                break;
        }
    }
} error:nil];

As long as your client doesn't cancel, it will continue to receive updates from the server whenever they happen.

Your server would need to send data in the appropriate format, and there's an experimental branch of Rack::Scaffold that does this.

Notes

These approaches might be overkill if you're only changing your image once a week; in that case you should cache an image for some reasonable time period.

Community
  • 1
  • 1
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Excellent. I have a prototype client running with SocketRocket. I didnt know AFNetworking had this functionality so I will look at that also. – gheclipse Aug 30 '13 at 13:44
  • With this approach will I need to do anything additional to support multiple clients? Does each one have its own Socket (so I can communicate individually with each client) or are all clients listening to the same line? – gheclipse Aug 30 '13 at 13:46
  • Each client has its own connection (because you might want to communicate different data to different clients). But if your implementation ignores that, it will just send the same data to every client. – Aaron Brager Aug 30 '13 at 16:18