WWDC 2022 – Day Five – Smooth Landing

Wow, this week has flown by and I’ve learned a lot, but I still have tons more to learn.  While I have less sessions planned today, I am sure I can find other sessions I will watch.  So let’s get started.

Creating accessible Single App Mode Experiences

Single mode apps, lock the system to a single app.  This is great for a kiosk, but you should make sure that accessibility is available.  Other scenarios, medical offices, testing, and you can actually enable it via guided access.

Links:

  • Guided access
    • Turn it on in accessibility settings.  Triple tap the side button and you can set restrictions and enable the restrictions you want in place.
    • I’ve never actually known about this setting, so I find it a great way to help setup a device for just email as an example.  Will have to test if you can launch a browser from an email when in this mode.
    • As a developer you can create your own custom experiences in your app.
    • For cognitive disability:
      • Be forgiving of errors,
      • Warn users before irreversible actions
      • Reduce dependence on timing
      • Always confirm payments
      • These will promote independence for people with cognitive issues
  • Code example 
  • Enable the UIGuidedAccessRestrictionDelegate for your app to enable this feature.
  • You must provide an array of restrictions which can be addressed by Guided Access
  • You also should provide a simple user facing title and additional details information 
  • Then implement the guidedAccessRestriction(withIdentifier: didChange:) method to get a notification when a restriction is toggled.  You can then post a Notification in your app to turn off user 
  • This feature was enabled in iOS 12.2 and you can check the status of customer restrictions by calling guidedAccessRestrictionState(forIdentifier:) at anytime.
  • Single App Modes
    • You can programmatically enable this mode on device programmatically, and they all benefit from the above features.
    • For Single App mode – this is for when you want the device to run always.  Will go back to the state on a reboot, but you need to make sure the devices is supervised – Use the Apple Configurator to setup the device in this mode.  You can only exit via the configurator
    • Autonomous Single App Mode – for when the app goes in and out of the mode.
  • Use a single API method to do it. – UIAccessibility.requestGuidedAccessSession(enabled: true)
  • Must be device supervised.
  • You can check for this mode on any iOS 6.0 device or higher.
  • Assessment Mode – this is for testing type applications.
    • This has been unified for iOS and MacOS
    • Doesn’t need to be supervised, but you have to get Entitlement
  • Accessibility API designed for Single App Mode
    • You may need to address additional items for people who are using assistive technologies.  In the configurator you enable a handful always available.  You can also add items in the Accessibility Shortcut menu.
      • But they need to be configured before single app mode
    • You can enable some of these via APIs
      • Use UIAccessibility.configureForGuidedAccess(features: enabled:) API for .zoom, .voiceOver, .invertColors, .assistiveTouch, and .grayscaleDisplay

Explore Apple Business Essentials

I wanted to learn more about how Apple is targeting SMB (small and medium businesses) customers for their services.  I also wonder if they enable APIs to let you add value added services on top of business essentials. 

Links:

  • This is a subscription based service with Cloud Storage, Devices Management, and other services for SMB
  • Signing in with a managed Apple ID the device is automatically setup and configured, along with all the software that is required will be installed.
  • Apple Business Manager
    • This is required to setup.  
    • You can add individuals or sync in from MS Active Directory or Google Workplace
    • You can setup Groups
  • Subscription
    • Then you can enroll either an employee plan or a device plan (for loaners, kiosks, etc.). Each employee can have up to three devices.  A fully loaded account appears to be about $25 per employee.
  • Settings and Apps
    • There is a security tab to bring together all the defaults for their devices. You can pre-configure wifi settings and many more so that the devices will be addressed automatically for a user and they won’t have to setup Wifi.
    • Managed Apps are auto updated and uninstalled if the user signs out of the device.
    • You provide a managed ID here for the users.
  • Employee experience
    • By signing in via their managed ID the device is already setup.
    • On a personal devices you go to setting and VPN which allows you to sign in with a separate work account. They will be crypto graphically separated on the device.  The essentials app will be on the machine which will provide access to services, like device repair, apps, etc.

There were no APIs discussed in this session, but it certainly makes sense for a small firm.  At one level, I would do this for my family as a means to manage their devices, but on another, I think the family sharing I have setup is good enough.

What’s new in Screen Time API

I use Screen TIme myself to help balance how much time I sit working on my machines.  Setting this up has been one way that I’ve improved my balance between computers and physical activity.  I have not looked at the APIs yet, to see if it makes sense to add any to my Apps.

Links:

This API was introduced last year, to help apps manage time for users and kids.  There were a set of Apps called out on this screen.

