De Swift Playgrounds-app voor iPad is altijd een beetje verscheurd geweest tussen twee zeer verschillende soorten gebruikssituaties. Aan de ene kant is de app duidelijk gebouwd met een primaire focus op onderwijs en een geweldige tool voor beginners, maar aan de andere kant is het ook de enige manier voor professionele ontwikkelaars om Swift-code lokaal op hun iPad te draaien.

Interessant genoeg plaatst dat Swift Playgrounds in een vergelijkbare positie als de iPad als geheel, in die zin dat de app zowel casual en eenvoudige gebruikers moet bedienen als een capabele tool voor meer geavanceerde gebruikers, vooral gezien de stijgende populariteit van de iPad Pro als een compleet computerplatform.

Deze week bekijken we hoe goed de nieuwe 3.0-versie van Swift Playgrounds die balans tussen eenvoud en kracht bewandelt, en hoe sommige van de nieuwe functies echt de manieren verbeteren waarop het kan worden gebruikt als een zeer draagbare, geavanceerde Swift-ontwikkeltool.

Instabug: Los bugs, crashes en andere problemen veel sneller op met behulp van de gedetailleerde stack traces, netwerklogs en UI-gebeurtenissen die Instabug automatisch aan elk bugrapport koppelt. Gebruikt door zowel mijzelf als duizenden iOS ontwikkelteams over de hele wereld. Probeer het gratis uit en integreer het met slechts één regel code.

Werken, spelen en onderwijs

Het duurt niet lang voordat je doorhebt dat Swift Playgrounds vooral bedoeld is als hulpmiddel voor studenten, docenten en voor mensen die willen leren coderen. Meteen na het openen, presenteert de app prominent verschillende coderingslessen en leeruitdagingen – en alles, van de gebruikte taal voor menu-items en commando’s, tot de release notes van de app in de App Store, hebben een duidelijke onderwijsfocus.

Hoe dan ook, zodra je een lege speelplaats opent en begint te coderen, zijn de werkelijke mogelijkheden van de app altijd behoorlijk indrukwekkend geweest – van de manier waarop het volledige toegang biedt tot de iOS SDK en Foundation, tot de manier waarop het ons in staat stelt views en view controllers native te renderen met behulp van PlaygroundPage.current.liveView, tot de snelheid van de compiler – vooral op de nieuwste iPad Pro-modellen.

Versie 3.0 voegt ook enkele zeer welkome verbeteringen toe aan de mix. Om te beginnen is de compiler nu bijgewerkt naar de Swift 5.0-versie, en de algehele stabiliteit van de editor en de manier waarop deze samenwerkt met de compiler is ook verbeterd. Wanneer een crash of runtime error optreedt, presenteert de app niet langer een eenvoudige waarschuwing die zegt dat er iets mis is gegaan, maar presenteert rijke foutmeldingen naast de regel code die de fout heeft veroorzaakt – en compilatiefouten worden nu weergegeven in een “Issues” lijst, vergelijkbaar met die in Xcode.

Modules gemakkelijk gemaakt

Misschien wel de grootste verbetering voor ontwikkelaars die Swift Playgrounds als een echte ontwikkeltool willen gebruiken, is de toegevoegde ondersteuning voor modules die meerdere bronbestanden bevatten. Swift modules zijn in wezen het “pure Swift” equivalent van een bibliotheek of framework, en de manier waarop ze zijn geïntegreerd in de Playgrounds app is gewoonweg fantastisch.

Een nieuw document icoon is nu te vinden in de linkerbovenhoek van de editor – en door erop te tikken verschijnt een popover waarmee we kunnen bladeren, en wijzigen, in de huidige playground’s bronbestanden en modules. Zowel nieuwe bestanden als nieuwe modules kunnen worden toegevoegd met een paar tikken, en elk nieuw bronbestand wordt automatisch geopend als een nieuw tabblad in de editor. Het is naadloos, snel, en maakt het triviaal om een groter stuk code op te splitsen in aparte modules. Elke module wordt ook automatisch geïmporteerd in de speeltuin, terwijl er nog steeds expliciete imports tussen modules nodig zijn.

Vergelijk het bovenstaande met het aantal stappen dat nodig is om een nieuw Swift-framework in Xcode toe te voegen.

Modularisatie kan vaak van groot belang zijn om een project gemakkelijker te kunnen onderhouden – vooral wanneer de hoeveelheid functies en bronbestanden groeit. Door dingen op te splitsen in afzonderlijke modules, elk met zijn eigen verantwoordelijkheid en domein, kunnen we zowel zorgen voor een redelijke mate van scheiding van belangen – en ook gemakkelijk te identificeren architectonische problemen, zoals wanneer twee verschillende stukken code zijn te sterk gekoppeld, of wanneer een uitzicht maakt te veel aannames over de gegevens die het rendert (omdat het verkrijgen van toegang tot dergelijke informatie zou nu het importeren van een andere module nodig).

