Topics

Topics

Apple's Files.app is a great way to interact with files on iOS.
Today we'll begin taking a look at how our app can better integrate with it. First up, we're going to learn how to allow users to open files in our app, from the Files.app. Let's get started.

We'll begin by creating a new project with the Single View App template in Xcode. In the future, we'll look at how Document Picker apps work, but for simplicity, we'll use just a plain single view app this time.

Then, we'll head into our AppDelegate.swift file, and add a new function:

This application(_:open:options:)function will be called when the user selects a file inside the Files app and presses the Share ( ) button on it, and selects our app in the UIActivityViewController that appears.

Pro Tip: We can also access this by long-pressing a file in the Files app and selecting Share from the menu:

Next we'll need to tell Xcode that our app supports the type of files we want to our app to be able to open. For this, we'll choose Text Files.

We'll click on our project at the top of the project navigator and click Info at the top. We'll find this screen:

We want that area labeled Document Types (0). We'll click the + button and enter in Text for the Name and public.text for Types.

Then, we'll add a new key to our Info.plist to make our app work more smoothly. We'll right-click on the keys at the top and select Add Row, then add the key LSSupportsOpeningDocumentsInPlace. We'll make it a Boolean and set its value to YES:

This allows our app to work with the files users open, without needing to first copy them into its own sandbox directory.

Finally, we'll head back to our AppDelegate.swift file and fill out that function we added earlier:

First we have to tell the system when we begin using a URL, saving the Bool value that url.startAccessingSecurityScopedResource() returns. If that Bool is true, then we'll also need to call stopAccessingSecurityScopedResource on our URL once we're finished with it.

After that we simply read the Data at the URL, then put it into a String so we can print it out.

Now we can Build & Run the app on our device, open the Files.app, choose an .txt file, share it, and our app appears in the Share sheet:

Tapping our app's icon opens it, and runs our code to print out the contents of the file, neat!

Continuous integration can be one of the best ways to build solid mobile apps. Nevercode delivers an awesome implementation of it for iOS, Android, Cordova, Ionic, React Native, and even Flutter-based mobile apps.

Nevercode enables developers to build, test and deploy native and cross-platform mobile applications automatically without any human interaction or any configuration headaches.

Setting up a new project is easy thanks to Nevercode's awesome automatic configuration functionality.

Nevercode will build our project for every commit we push, and run all of our Unit tests and UI tests, each time we push a new commit.

They also allow us to enable automatic build distribution. This can help our team or clients always stay up to date with how our app is progressing. They support all sorts of deployment services, including Apple's TestFlight.

Nevercode actually performed some analysis on more than 75,000 builds calculated that they save up to 20% of a developer's work day. That's about 10 weeks a year! That's the true power of continuous integration and continous deployed with Nevercode. Read more about this analysis here.

Topics

Topics

Back in Bite #292 we looked at Sourcery and how we could use it to add handy properties like count to our Swift enums. Sourcery is still just as awesome but Swift 4.2 actually removed the need for using it in this... case. 🤭 Let's take a look.

We'll be adding to the list of cases in our enum frequently as new spaceships are added, and we'd like to display the number of spaceships in our app. We could extend our enum, adding a count property:

Continuous integration can be one of the best ways to build solid mobile apps. Nevercode delivers an awesome implementation of it for iOS, Android, Cordova, Ionic, React Native, and even Flutter-based mobile apps.

Nevercode enables developers to build, test and deploy native and cross-platform mobile applications automatically without any human interaction or any configuration headaches.

Setting up a new project is easy thanks to Nevercode's awesome automatic configuration functionality.

Nevercode will build our project for every commit we push, and run all of our Unit tests and UI tests, each time we push a new commit.

They also allow us to enable automatic build distribution. This can help our team or clients always stay up to date with how our app is progressing. They support all sorts of deployment services, including Apple's TestFlight.

Nevercode actually performed some analysis on more than 75,000 builds calculated that they save up to 20% of a developer's work day. That's about 10 weeks a year! That's the true power of continuous integration and continous deployed with Nevercode. Read more about this analysis here.

Topics

Topics