To be honest, I don’t recognize any of them. I may have to look them up to see what they do.

  • Highlights from 15
    • Family controls
      • Gate way to Screen Time API
      • Prevents removal
      • Provides privacy tokens 
    • Managed settings
      • Allows your app to brand a similar feature to screen time
    • Device Activity 
      • Tracked activities and identified if you exceed a threshold.
  • New Items
    • Sample app – Workload
    • In Family Controls in iOS16
      • Can authorize independent users from their own device
      • This allows for non-parental control use cases
      • You do a simple request on app launch
  • Once successfully authenticated it won’t prompt again.
  • Managed Settings:
    • Revamped to make it easier to use.  Especially in the data store.
    • In iOS15 you could only have one per process. Now   you can create up to 15 stores per process and they are shared between the app and all of it’s extensions
  • The most restrictive settings always win.
  • Device activity 
    • Has new reporting services to create custom usage reports via SwiftUI
    • Will address privacy too
  • The above code is a sample of a report, using the new Swift Charts API

What’s new in PDFKit

I’ve never looked at PDFKit; however, I am thinking about adding printing features to my card tracking application.  My assumption for this session is that I will be able to create a PDF for the reports I am thinking about.  By creating PDFs, it should become easier to create the reports, as well as to share them.

Links:

  • PDFKit Review
    • Full featured framework for viewing, editing, and writing PDF files,  available on iOS, macOS and Catalyst
    • Four core classes 
      • PDFView (included in your layout)
      • PDFDocument (the file or root of the object graph)
      • PDFPage (one ore more are contained in the Document
      • PDFAnnotations (Optional leaves to a Page – this are editable)
      • Check out Introducing PDFKit
  • Live text and Forms
    • In PDFs this is different than in the photos, in PDF if you see text – it is expected Text.
    • This allows Text selection and search
    • OCR Scanning has on demand on and is done in the document itself
    • Forms are automatically recognized and you can tab thru them as you would expect
  • Create PDFs from images
    • This creates Pages from images. This is a new API
    • public convenience init(image: CGImage, andOptions options: [PDFPageInitWithImageOption : ANY] = [:] )
    • This is auto compressed by default
    • Options include – 
      • mediaBox (like Letter or A4)
      • rotation (Portrait or landscape
      • upscaleIfSmaller – by default if the image is larger than the media box, it will scale down to fit, 
  • Overlay Views
    • To draw on a page with Pencil get
    • You can now use Overlay view on each PDF page
      • Install your overlay view 
        • Since you can have 1000s of pages in a PDF –  PDFKit will intelligently load via a new protocol
        • You must create overlayViewFor page:, the others are optional
        • A detailed walk thru of an implantation of this codes is included in the video
  • Save your content in the PDF
    • Use the PDF Annotations a the model – 
      • The Appearance Stream can recorded and will work across other readers
      • PDF annotations are stored in a dictionary – so you can put your own custom data in private objects
    • Override content for saving.
    • Images and PDFs are saved by default with maximum resolution. 
  • Best practices when saving
    • You can over ride this by .saveAllImagesAsJPEG and/or .optimizationImagesForScreen
    • .createLinearizedPDF – is optimized for internet based reading.. loading the first page first.  By default PDFs have always loaded from the last page
  • This is another session that I recommend going thru the video multiple times to get all the code examples.  Or you can get the transcript: https://developer.apple.com/videos/play/wwdc2022/10089/

Use Xcode for server-side development

While Swift has already been made available on platforms like IBM System-Z and Linux, most people still think of it as a client side application language.  While viewing this session I looked up if Swift supported WebSphere and was disappointed to see this article from 2020 – IBM Stops working on Swift – https://www.infoq.com/news/2020/01/ibm-stop-work-swift-server/. While I was disappointed to see this, I figured I could still learn how the technology works.  This session will show how to do server-side code in Xcode.  I have used multiple IDEs over my years and find that even with it’s nuances, Xcode is my favorite IDE. 

Links:

Extending an iOS application into the cloud, is an example of why you may care about server-side development.  Server components tend to be created using different technologies… but if you can use Swift, it would simplify this a lot.  Server apps are modeled as Swift Packages.  Making it a web server, requires you to define the package dependency to appropriate technology. The example talked about using Vapor which is an opens source server.  The sample code was a simple server that echo’s back data sent to it.

By using Xcode you can not only test in a terminal window via CURL, you can also write a simple iOS app to test the interaction via the simulator.  Enabling simple server deploy allows for quick testing via the cloud.  Many of these use cases are very much like what my day job application does via it’s on infrastructure and languages.   The pattern here is traditional server based development.  From a server database perspective, Swift has drivers for FoundationDB, Redis, Cassandra, Postgres, DynamoDB, MongoDB, SQLite and more.  For more information you can look at the above Swift server documentation page.

So allowing for a swift development shop to extend it’s reach to server based apps via Swift, is a great story.  Glad to see this one.

Bring multiple windows to your SwiftUI App

Okay, going to wrap up the day with two more sessions on SwiftUI.  The amount of links that theses sessions are driving shows that they are really bringing together a lot of the ideas presented over the course of the week.  SwiftUI has really made it easier to develop for Apple’s platforms.  As I mentioned elsewhere, I was really hoping that this year Apple would make a SwiftData framework to simplify the usage of things like Core Data and CloudKit.  Unfortunately, they did not do that, there’s always WWDC23.  Well let’s dive into the last two sessions.

Links:

One thing that amazes me about Friday sessions as WWDC is how dense they are.  Each my planned sessions today are only about 15 minutes long, but they pack a ton of great content in them.

  • Scene basics
    • Scenes commonly represent a window on screen. 
      • Window Group (All platforms), for data drive applications 
      • Document Group (iOS and macOS), for document driven applications 
      • Settings defines an interface for in app settings on macOS
    • You can compose them together to extend your apps functionality.
    • Two new additions:
      • Window – a single unique window on all platforms (this is great for things like games)
      • MenuBarExtra – macOS only – control in the menu bar (it is persistent in the menu bar- available as long as the app is running) – has two rendering styes – both a default style, and a chrome-less window attached to the menu bar.
  • Auxiliary scenes
    • You can add an additional scene to your Scene group – this will take it’s title and add it to the Window menu item  on the Mac
  • Scene Navigation
  • There are new callable types via @Environment for example:
    • \.openWindow – can present windows for either a window Group or window
    • \.newDocument – can create a new document window for both FileDocument and referenceFileDocument
    • \.openDocument – can present a document window with contents from disk (using a url)
  • Prefer your model’s identifier rather than the model itself. Value should be Hashable, Codable,
  • You need to create a scene for a data type.  The above code shows the button and the scene definitions.
  • Scene customizations
    • By default you will get a menu item for each group in the file menu.  You can override this with the .commandsRemoved() scene modifier.
    • By default new windows are placed in the center of the screen – you can override with .defaultPosition(.topTrailing) which will be used if now position has been provided before
    • Also .defaultSize(width: , height:) modifier 
    • And .keyboardShortcut(“0”, modifiers: [.option, .commend]) = at the scene level which allows you to create a new scene with this keyboard shortcut 

Efficiency awaits: Background tasks in SwiftUI 

And finally a follow up from last year’s async updates.  This should improve the UI responsiveness of my card tracker app.  While I have loaded a lazy grid for the cards view, it is still pretty slow.  I think I need to put up placeholder images.

  • Stormy: a sample app – that uses background tasks
    • This API is available on watchOS, iOS, tvOS, Mac Catalyst and Widgets.  It is also supported for IOS apps running on Apple Silicon Macs
    • This app prompts users to take pictures at noon if it is stormy outside.  You can see the the system can schedule the refresh for noon, and then run multiple tasks in the background awaiting for results via async/ await before notifying if the user should take the picture. 
  • Background on Background Tasks
    • These happen during the App Refresh period for background processing.  If the app is running out of time, the system will notify it to gracefully handle processing.
    • By setting a network request as a background network request, it can be put back into a wait state and woken back up for more processing when the network responds.
  • SwiftUI API in practice
  • Creating the schedule request, we will call this function and register a New .backgroundTask() scene modifier.  In this case we use .appRefresh(“Name”)
    • Note this code allows for a periodic check and 
  • Swift Concurrency
    • URLSession has adopted concurrency so now you can use try? await on URLSession.  If you want to setup it up as a background session, you should change from URLSession.shared to URLSessionConfiguration.background(withIdentifier: “App specific identifier”), and use that configuration in your URLSession(configuration: config) don’t forget to set sessionSendsLaunchEvents = true for your config object.
    • This is really important on watchOS as all network request must be done as background sessions.
    • Since an background may be expiring, add a onCancel: to your await via awaitTaskCancellationHandler{ } on Cancel: { }
    • The second runs only when the task is cancelled, and in this code it will promote the request from background to background Download.
  • Updating the app to be able to launch in the background with a .urlSession type using the same identifier we created earlier.  This ill only launch when the specific task request it.