Modules stellen ons ook in staat om gebruik te maken van het internal toegangscontrole niveau, en om typen en functies die alleen bedoeld zijn voor intern gebruik binnen een module ontoegankelijk te maken van buiten die module. Aangezien internal het standaard toegangsniveau in Swift is, betekent dat ook dat we de types en functies die we willen uitlenen als onderdeel van de publieke API van onze module expliciet moeten markeren als public. Hoewel sommige ontwikkelaars dat misschien een beetje een “karwei” vinden, dwingt het ons in zekere zin om meer duidelijke en goed gedefinieerde API’s te ontwerpen.

Xcode compatibiliteit

Hoewel Swift Playgrounds nu veel kracht en een aantal nieuwe functies heeft gekregen die het een veel capabeler ontwikkeltool maken, is het voor de meeste gebruikssituaties verre van een volledige vervanging van Xcode – en dat probeert het ook niet te zijn. Er zijn goede redenen waarom het “Swift Playgrounds” heet en niet “Xcode voor iPad” (hoewel we hopelijk dat laatste op een gegeven moment ook zullen zien). Het is een tool voor het spelen met ideeën, voor het doen van lichtgewicht codering onderweg, en voor het bouwen van prototypes en geïsoleerde modules – in plaats van een complete IDE met ondersteuning voor complexe projecten.

Dus aangezien – voor de meeste ontwikkelaars – Swift Playgrounds waarschijnlijk zal fungeren als een aanvulling op Xcode, in plaats van een vervanging, hoe gemakkelijk is het om projecten en code te verplaatsen tussen de twee? Helaas is het antwoord, voor het grootste deel, niet zo eenvoudig. Hoewel apps zoals Working Copy (disclaimer: voormalige sponsor), en tools zoals Shapeshift (disclaimer: geschreven door mij) het vrij triviaal maakt om de broncode te verplaatsen tussen de Mac en de iPad – is er helaas zeer weinig directe compatibiliteit tussen Swift Playgrounds en Xcode.

Om te beginnen gebruiken ze verschillende bestandsformaten. Xcode gebruikt nog steeds het .xcodeproj-bundelformaat dat het al jaren gebruikt, en hoewel door Xcode gemaakte .playground-bestanden op de iPad kunnen worden geopend, gebruiken de playgrounds die in de Playgrounds-app zelf zijn gemaakt het alleen voor iPad geschikte .playgroundbook-formaat.

Het enige dat Xcode 10 kan doen met Swift Playgrounds-bundels is een pictogram weergeven – hopelijk komt daar verandering in tijdens de WWDC van dit jaar.

Dit betekent dat we nu weliswaar eenvoudig modules en bestandshiërarchieën op de iPad kunnen maken, maar dat we, zodra we onze code weer naar de Mac willen verplaatsen (wat we, als we een app bouwen, op een gegeven moment wel moeten doen), die code moeten reorganiseren in iets dat compatibel is met Xcode – bijvoorbeeld door bestanden aan Xcode-projecten toe te voegen en frameworks voor onze modules te maken.

Hopelijkerwijs zullen toekomstige versies van zowel Swift Playgrounds als Xcode een meer genormaliseerd projectformaat brengen (hoe geweldig zou het niet zijn als alle ontwikkelaarstools van Apple de Swift Package Manager en zijn Package.swift manifest zouden gebruiken om projecten te definiëren?), wat het veel makkelijker zou maken om hele projecten van en naar de iPad over te zetten – wat mogelijk nog meer geavanceerde gebruiksmogelijkheden biedt, en ons in staat stelt om onderweg hele apps te bewerken.

Testbaarheid mogelijk maken

Een ander aspect van Swift-ontwikkeling dat in Swift Playgrounds op de iPad ontbreekt, is ondersteuning voor unit- en UI-tests. Niet alleen biedt de app geen enkele ingebouwde manier om tests uit te voeren, hij wordt zelfs niet geleverd met het XCTest framework waarop de meeste Swift-ontwikkelaars vertrouwen als het gaat om enige vorm van geautomatiseerd testen.

Betekent dit dat het schrijven van tests op de iPad helemaal niet meer mogelijk is? Gelukkig niet. Ondanks al zijn beperkingen bevat Swift Playgrounds nog steeds de complete Swift-compiler, en aangezien XCTest – uiteindelijk – niets anders dan code is, kunnen we vrij eenvoudig enkele van de kernaspecten ervan opnieuw implementeren in Swift Playgrounds zelf!

