Surprise of the day: you can’t set AVAudioSession’s category in Swift 4.2 for iOS 9 and older

Today I was migrating a project to Swift 4.2 and encountered a quite bizarre issue. As it turns out, you can’t call the setCategory(_:) method on an instance of AVAudioSession in Swift 4.2 – the method was mistakenly marked as unavailable in this version of the language (and radars were filed). 

This can be a problem if your project targets iOS 9 or older, as the only alternative method setCategory(_:mode:options:) is available for iOS 10 and above. 

Objective-C to save your day!

Fortunately, the problem can easily be solved using Objective-C. You even have options here:

  • You can create an Objective-C category for AVAudioSession class and add a method that would call the setCategory:error: method, which is the objc counterpart of setCategory(_:). Just don’t forget to import the category in your bridging header.

OR

  • You can call setCategory:error using NSObject’s perform(_:with:with:) method. Like so:

This solution works because of the dynamic method resolution provided by the Objective-C runtime. NSSelectorFromString(_:) takes a method name as a string and returns a selector that was registered with the runtime system. This allows us to bypass the compile-time check for the method’s availability. And the perform(_:with:with:) method lets us send messages that aren’t determined until run-time.

To conclude, even though simple solutions for the issue were found, it still left me wondering how this silly mistake could make it to the production versions of Apple’s SDKs. 🤔

A better way of accessing properties of your view’s layer from Interface Builder

Interface Builder can make laying out complex UI a breeze. It saves a lot of time and is becoming even better and more powerful with every Xcode update. However, it is not that perfect (yet) and trivial tasks like rounding a view’s corners in IB may require doing something like this:

Yikes! Defining runtime attributes in IB is error-prone and kinda time consuming.

There is a better way of accessing the properties your view’s underlying CALayer in IB. All you have to do is to create an extension for UIView class with properties that proxy its layer’s properties and apply @IBInspectable attribute to each of those properties:

With this extension in place, you will notice that any view in IB will have a new set of attributes in Attribute inspector:

Ah, much better, isn’t it?

I hope this will make your experience with Interface Builder even more enjoyable. Happy coding! 🙂

Compiler diagnostic directives in Swift 4.2

Every once in a while, we all find ourselves in situations where we need to leave a reminder note or a message for a particular piece of code for our future selves or colleagues working on the same project. This may be a TODO or FIXME note, for example.

Until Swift 4.2, comments seemed to be the only go-to option for this kind of tasks. While many IDEs can automatically detect and highlight such comments, as far as I know, there is no similar built-in functionality in Xcode or command-line build tools.

Fortunately, Swift 4.2 introduced a couple of compiler directives for accomplishing that and even more. Using #warning directive we can now make the compiler emit warning messages:

If you use this directive, a familiar warning message will appear right next to it in Xcode and in CLI the compiler will output the warning message to the standard error stream (stderr).

#error directive halts the compilation of your code and emits a message with explanation:

Also, you can use these directives in tandem with conditional compilation:

With these directives you can rest assured that your TODO and FIXME notes won’t be left forgotten anymore. Personally, I’m very happy with these additions to the language and hope you’ll find them useful too.

Reading NFC tags using iPhone

Support for NFC was first added to iPhone 6 and iPhone 6 Plus along with the debut of Apple Pay in 2014. However, initially there was no API that would allow third-party apps to access the NFC module. Fortunately, three years later, with iOS 11 Apple introduced Core NFC, the framework used for detecting NFC tags and reading data in NFC Data Exchange Format (NDEF) from them on iPhone 7 / iPhone 7 Plus and above. In this post we’ll go through the basic steps of adding NFC reading capability to your app using Core NFC framework.

Project setup

Let’s start by setting up the project. First, you need to enable Near Field Communication Tag Reading capability for your project. To do this, select the project in project navigator, open Capabilities tab and change the switch for Near Field Communication Tag Reading to ON state. This will automatically add required entitlements to your project and, if you are using automatic signing management, will enable NFC Tag Reading service for your app ID. If you are managing app signing manually, make sure to enable NFC Tag Reading service for your app ID and regenerate provisioning profiles on Apple’s developer website.

Next, you need to add NFCReaderUsageDescription key to your project’s Info.plist file with the description of the purpose why your app requires access to NFC module. If you don’t provide this key with your usage description, the app will exit when you attempt to start an NFC tag reading session.

NDEF reader session

With these modifications in place we can jump right into coding. An instance of NFCNDEFReaderSession is used to detect and read NDEF data from NFC tags. The following example shows how to initialize a reader session and begin scanning.

During initialization you specify the delegate for NFCNDEFReaderSession, which will handle any data/errors returned from the reader session and a dispatch queue to be used for calling the delegate methods. You tell the session whether it should support multiple tag detection using invalidateAfterFirstRead parameter of the initializer.

Also, you can provide users with brief instructions by setting the session’s alertMessage property.

Once you call begin() method on the reader session, the device will start scanning for NFC tags and the standard scanning UI will be displayed with the message you supplied to alertMessage property.

You can use readingAvailable property of NFCNDEFReaderSession class to check if NFC reading capability is available on current device.

The session’s delegate should conform to NFCNDEFReaderSessionDelegate protocol. This protocol defines 2 required methods: readerSession(_:didDetectNDEFs:) is called each time NDEF data is detected and readerSession(_:didInvalidateWithError:) is called to inform the delegate when the reader session is invalidated with an error.

To stop reader session programmatically use invalidate() method.

Keep in mind that invalidated sessions cannot be reused, so a new instance of NFCNDEFReaderSession should be used to begin scanning again.

That’s all you need to add NFC tag reading capability to your app. I’ve uploaded a demo project to github, so feel free to download and play around with it.

Happy coding everyone!

How to get the UTI of any file on macOS

In this post I’d like to share with you a quick tip on how to get a file’s universal type identifier and other metadata on macOS using terminal.

With the introduction of Spotlight on Mac OS X v10.4 Apple also added a few command line tools for querying and manipulating indexes created by Spotlight. Among them is mdls, a utility that, as its man page states, “lists the metadata attributes for the specified file”. These metadata attributes include a file’s UTI and UTI inheritance hierarchy.

Using mdls is pretty straightforward:

It will print out a whole bunch of stuff and kMDItemContentType and kMDItemContentTypeTree are your file’s UTI and UTI inheritance hierarchy:

That’s it for now. I hope this helps someone.

Happy coding!

print(“Hello world!”)

Hi! My name is Davlat and I’m a software developer. As this is the very first post on this blog, I should probably outline what I’m planning to share with you here. The way I see it right now, this blog will mainly contain random thoughts of mine about different topics related to coding and other tech stuff in general.

A life of a programmer is full of captivating, sometimes even mind-bending discoveries. And when such findings strike you while you were fixing yet another nasty bug late in the night, it’s not totally unusual to have an itching desire to share with the rest of the world what you have just learnt. I think, this blog will be my place to write about such things.

Welcome to my blog and happy coding! 🙂