5

I'm working on an Objective-C Cocoa app in Xcode for OSX which will be distributed outside the App Store.

One of the menu items in the app is "Check for Updates". The user can click this item and check if there's an update available.

If there is an update available, the update will be downloaded.

My question is : What is the common approach for updating an app? Since the app is open, it can't overwrite itself. So how is this typically done?

Do you separate your app into a launcher and the app itself? If so, I imagine that when the user starts the app, it is in fact the launcher that's started. The launcher then checks to see if an update has been downloaded and it replaces the old app binary with the new app binary. Is that how it's done on OSX or is there a smarter way?

user1884325
  • 2,530
  • 1
  • 30
  • 49
  • 4
    if your app is available on the App Store, you can let the App Store app handle updating for you. There's also a [free software update framework that's quite popular named Sparkle](http://sparkle.andymatuschak.org). – Michael Dautermann Sep 23 '13 at 16:58
  • 2
    Michael's comment covers both of the standard ways, it should probably be an answer – Catfish_Man Sep 23 '13 at 17:18

1 Answers1

8

Sparkle is really good, however if you prefer in-house solution then here is one possible approach.

Steps:

  • Old application (after launch) checks for updates
  • if update found download and unpack it into a temp location
  • launch an external application do to the "swapping" replace old currently running app with the new one unpacked into a temp location
  • old app terminates

Where the real "magic" happens is when old app is done with the download and unpack. Then old app from it's bundle copies to a temp location it's relauncher (simple terminal app) and launches it with the following command line args:

  • First param is the process ID of the old app (which is running)
  • Second is the path to the new version (this will be moved into Applications folder)
  • Third (optional) path to the old application (used to delete it explicitly)

When all is done, after launching the relauncher old app terminates. At this point relauncher is already running and waits for old app's termination.

When old app terminates then relauncher does three things:

  • Deletes the old app from Applications
  • Copies new version from temp location into Applications
  • Launches the new version from Applications.

Update is done.

robert
  • 5,742
  • 7
  • 28
  • 37
  • How should I go about 'downloading and unpacking it'? I have thought about using zips but it seems next to impossible! Should I think about downloading the whole .app directory from the server? – maxisme Oct 06 '15 at 12:39
  • I suggest to download one zip file. Inside that zip file is the whole .app directory. Then unzip it you can find it how here: [link](http://stackoverflow.com/questions/2296667/unzipping-a-file-in-cocoa) – robert Oct 09 '15 at 17:59
  • Okay thanks! And now any ideas on how to get the external application to work?! – maxisme Oct 10 '15 at 12:05
  • I would try the same approach as with unzip. [link](http://stackoverflow.com/a/17856486/2050306) – robert Oct 10 '15 at 12:19
  • Sorry I meant an external application that will close the old app and open the new one? – maxisme Oct 10 '15 at 12:21
  • Yes I understood that. Unfortunately I don't have access to the original source code. Anyway try to create a new NSTask object and point it to the external application with different parameters. Try first with simple terminal app just to dump out params etc. – robert Oct 10 '15 at 12:35
  • I have built the app with just the .m file of a project. But won't a terminal app require the user to enter there sudo password? Also Wont I have to have the app embedded within my project as the user shouldn't need to download another application? Very confused by this process!! – maxisme Oct 10 '15 at 14:34
  • In this case sudo password is not required for terminal app. Yes, you have to embed the terminal app(the relauncher) inside your app bundle. User initially downloads you app bundle and inside it will be your relauncher too. So no need for separate download. Just for new version inside a zip file. If the process is still confusing try to break it to simple and smaller parts. Try to play first with NSTask, then try to build a simple Terminal app. Give it few command line args and dump them out. Then combine the two etc. – robert Oct 10 '15 at 16:34
  • I’m looking to do this same thing. @maxisme Did you ever figure this out? – Clifton Labrum Jun 06 '20 at 06:01
  • @CliftonLabrum I just used sparkle in the end! Pretty straight forward to set up. – maxisme Jun 06 '20 at 08:05