(Het zou geen Swift by Sundell artikel zijn zonder wat code voorbeelden, toch? 😉)

Laten we beginnen met het definiëren van een “afgeslankte” versie van de XCTestCase klasse, maar dan als een protocol. We willen dat alle testgevallen een lege initializer hebben (zodat we dynamisch instanties kunnen aanmaken), methoden voor het opzetten en afbreken van elke testrun, evenals een op de Swift Package Manager geïnspireerde allTests eigenschap om onze testrunner toegang te geven tot elke testmethode die we willen uitvoeren:

protocol XCTestCase { init() func setUp() func tearDown() static var allTests: { get }}

Hoewel we XCTestCase als een concrete klasse hadden kunnen implementeren, en gebruik maken van de Objective-C runtime om test methodes te identificeren – net zoals XCTest dat zelf doet op Apple platforms – dat zou vereisen dat we elke methode markeren met @objc, en zou ook onze code minder portable maken in het geval we het willen implementeren op platforms zoals Linux.

Volgende, laten we ons XCTestCase protocol uitbreiden met een methode die ons een gegeven testgeval laat uitvoeren (door al zijn methoden op te sommen en elk aan te roepen), evenals lege standaard implementaties van setUp en tearDown:

Met het bovenstaande op zijn plaats, zijn we nu in staat om testgevallen te definiëren, maar we hebben ook een manier nodig om verificaties en beweringen uit te voeren terwijl we onze eigenlijke test logica schrijven. Om dat te vergemakkelijken, beginnen we met het implementeren van de XCTFail functie, die ons een test laat falen als niet aan een bepaalde voorwaarde wordt voldaan. We geven het een optioneel reason argument, en we noteren automatisch de naam van de test functie waarin het is aangeroepen, evenals het regelnummer – zoals dit:

Met het bovenstaande kunnen we nu de XCTAssertEqual functie implementeren, waarmee we kunnen bevestigen dat het resultaat van een bewerking gelijk bleek te zijn aan het resultaat dat we verwachtten:

Dat is echt alles wat we nodig hebben om te beginnen met het schrijven van een aantal basistesten. Bijvoorbeeld, hier is hoe we nu zouden kunnen verifiëren dat een Playlist type correct zijn nummers bijhoudt, en er ook voor zorgen dat zijn serialisatie code werkt zoals verwacht:

Om onze bovenstaande tests uit te voeren, roepen we eenvoudig run() aan op het type van de test case:

try PlaylistTests.run()

Het is misschien geen complete her-implementatie van XCTest, en we zouden elke assertiefunctie en testfunctie die we nodig hebben handmatig moeten blijven toevoegen – maar het laat zien dat veel verschillende geavanceerde ontwikkelingsfuncties technisch mogelijk zijn op de iPad – we hebben soms alleen een beetje tijd en creativiteit nodig om ze te realiseren.

Steun Swift by Sundell door deze sponsor te bezoeken:

Instabug: Los bugs, crashes en andere problemen veel sneller op met behulp van de gedetailleerde stack traces, netwerklogs en UI-gebeurtenissen die Instabug automatisch aan elk bugrapport koppelt. Gebruikt door zowel mijzelf als duizenden iOS ontwikkelteams over de hele wereld. Probeer het gratis uit en integreer het met slechts één regel code.

Conclusie

De 3.0-versie van Swift Playgrounds voor iPad is een fantastische update van een toch al heerlijke app – die krachtige nieuwe mogelijkheden toevoegt en kernontwikkelingsfuncties, zoals foutrapportage, veel krachtiger maakt – en dat alles met behoud van de focus op gebruiksgemak en educatieve inhoud.

Swift 5, modules, bewerken met tabbladen en beheer van bronbestanden zijn allemaal geweldige functies die deze versie van Swift Playgrounds de meest capabele tot nu toe maakt – en het is een grote stap in de richting van het mogelijk maken van veel meer Swift-ontwikkelingstaken op de iPad. Net als bij het werken op de iPad in het algemeen, vereist het gebruik van Swift Playgrounds soms een beetje extra geduld en workarounds, maar het resultaat kan vaak zorgen voor een krachtige ontwikkelomgeving op een zeer draagbaar apparaat.

Swift Playgrounds is nog steeds geen “Xcode killer”, en het zal dat waarschijnlijk ook nooit worden, maar dat is OK. Hoewel betere interoperabiliteit met Xcode (vooral in termen van bestandsindelingen en projectstructuur) en meer geavanceerde editorfuncties (zoals tools voor refactoring en tekstvervanging) zeker meer dan welkom zouden zijn, zolang ik onderweg snel Swift-code kan schrijven, ben ik meer dan tevreden – in ieder geval terwijl ik wacht op de komst van “Xcode voor iPad”.