In deze korte tutorial wil ik me concentreren op Swift's nieuwe syntaxis voor beschikbaarheidcontrole. Als u enige hoeveelheid iOS- of OS X-ontwikkeling hebt gedaan, weet ik zeker dat u weet hoe vervelend het kan zijn om te controleren of een bepaalde API beschikbaar is op het apparaat waarop uw toepassing wordt uitgevoerd. In Swift 2 is dit voor ontwikkelaars veel minder lastig geworden.
Stel het volgende scenario voor. Je ontwikkelt een iOS-applicatie die iOS 7 en hoger target. Tijdens de WWDC van vorig jaar introduceerde Apple een nieuwe API voor meldingsregistratie.
registerUserNotificationSettings (_ :)
Betekent dit dat u het implementatiedoel van uw toepassing van iOS 7 naar iOS 8 moet verhogen? U zou dat kunnen doen, maar het zou een aanzienlijk deel van het gebruikersbestand van uw toepassing in de kou laten staan, alleen om te voldoen aan het nieuwe beleid van Apple voor lokale en externe meldingen. Uw gebruikers zullen u daarvoor niet bedanken.
Het alternatief is om de nieuwe API alleen te gebruiken op apparaten met iOS 8 en hoger. Dat is logischer. Rechts? De implementatie zou er ongeveer zo uitzien.
func applicatie (toepassing: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool if UIApplication.instancesRespondToSelector ("registerUserNotificationSettings:") let types = UIUserNotificationType.Alert | UIUserNotificationType.Sound | UIUserNotificationType.Badge let settings = UIUserNotificationSettings (forTypes: types, categories: nil) application.registerUserNotificationSettings (settings) return true
Dit is een haalbare optie, maar het is geen risico. In deze tutorial zal ik niet ingaan op de details van die risico's, maar ik wil wel benadrukken dat de meeste ontwikkelaars vinden dat het prima is om de bovenstaande aanpak te gebruiken. Het volgende voorbeeld toont een variatie op deze benadering, deze keer met behulp van Objective-C.
if ([UIUserNotificationSettings class]) [application registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes: (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge) categories: nil]];
Hoewel beide benaderingen in de meeste situaties werken, zijn er situaties waarin u problemen tegenkomt. Sommige API's beginnen bijvoorbeeld hun leven als privé-API's en worden in een later stadium openbaar gemaakt. In dat scenario raakt u mogelijk privé-API's op apparaten met een besturingssysteem waarin die API's nog niet openbaar zijn. En ik weet zeker dat je weet wat dat betekent.
Dankzij het werk van het Swift-team is de oplossing voor ons probleem eenvoudig en duidelijk in Snel 2. Bekijk het volgende voorbeeld. Merk op dat het implementatiedoel van het project is ingesteld op iOS 7, met behulp van Snel 2 en Xcode 7.
In het voorbeeld gebruiken we API's die zijn geïntroduceerd in iOS 8. Omdat de compiler weet dat het implementatiedoel van het project is ingesteld op iOS 7, wordt er een fout gegenereerd door ons te vertellen dat de API's die we willen gebruiken alleen beschikbaar zijn in iOS 8 en hoger. Hij weet dit door de SDK te controleren op beschikbaarheidsinformatie. Als u op drukt Commando en klik op de registerUserNotificationSettings (_ :)
methode, zou u zoiets moeten zien.
@available (iOS 8.0, *) func registerUserNotificationSettings (notificationSettings: UIUserNotificationSettings)
Gelukkig biedt Xcode ons een oplossing om het probleem op te lossen. Het suggereert om een versiecontrole te gebruiken om te voorkomen dat de API's exclusief voor iOS 8 en hoger worden aangeroepen als onze gebruikers de applicatie uitvoeren op een oudere versie van iOS.
Merk op dat deze functie werd geïntroduceerd in Swift 2. De compiler werpt geen foutmelding als je Swift 1.2 gebruikt. De toevoeging van de versiecontrole maakt het voorbeeld ook gemakkelijker te begrijpen. Bekijk het bijgewerkte voorbeeld hieronder waarin we het advies volgen dat Xcode ons heeft gegeven.
func applicatie (toepassing: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool if #available (iOS 8.0, *) let types = UIUserNotificationType ([UIUserNotificationType.Alert, UIUserNotificationType.Sound, UIUserNotificationType.Badge]) let settings = UIUserNotificationSettings (forTypes: types, categories: nil) application.registerUserNotificationSettings (settings) return true
De syntaxis is duidelijk en begrijpelijk. Met behulp van de beschikbaarheidssyntaxis controleren we of de app wordt uitgevoerd op een apparaat met iOS 8 en hoger. Als dat niet zo is, de als
clausule wordt overgeslagen, anders roept de applicatie de nieuwe API op voor notificatie registratie.
De syntaxis is eenvoudig. We beginnen de beschikbaarheidsvoorwaarde met #beschikbaar
en wikkel de voorwaarde tussen haakjes. We kunnen zoveel platforms toevoegen als nodig is, en scheiden de lijst met platforms met komma's.
if #beschikbaar (iOS 8.0, OSX 10.10, watchOS 2, *) ...
Merk op dat we de lijst met platforms met een asterisk beëindigen. Dit sterretje is verplicht en geeft aan dat het als
Deze clausule wordt uitgevoerd op het minimale implementatiedoel voor elk platform dat niet is opgenomen in de lijst met platforms.
Zoals we eerder zagen, kunnen we de @beschikbaar
attribuut om beschikbaarheidsinformatie toe te voegen aan functies, methoden en klassen. In het volgende voorbeeld vertellen we de compiler dat de useFancyNewAPI
mag alleen worden aangeroepen op apparaten met iOS 9 en hoger.
@available (iOS 9.0, *) func useFancyNewAPI () ...
Houd er rekening mee dat de beschikbaarheidsyntaxis geen alternatief is voor de twee voorbeelden die ik aan het begin van deze zelfstudie heb laten zien. Deze voorbeelden zijn onjuist en mogen alleen worden gebruikt als u Objective-C of een eerdere versie van Swift gebruikt.
De beschikbare syntaxis is nog een andere reden om uw Swift-projecten naar Swift 2 te migreren. Het verwijdert foutgevoelige oplossingen voor het controleren van de API-beschikbaarheid. De wereld ziet er een beetje vriendelijker uit met Swift 2. Doens't it?