Last week's introduction of the new iPad Pro brought us some fantastic improvements to the Apple Pencil. One of those improvements was the ability for the Apple Pencil to recognize simple gestures. Today we'll look at how to work these in our code. Let's dive in! 🏊‍♀️

First, let's cover the new system-level options for Apple Pencil. If we pair an Apple Pencil with our new iPad Pro by attaching it to the new magnetic inductive charger on the edge, we'll see a new item in our Settings.app for the Pencil.

Apple has provided a way for us to read these settings inside our own apps. This is through the UIPencilInteraction class's preferredTapAction class variable. This returns an enum representing the user's current selection for how the double-tap Pencil gesture should behave.

Apple recommends we make the default behavior of our apps match whatever the user has selected in Settings.app.

We'll begin by setting our view controller as the delegate of a new UIPencilInteraction object, then adding that new interaction object to our view controller's view.

Continuous integration can be one of the best ways to build solid mobile apps. Nevercode delivers an awesome implementation of it for iOS, Android, Cordova, Ionic, React Native, and even Flutter-based mobile apps.

Nevercode enables developers to build, test and deploy native and cross-platform mobile applications automatically without any human interaction or any configuration headaches.

Setting up a new project is easy thanks to Nevercode's awesome automatic configuration functionality.

Nevercode will build our project for every commit we push, and run all of our Unit tests and UI tests, each time we push a new commit.

They also allow us to enable automatic build distribution. This can help our team or clients always stay up to date with how our app is progressing. They support all sorts of deployment services, including Apple's TestFlight.

Nevercode actually performed some analysis on more than 75,000 builds calculated that they save up to 20% of a developer's work day. That's about 10 weeks a year! That's the true power of continuous integration and continous deployed with Nevercode. Read more about this analysis here.

Topics

Topics

In Bites #316 and #317, we began looking at Swift's new Codable (Encodable & Decodable) protocols. Today we'll continue by learning more about how Swift Enums work can work with these protocols. Let's get started.

First off, lets try a basic example. Here's an enum:

enumSpaceshipKind{casetransportcasefreightercasefighter}

If we simply do this:

