How to add auto-update feature in macOS app: Step by Step guide to setup Sparkle framework (Part 2)
Tags: sparkle, macos, swift, tutorial
Published: 2020-02-25 19:11:24


**Recap of Part 1** - We learned what Sparkle is, and why we need it for apps released outside of the macOS App Store. We added Sparkle in our app via Cocoapods. We also learned few concepts related to Sparkle, how does Sparkle works, appcasts, how to serve appcast XML, and finally, we configured Sparkle to give the location info of our appcast XML, using which it can figure out whether a newer version of our app exists.

Let's begin this part where we left off in the previous. Build and run the app.

The below screenshot is the state of the app where we left off in the previous part.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xz30egj0sqgakjm0xl1l.png)

Go ahead and try to update the app by clicking on the "Install Update" and you should see the following behavior with an error alert generated at the end, captured in video recording below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1dluh2fku2nga7lxj3d8.gif)

<a name="issue"></a>
#####Observations from using current version of the app (v1) thus far:

* App remains open upon clicking the "Check for Updates" button. This behavior causes the *Sparkle update alert* hidden behind the App. This behavior is an **issue**, and we fix it in version 2 of the App. The app updates to version two via Sparkle
* When we click on "Install Update," Sparkle downloads "a" version of "some app." We don't have a version two yet (heck, we don't even have the binary of current version one), so what does it download then?
 * We are using a default appcast XML from Sparkle, which comes with a test app "https://sparkle-project.org/files/Sparkle%20Test%20App.zip". Once we have a binary for version 2, we replace this test app URL with ours.

##Production ready

Releasing a macOS app, which can also be trusted by users, especially if we are distributing the App outside of the App store, means code signing and getting the App notarized by Apple. So let's do it.

> For us to be able to test updates via Sparkle, our App should be in binary form and run from within the Applications folder (not via Xcode).

The first step in creating a binary of your macOS app is Archiving it. Archive your App in Xcode by clicking on the "Archive" option under the "Product" menu. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vcl5b1bw2gi4c1dhssad.png)

Once the generation of the Archive instance is finished, click *Distribute App*" Since we are distributing the App directly to our users, select the "Developer ID" option as the method of distribution.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4ft39tlkd2md3cmh53s4.png)

Click "Next." You get an option to upload your App to Apple notary service or proceed without notarizing.

If you are thinking of proceeding without Notarizing your macOS app, then **think again**. While this tutorial is not about App code signing or Notarization, but I feel Apple notarization is very important and should always be considered, so adding more info about it.

> [Apple Notarization](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution) helps the user know that the App doesn't contain any malicious code

> *Notarization gives users more confidence that the Developer ID-signed software you distribute has been checked by Apple for malicious components.*

{% twitter  1182080325486350336 %}

{% twitter  1182076300254679040 %}

{% twitter  1182077955981414401 %}

Not only does apple notarization provide confidence for your user, but starting with macOS Catalina, an App distributed outside of App store [must be notarized](https://developer.apple.com/news/?id=09032019a) by Apple to run on macOS Catalina

Ok, now that we understood the importance of Apple notarization, let's move on to the next step, which is choosing the option to *Upload* to Notary service. Click "Next."

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/69cdgk4igq6pcd3lzzvx.png)

Boom, We see an error. Well, we did everything right, then what is causing this error? All comes back to code-signing and Notarization. The Apple notarization process is a topic in itself, and Apple covered it in great detail in [WWDC 2019](https://developer.apple.com/videos/wwdc2019/). You can watch the video [here](https://developer.apple.com/videos/play/wwdc2019/703/).

So let's get to resolving the issue that is causing the failure to upload to Notary service. First, describing the issue in brief. Not only our App code but any deeply nested code withing our App must also be code signed with our Developer ID, for us to be able to get our App Notarized by Apple. In our case, Sparkle code is embedded in our app binary, and also needs to be codesigned by our Developer ID. In the normal codesigning process, it does not automatically codesign embedded code/app, so we need to do it explicitly. In the following part, we add a step to codesign Sparkle and resolve upload to notary issue.

##Codesigning and Notarizing Sparkle

In Xcode, head over to your project's Targets "Build Phase" tab. Click on **+** sign located on the top left and add a "New Run Script Phase." I call my run script *Run Script - Deep Signing Sparkle framework*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zpl62bs4k76nu7k2p29d.png)

Inside script text field type in the following script:

```
#For Apple notarization, we need to deep sign Sparkle framework
LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}"
IDENTITY=${EXPANDED_CODE_SIGN_IDENTITY_NAME}

codesign --verbose --force --deep -o runtime --sign "$IDENTITY" "$LOCATION/Sparkle.framework/Versions/A/Resources/AutoUpdate.app"
codesign --verbose --force -o runtime --sign "$IDENTITY" "$LOCATION/Sparkle.framework/Versions/A"
```

This Run Script build phase should solve our failure to Upload to Notary service issue. Let's see if it did. Start over and Archive again. Once it is archived, click "Distribute App" and choose the "Developer ID" option. Click "Next" and finally the moment of truth. Choose "Upload" (*send to Apple notary service*) option and click "Next." This upload was the step that gave the error before.

This time upload to notary service works. See [screen recording](https://dev-to-uploads.s3.amazonaws.com/i/vh109c88ax24b6zeht14.gif) below.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vh109c88ax24b6zeht14.gif)

Once Apple successfully notarizes our App, it sends us notifications. For a super simple App like ours, I got it within a couple of minutes.

Apple delivers notarization completion notification via both email and Xcode.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c17hfswmf9b4gshbqjjv.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2vl8ksugppy0dtg6sc4q.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gschmpcnbxra1apnr7io.png)

Finally, we are successful in notarizing our App. Now it's time to distribute our App to users. For that, let's export App in the form of the .app file (binary). The version of the Archive that got notarized has "Ready to distribute" under Status.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hlws3kg524ypsfzndgrl.png)

Click on the "Export App" button and save .app file. 

**Congrats**, you have successfully finished creating a distributable signed and notarized first version of your App.

All that is left is moving the .app file to your Application folder. Go ahead and move it and launch your App by clicking on the App icon. 

The App works similar to how it worked when we run it from Xcode. So now, we need to fix the [issue](#issue) we found earlier in this version of the App.

This brings us to the end of Part 2.

In Part 3, we fix this [issue](#issue) and update the App to version 2. Create version 2 binary and upload it to the cloud. Update our appcast XML, with relevant release notes, to notify to the (current) version 1 that a newer version is available for update. Finally, the current version of the App, sitting in our Application folder, gets updated to version 2 via Sparkle. 

Well, we did quite some work, and so it's good to take a quick break. For some, a break could be taking a walk or stretch, then go ahead and do that (come back later for this last exciting part). However, if you one of those who find trivia to be exciting and save them for interesting party conversations, then here is one for you.

:bulb: *There is just one letter that's not in ANY of U.S. state name. What is that letter?* 🤔 *Think about it and then head [here](https://www.rd.com/culture/letter-not-in-any-state-name/) to check if your answer was correct*