enumSpaceshipKind:Codable{

We'll get an error: Type 'SpaceshipKind' does not conform to protocol 'Decodable'.

We can get around this by making our enum a "raw" value type like a String:

enumSpaceshipKind:String,Codable{

Nice. Since Strings are Codable, this works great. Same goes for Int and other basic Codable types.

This is a fine solution for simple use cases, but things get a little (alright, a lot) more involved when one or more of our enum cases has associated values.

Here's an example:

publicenumContentKind:Codable{caseapp(String)casemovie(Int)}

If we compile now, we get that same does not conform... error.

Let's fix that by extending our enum. First, since we'll be taking on more of the encoding and decoding logic ourselves, we'll need our own Swift Error type to throw when things go wrong.

extensionContentKind{enumCodingError:Error{casedecoding(String)}

Then, we'll need to tell Swift the keys we'll be using to encode or decode our data. We'll use another enum for this, this one adopting the built-in CodingKeyprotocol:

Then we check for each of our two possible cases, configuring ourselves and returning if successful. Finally, if we didn't return successfully and reach the end, we throw one of those CodingErrors we defined earlier.

This time we grab the encoder's container up front, then simply switch on ourselves to see which value to encode.

Now our associated value enum can be encoded and decoded all we want. Nice!

Pro Tip: Writing all of this by hand can get extremely tedious for anything more than a few simple cases. Try something like Sourcery (Bites #292, #294, and #295) to generate this more boilerplate-ish Codable implementation.

We'll sign up with Github (we could also use Bitbucket, GitLab, or sign up with email / password for repos on any other git server). Neat!

Next, buddybuild will let us choose a git repo to create our first project with.

Once we select the repo we want to build, buddybuild will get to work building our app for the first time.

After that build is complete, our app is set up on buddybuild - it's that easy.

buddybuild installs and configures the necessary web hooks for our project so new builds are triggered whenever code is pushed. It also scans your repo for any tests you might have written, and runs them reliably on the simulator and physical devices.

With buddybuild, we won't need to wait for App Store processing time or reviews before deploying to testers.

buddybuild's continuous deployment system can send our app to users instantly on every build, on a schedule that works for our team, or at the push of a button.

This kind of comprehensive Continuous Integration and Continuous Deployment workflow is a game changer for iOS and Android teams. It also means we can have our whole development workflow set up in just minutes. We can also infinitely customize and extendbuddybuild so it exactly just the way we want.

Buddybuild's deployment service also handles the process of adding new users (and their devices) by automatically managing UDIDs, iOS provisioning profiles and signing identities. (Fantastic UX for both testers and devs!)

Only buddybuild goes even farther, and gives us a fully integrated feedback platform.

Once users have installed our app and are testing it out, they can send their feedback (along with important diagnostic details) by simply taking a screenshot.

buddybuild also has rich pull request support. We can even pair it up with Danger to automate (the usually tedious) code review processes.

If our team works with pull requests frequently, buddybuild can be configured to build the pull request, then merge, commit, and update the commit status in GitHub, Bitbucket and GitLab. This ensures we always know before when a pull request is safe to merge.

If we have Unit Tests or UI Tests for our app, buddybuild will consistently and reliably run them as part of every build and automatically display how much of our codebase is covered by our tests. Neat!

If our app ever crashes, buddybuild's Source Context functionality will trace back and highlight the exact line of offending source code that caused the crash, telling us which users were affected, and how many times the crash happened.

Each crash is also recorded with an Instant Replay - this is a video replay of our users' actions in the moments leading up to the crash. Never wonder about "steps to reproduce" again! Super cool.

Buddybuild is also a great community citizen, and has our backs as iOS developers. For example, they'll give us a heads up on any potential breaking changes in Xcode. Within 48 hours of any Xcode release (including betas!), buddybuild will automatically takes our most recent successful build, and build and run tests against it using the latest version of Xcode. Then it will email us the results. How cool is that?!

Last but certainly not least, buddybuild not only comes with built-in integrations with tons of services we all know and love like GitHub, BitBucket, GitLab, Slack, JIRA Pivotal Tracker, Slack, HipChat but it's also infinitely customizable to meet the exact needs of your development team!

Topics

Topics

They appear everywhere from our Application's Identifier all the way down to the Dispatch Queues we create in our code.

These identifiers are somewhat opaque in a conceptual sense, and have been around in programming for many years.

We create or set them once, and sometimes reference them in our code, but the main idea is that they're a unique, human-readable way to identify some unique "thing". Their nature also offers the benefit of being unlikely to "collide" with one another.

The first thing we'll want to define is some kind of top level prefix to put on all our identifiers.

Fun Fact:Historically these identifiers were literally reversed-DNS. That is to say, to form one in code we might take our website's domain name, reverse it, then append our app's name (for example). These days, on Apple platforms, this isn't really a "thing" anymore. Now, we're usually given a string property or text field where we can supply just about any value we want.

This means that the common TLD's on the internet are also commonly used here. A company may begin all of their identifiers with com., while a non-profit may start theirs with org..

Next, we'll want to think of some way to group all of our identifiers, across all of our apps.

Often this is a domain-style version of our company or organization's name, or perhaps simply our own name, all lowercased, with no punctuation.

Applications and Extensions

com.littlebites.reader - An identifier for an imaginary app to read Bites. We might be tempted to just use com.littlebites.app or something generic, but this way we leave ourselves open to the possibility of making other apps in the future.

In-App Purchase Identifiers

With these, we want to think about the complete set of In-App Purchases we plan on offering and create groups within them if possible.

We know we want to offer other types of In-App Purchases in the future, so we've "grouped" all subscription purchases under a subscriptions. segment. Then we're able to add a shorter phrase denoting the type as the final segment.

App Groups

App Groups help us share data between our apps or our app's extensions.

group.com.littlebites.cache, group.com.littlebites.user - Apple encourages to begin these with the group.. This way we know right away what we're dealing with. Here we've created two app groups, one to share less-important cache data (images, etc.) between apps while we sort of "wall-off" user data into it's own group.