As usual I was a bit overly ambitious yesterday and ran out of time. So I have a few more sessions I have to watch this morning before things get going. The first of which is:
The SwiftUI cookbook for navigation
Review of new APIs for navigation across of SwiftUI. This will provide simple receipts to get started:
- Quick review of existing APIs
- Based on passing Links around.
- You basically add a binding to a link to persist state as in – NavigationLink( “Details”, isActive: $item.showDetail) { DetailView() }
- In the new API you move the binding up to the top.
- NavigationStack(path: $path) { NavigationLink(“Details), value: value)
- Much simpler than above.
- New navigation APIs
- Basic recipes app is used as an example with a three category app.
- New container types:
- Navigation Stack – this is a push / pop interface:
- NavigationStack(path: $path) { Details() } – this is settings on macOS, Find my on the Watch, etc.
- Navigation Split View:
- NavigationSplitView { Categories() } detail: { Grid() }. // to column example
- Perfect for multi column apps like Mail or Notes and will collapse to Stack in smaller views
- There are two sets of initializers. Above is a two column
- Three column is vain NavigationSplitView { Categories() } content: { List() } detail: { Detail() } // think of the notes app with the folders listed
- There’s a great session in 2021 on this
- Navigation Link shows a Title and the info to present:
- NavigationLink(“Show Detail”) { Details() }
- The new one presents a value, not a view: NavigationLink(“Show information”, value: informationShown)
- That value will change based on the type of item it is presented in
- Navigation Stack – this is a push / pop interface:
- Recipes for navigation
- Basic stack of Views, with sections for each item. And within each item you can get details
- You will need a NavigationStack, NavigationLink, and the modifier .navigationDestination(for: )
- This will push items on the stack so when you go back you will go back up the stack
- Basic stack of Views, with sections for each item. And within each item you can get details
- You can bind the path to the view via a state binding. This recipe works on all platforms.
- Multi-column presentation without stacks:
- Uses NavigationSplitView, NavigationLink, and List ( great on larger devices)
- Now we have fill programmatic control over the view
- This is auto translated to a single stack on WatchOS and TvOS, so this is also available on all platforms
- Adding them together for a complex view navigation: Two column navigation experience (This is what I need for my Card Tracker app).
- Allows for navigation between rated information, using NavigationSplitView, NavigationStack, NavigationLink, .navigationDestination(for:) and List
- Start with a standard two column display but add a navigationStack into the details:
- The root view is the RecipeGrid. If we go to it to show details
- We now have a link for each grid entry., We will need to add a .navigationDestination Modifier – we don’t want it on each link. So we should place it put is next to the scrollView – bellow .navigationTitle
- And finally:
- Persistent state: To do this we need to address Codable and SceneStorage
- This example requires us to move state to the class, make it Codable
- Take special focus on the initializer as defined in the sample code with the session. They are using Json to save and restore the state. This uses @SceneStorage. Adding .task modifier to view, this is run asynchronously beginning when the view appears and ending when the view disappears. I am sure this code will be used to easily extend a lot of views
- It is apparent from this session that Apple is suggesting you switch to these patterns as soon as possible. I believe this is to make your code across more and more platforms without a bunch of compiler directives. There are articles available on how you should migrate.
- You may want to check out this link – https://developer.apple.com/documentation/swiftui/bringing_robust_navigation_structure_to_your_swiftui_app
Dive into App Intents
The last of the sessions I wanted to get to on Day 2, this is another meaty one. As I’ve been playing with App intents in Wasted Time, though I never did get them working the way I wanted, this session is of great interest to me. To quote Apple Fitness+ – “Let’s Go!”
- Introducing AppIntents
- Introduced in IOS10, now there is a new Framework called “AppIntents”.
- By using Intents you app becomes available in Siri, it also makes it show in Spotlight, you can now address Focus Filters, and of course shortcuts (this makes app available across all parts of Apple’s ecosystem).
- Intents and Parameters
- Single unit of functionality – run by request (or automatically)
- Include: Metadata, Parameter and Perform Method
- Need to create an intent for each item action a user could expect. Then you create a struct which concludes a @MainActor and perform() method. Include a title as a static
- And that’s it for a simple intent that takes a user to a specific screen in your app. (I should create an intent that shows a user the metrics screen in Wasted Time)
- If you add a little code you a make your Intent show up in the Shortcuts app. Will want to check out Implement App Shortcuts with App Intents
- Phrases is used by Siri
- Additional example was shown to help you take the user to any screen.
- Entities, Queries, and Results
- Use entity when values are more unbounded. List a list of books vs, the screens in an reading app, you app then enabled queries and returns this entities as a Result
- The entity should be Identifiable, a type Name and a DisplayRepresentation – could be a string of text
- The Query Struct provides an interface to retrieve the entity from your app. Must have ID lookup, can also provide suggested entities and more. It must confirm to EntityQuery protocol.
- Implement the defaultQuery type on an entity pointing to the Query.
- With additional work you can allow for stringing intents together.
- The Open Intent is used to open your app with an intents value passed in.
- Properties, Finding, and Filtering
- Entities expose properties which can be useful by other parts of the system and used in intents and short cuts – for example:
- Here in our Book example from the session, we can export more information about the book. You use @Property wrapper in your entity to export them.
- By combing Properties with Queries now you have the ability to find and filter to be used in Shortcut building blocks.
- You will need to adopt Property Query in your application. You define how you want to allow for the query to perform.
- You use these to define NSPredicates to be used in query and similar in sorting
- Implementing matching then allows the system to string the predicates together to provide the resultant list
- User Interactions
- You can enable Dialog (for Siri) and Snippets (for visual feedback), Request Value, Disambiguation, and Confirmation to help clarity
- You can think of Snippets as visual version of Dialog
- Since this is done as a closure, it is more and more important to keep your views small and self contained.
- Architecture and Lifecycle
- There are two ways to build the intents – in the App or via a operate extension
- Simpler to do it directly in your App
- If you enable openAppWhenRun it will be able to run in the foreground
- An extension is lighter weight, and if you use focus intents, it will run immediately
- With App Intents your code is the source of truth. Xcode will create the Metadata file needed for your intentions
- To upgrade from SiriKit apps you can click Convert to App Intent in the definitions file.
And now we get to the content I was planning to get to for today:
What’s New in Privacy
- Privacy is a fundamental human right. I still appreciate this statement from Apple and it is one of the reasons I use their products and spend my free time developing for their platforms.
- There are four patterns (or pillars) that Apple uses for their approach:
- Data minimization – only use the data needed to build the feature
- On-device processing – use the device to address any sensitive data
- Transparency and Control – If data is sent off device, let users know and control what it is, how it Is used, and control it’s access
- Security Protections – keep data safe at rest and in flight
- Platform Updates
- Device name entitlement – which restricts access to device name. Location shows app attributes in control center, gatekeeper has improved to verify integrity of the app in more places. Launching Mac apps at login notifies people of additions and Pasteboard now requires permission.
- The “user’s name” is provided in device name. So now the name will return the “iPhone” if you do not request entitlement.
- Location use will now also show the app (not just the arrow) in the bar.
- GateKeeper on the Mac, checks integrity of all notarized apps. You should makes sure your signatures stay valid. It will also prevent the app to be modified in the certain ways. You need to include info.plist changes to allow other apps to update your app. This will have implications to Eclipse based apps.
- I like this feature for security purposes, but I can see this being an issue in an enterprise setting
- Will certainly have to ask my day job to look into this one in more detail
- To enable apps to run at start in –
- Single API to launch app, launch agent or daemon
- SMAppService API is used for this. All items should be inside your bundle and they should be able to run fine.
- Pasteboard Access – now you will get a confirmation message, you should edit options, a keyboard shortcut or UIKit paste controls to stop these.
- New Feature to adopt
- UIKit Paste Controls – if you add this to your app experience, this allows without any edit menu, keyboard short kit, etc. It is validated by App Intent. It must be visible to work
- Media device discovery – Permission used to be required and access to bluetooth, which poses a finger printing risk. Using discovery end up showing up in the same area as AirpLay and the app only sees the sandboxed results being used. The app won’t see the whole network but will get those features it needs from the network. Create an app extension to enable discovery if you are a protocol provider.
- PHPicker – The new photo picker will provide access to the photos without prompt.
- Private access Tokens – this replaces captchas and uses blinded tokens. Reduces ability to track users. This is based on IETF privacy pass standard. (Check out replace Captchas with private access tokens).
- PassKeys – check out the prior session from Day 2.
- Safety Check
- I ran this feature today and hadn’t realized that I had some people with access to my photos library.. let’s just say – I fixed that 🙂
- This can allow for single button changes to help people in domestic or other abusive relationships – stops sharing data with people, apps, signpost of features on other devices, changes password and change trusted phones numbers and manage emergency contacts.
- Emergency Reset is across people and apps immediately. The only issue that I can think of is, if someone is kidnapped they could be forced to run this option and “disappear” from those who may be searching for them.
- Manage Sharing and Access- allows you to review and confirm – this can help you identify if someone has added an app to your device to track you. Quick Exit – takes you back to Home Screen immediately and changes so that going back to Settings to take you back to the root of Settings.
What’s new in HealthKit
I love my Apple Watch and Fitness Plus+ the additions of Medicine and sleep tracking are exciting
- Sleep Analysis
- Apple watch can be used to manage sleep schedule, this year we have Sleep Stages
- Stages are stored in HealthKit, represented by category samples HKCategoryType.sleepAnalysis of REM Core and Deep.
- Create one sample fore each continuous period of time.
- Sleep Core equal to stages 1 and 2 of the AASM model
- Deep is Stage 3
- REM corresponds to Rapid Eye Movement
- “Sleep” state will be deprecated.
- You a read sleep samples for a given stage using Predicate .predicateForSamples( _, value: .asleepREM), you will receive an array of samples in that state.
- Swift Async
- They have updated the queries using async – making queries simpler
- They are all based on HKQuery – for example HKStatisticsCollectionQuery
- You can use the HKStatisticsCollectionQueryDescriptor, as an example to get all the calories burned in a week by using a predicate of caloriesPredicate
- Workouts
- Great for capturing workouts and all day metrics. API is being updated to identify Triathlon and other interval based activities.
- Activities cannot overlap in time, and are not required to be continuous.
- You assign the type of data you want to collect in a work out by starting a new activity .beginNewActivity
- Reading metrics which will allow you to pick the statistic for a specific activity type. This means older methods are being deprecated in favor of this method. There are a new set of Predicates for search and statistics.
- By using workout activities to track intervals you can now get a more comprehensive view of the workout. SWOLF (strokes in a given length and the time it took to swim that length) is being added as a unique metric that will be captured.
- Heart rate recover is also being captured. This Cardio recover data type will be available in the health app. .heartRateRecoveryOneMinute
- Vision Prescriptions including digital copy of physical prescription
- You can now add in vision correction information – 75% of US adults require prescription for vision correction
- Can save both classes and contact information – Start date == prescription date
- You can include a digital copy of the prescription
- (I wonder if Apple will use this data to improve their AR/VR experience going forward)
- Prescription have a new permission authorization – it is unique for each prescription.
What’s new in the CloudKit Console
I’ve been using CloudKit for an app I’ve been working on for the last few years. Looking at what’s new in the console will help me understand how this may impact my desire to release this app. This is used to synchronize data between devices.
- Hidden Containers
- In the console you can now choose which are hidden or available – this is at the team level so you don’t see them in the various tools. Keeping things cleaner for views and workflows.
- Act As iCloud
- In the Console you can now view as iCloud account verses as your Development account.
- So you can sign in as a separate iCloud Account to look at the data from that account.
- I can use that to see how the data may be stored in my app
- You can’t perform schema operations, but you can do queries.
- Great for debugging and see how the data is used in Production.
- Data is still encrypted and only viewable by the original account
- Zone sharing
- This is used to share data securely across users
- I am not using this feature, but it seems like a key thing for games and social activities. There are both Public and Private shared zones to help separate the data
- You can take an existing zone and then decide if it is shared. I don’t believe it moves over the data from that zone. But people who join later will have access to shared data.
What’s New in Swift-DocC
Since I am focusing on APIs in my day job an dhow to make our APIs more discoverable and consumable, I am really interested in what is going on with DocC. This and the next session will provide me insights on what we may need to do. The only issue is, my day job team is focused on Java based development, so the patterns are important to me, but the specific implementation details may not apply.
- Allows you to use Reference, articles and tutorials adding in additional workflows for frameworks and app projects, can also do Objective-C and C APIs
- Supports Hosting providers like Github Pages
- Have moved to Open Source for the project.
Focus is on:
- Document
- You document right in the code – with no documentation created.. the Build Documentation will create stubs automatically.
- API
- Add three slashes for documentation – ///
- Link syntax is “LINK“
- Start by teaching how each API works individually and then build up to higher level content
- Use mark down code syntax to provide code example.
- Initializers you should describe each parameters
- There’s a language toggle to help people see examples in appropriate syntax
- Top level page you can add a new file of type documentation catalog, this allows you to build out summary and overview
- You can add images, etc.
- And links to each page for the APIs
- Publish
- Builds a static bundle called a DocC archive, it can be shared by Export.
- It also includes a standard website out of the box and compatible with most WebServers.
- You can auto Publish to GitHub Pages via a Base Path to make it compatible for certain hosting items – like your own domain
- I tried this for Wasted Time and am currently getting a build error for the Build Documentation command
- To create the Base Path – you need to add in the build settings.
- The workflow is very simple for those using Git and you can make it automated via the Swift-DocC Plugin
- Browse
- The new browser and navigation function makes it much easier to explore the API and Documentation
- It calls out Methods, Protocols, Events, Properties, and Structs.
- It also supports searching via the Filter bar
- Examples and more details are available at:
Improve the discoverability of your Swift-DocC content
The second session on DocC is about the design of your documentation
- Web navigation
- This has both a navigator / filer bard
- Disclosures all you to show relationship of objects, properties, etc.
- Filter bar includes type tags to reduce the amount of things that are included
- Content view
- This has both a navigator / filer bard
- Optimize your content
- There is automatic organization which means your documentation is organized by type
- But you an override this default view by
- Define the high-level themes (limit to a few key things here, sort them by importance or adoption)
- Essentials – getting started, etc.
- Great to add code examples and introductory articles, etc.
- What can be done with your framework
- How can you get data or visualize your framework’s data
- What management tasks are available
- Essentials – getting started, etc.
- Organize by importance and specificity
- Use this to guide thru the content
- Optimize titles to make it helpful for developers
- Update titles so it is clear and descriptive –
- Should make sense on it’s own
- They should be mutually exclusive
- Define the high-level themes (limit to a few key things here, sort them by importance or adoption)
- By improving your Documentation and making it easy to understand you can help Serendipity for developers
What’s new in iPad Design
There are a lot of changes to expand the iPad to a more desktop like experience, especially with external displays. These new design patterns will improve the overall experience with your app.
- Toolbars
- They organize your apps functionality
- If we compare pages between iPadOS15 and 16 notice the difference at the top. The iPadOS16 view provide a lot more functionality and discoverability of functions:
- The most common. Workflows in your app should be tagged in the center options. If you have too many, you end up with an overflow identifier. You can add Customization if you have a lot of items.
- You can group or collapse toolbar options. When there’s not enough room, they will collapse to a + button
- Important item that must always show should be in the trailing edge.
- Document Menus –
- Documents should use this new menu, and you will get back a < to go to a browser view.
- Standard item like Print, or Duplicate can show in this menu.
- Editing menus
- These are now optimized for touch, pointer and other modalities. So you get horizontal for touch and vertical popup for Pointer
- You should leave the default values and group your custom objects
- Find and replace
- You now have a system Keyboard option for find and replace.
- When attached to a hardware keyboard it shows up a the bottom of the screen
- Navigation
- Content browsing experiences are everywhere.
- New style – browser style navigation (using back and forward buttons)
- It’s up to your app to decide what those buttons should navigate to.
- Note you don’t need this mode if your app is fairly flat in content.
- If you use this, then you can enable search in the top right of the browser window. Great for filtering the details. It supports suggestions, filters and other features..
- If you want to search across all of your app, you should have search in a Search Tab (like the left hand navigator list)
- Selection and Menus
- iPadOS15 had Drag select (aka Band Selection)
- In iPadOS16 you can now use keyboard modifier to select and deselect. It also doesn’t go into editing mode.
- You can now long press or click again to get a menu pop-up to execute commands against the selection
- You can also use context menus in empty area.
- Your app should support
- Keyboard Focus
- Band Selection
- Multi-Select without modes
- Menus for multiple selection
- Empty Area Menus
- Submenus – on iPhone you should only use them when you really need one. (They are vertical)
- On iPadOS they go horizontally, they are quick
- You also now have a new control for popup buttons in list, which show a menu to choose an option.
- This will keep you in context and reduces the number of steps
- Use for well defined list of things
- Tables
- New component in iPadOS16. – different than the old Table control
- Think of this like a spreadsheet. It supports sort by taping a header. Swapping columns (to show only the most important). They support multi-selection features.
- Think of them as an extended list view. Tables switch back to a single column list if size is limited. If that is done, you should take the additional columns and add them as subtitles. Sorts should then be moved to a ToolBarItem
Building a Desktop-class iPad App
Given that my Card Tracking app is really a task specific database tool, I think understanding how to make the Desktop and iPad versions as equal as possible is key. The new features of iPadOS16 will make this more possible. So this session should provide me with guidance on how to improve many of my features.
- This is a deep dive session to update an existing App and will focus on three high-level changes.
- UI organization:
- Start by changing from standard Navigation View and move many options up to the NavigationView type.. using Browser or Editor options. I would need to switch to Editor mode for my Card Tracker
- Will want to customize the built in Back action to match our needs
- Update the Title Menu with document info
- Enable Document Renaming
- And expose features into the Bar.
- Start by changing navigationItem.style = .editor
- Change out the old Done button with navigationItem.backAction = UIAction(…)
- If appropriate we could do title information, like document properties.
- You can now enable new features based on the UIDocumentProperties and you then able things like drag and share based on the document. If you go thru the prior session on Desktop Class iPad apps – you will learn about the system menu items and adding your custom items to the document menu.
- For system functions you will need to override the system functions for any app specific activities, like actually renaming the file. On Mac Catalyst you will need to manually expose the Title options to the menu builder.
- Quick actions
- Adding actions:
- Fixed groups are not customizable or able to be moved by users, so they are present on the leading edge of the view.
- Handling different sizes between iPad you want to be able o define multiple actions, and preferredElementSize property means you can address the menu size and .keepsMenuPresented attribute allows multiple selection without dismissing the menu
- Theres a ton of stuff here.. highly recommend multiple views and analysis of the posted code.
- Text experience
- Prior to iOS16 you’d have to have develop your own bulk actions edit mode with new menu items.
- You can now enable this design with a light weight selection style, by enabling multiple properties, .allowsMultipleSelection = true, we enable Keyboard focus via .allowsFocus = true and then enable keyboard to drive the selection by .selectionFollowsFocus = true
- If you do these changes you want to make sure to adjust via performPrimaryActionForItemAt indexPath on the collectionView.
- You then enable collectionView(_:contextMenuConfigurationForItemsAt:point:) https://developer.apple.com/documentation/uikit/uicollectionviewdelegate/4002186-collectionview If the array is empty then you are in an empty space and invoke the Add or similar function, otherwise check for single item or you should loop thru the multiple selections. On an iPad you use a two-finger click get the menu
- Find and replace is enable via setting a property.
- You can define your own custom items for selected text. Check out adopt desktop class editing interactions for much more.
Meet Transferable
Support drag and drop, cut and paste and also other interactions across your app. Check out the app for this one.. great to see catalog of female inventors and scientists. The sharing interface is also available via this (ShareLink).
- This is a declarative way, built on Swift First:
- Anatomy of Transferable
- To transfer data between two applications there is always binary data that goes across. You need to understand what it corresponds to. All items need to provide ways to convert too and from binary type, and the Content type. This is an apple specific technology (content type – (uniform type identifiers – UTI).
- To create your own UTI –
- Add declaration your info plist file
- add a file extension and add it to your info.plist
- Declare it in code – check out UTI – A Reduction video
- Many standard types already conform to transferable. You will use ShareLink and new PasteItem API
- Conforming custom types
- You need to implement add :Transferable to your object and then define the transferRepresentation as in static var transferRepresentation: some TransferRepresentation { … }
- Three key items CodableRepresentation, DataRepresentation and FileRepresentation
- CodableRepresentation uses an encoder and decoder and by default it uses JSON – to learn more – watch WWDC18 session on Data you can trust. Use this for simple items.
- DataRepresentation allows conversion via only two modes – this is for in memory binary information.
- FileRepresentation should be used for very large items, like video and audio files.
- Advanced Tips and Trips
- Order of TransferRepresentation is important. They system will use the first one that matches.
- ProxyRepresentation – should read up more on this one.
- You will get very different behavior between FileRepresentation v.s. ProxyRepresentation one is the data itself vs. the link to the data.
- Key links:
- WWDC18 – Data You Can Trust
- Tech Talk – Uniform Type Identifiers — a reintroduction
Optimize your use of Core data and CloudKit
A few key links to start with:
- https://developer.apple.com/documentation/coredata
- Synchronizing a local store to the cloud
- WWDC21 – Build apps that share data through CloudKit and Core Data
- WWDC22 – Evolve your Core Data schema
- You should also go back to WWDC19 to get the sample app and review it.
AS mentioned earlier in my posts, I have been working on an app that tracks Greeting Cards. It uses Core Data and CloudKit to synchronize across devices. I am currently seeing long delays in that synchronization and hope I can gain some insights here. I like that he calls this the Water Cycle, – I think of this as agile at one level, and waterfall at another.
- Exploration (Via a data generator)
- Goal is to learn, challenge and verify all assumptions, will the store sync when I expect it, how does the system behave with very large data
- Will focus on how the shape, structure and variance of the data.
- Using Algorithmic data generators allow you to test, you should be able to store and analyze this data. Building these to create larger and complex datasets are great practice
- You can then build tests to validate
- You should also create a test to test syncing this data since we are taking about CloudKit
- Binding generator to a user interface you can now see how the data is behaving from user perspective.
- Analysis
- Focus on Instruments on time and allocations
- You can use profile and it will create tests to analyze the steps that are running. This will help you understand where time is spent on the application
- Using Allocations in Instruments you can see if you are either leaking memory or keeping data around after use for too long. Use this to uncover if you have retain errors.
- Logs for information from CloudKi and Applications and push notifications.
- Looking at this you can see= what system services are being used
- Dasd is the process you want to look at in the logs for Mac based scheduled logs
- It will show any policies that affect how the process runs
- Cloudd and apsd processes should also be reviewed.
- In terminal you can use log stream —predicate ‘ process = “” AND (sender = “CoreData” or Sender = “CloudKit”) to get a window of with real time log streams
- Focus on Instruments on time and allocations
- Feedback
- Collecting diagnostic information from devices allows for actionable and specific
- Need to install CloudKit Profile on the device
- This is from the developer portal and it will try and install on the device.
- Reboot the device to take effect
- Reproduce the behavior and then create a sysdiagnose
- Collect a Sysdiagnose
- On current iPhone press both volume buttons and a the Power button for a few seconds.
- You will see a sysdiagnose in logs and you can press share to send via airdrop or other method.
- With sysdiagnose you use log show —info —debug —predicate ‘process = “dasd” AND message contains[cd] “appidentifier”’ system_logs.logarchive to get the data in terminal
- See more details in the video transcript.
- If you have access to the device you can collect the Store Files via Xcode
Compose custom layouts in SwiftUI
This should be another really meaty session, as Custom views are a key feature with this release. A sample project and detailed documentation can be found at https://developer.apple.com/documentation/swiftui/composing_custom_layouts_with_swiftui
Combining built in views to more complex views. Modifiers provide conditional controls:
- Grid (Static 2 dimensional views – you use lazy grids for scrollable views.)
- Swift UI will figure out size (columns and rows) automatically.
- You should always create sample data in your structs so you can use it in Previews
- You use the .gridColumnAlignment modifier to adjust a single column in a grid
- You can add the .gridCellColumn to span multiple columns
- Layout (create a custom one)
- To adjust button widths to equal the widest button stack you can create a custom Layout. So you can now change from HStack to a custom stack. In this case you make a type that confirms to Layout.
- A sample of a customer stack is here
- Note the inout Void cache to share values across instances (more info in the documentation)
- All views have spacing preferences that indicate the ideal spacing between itself and items on any sides (and each side could different ) it can vary by type and by platform. If edge presences don’t match the system will use the larger by default.
- To see the details the commented areas above – watch the session, as they are details that you need to understand.
- I really like this feature. Since I had tried to use Geometry Reader to solve the problem. It’s intended use is one directional.
- ViewThatFits (auto selects the view that fits)
- You can use this to pick the item that fits, in the available space.
- Read the documentation on this one.
- AnyLayout – AnyLayout
- Lets you provide different layouts based on some condition. It will transition to that view when the value changes. So you get a viewDidChange instead of a new View.
- This allows for smooth animation and reduced impact to your users
Build a productive app for Apple Watch
I have had an Apple Watch app on the store since 2019. So this session is always interesting to me. Let’s see what nuggets I can glean to improve my app. Check out the details at https://developer.apple.com/documentation/watchOSApps
- Each year more capabilities are added to WatchOS. So this session will allow you to add them toters
- Create A watch App
- You should decide if you need to make a companion app on the phone.
- Great apps focus on essential focus of the app.
- The dual targets are a hold over from earlier days. New model you only need one.
- You can convert your app using the validate setting to transfer the App to the new Swift UI Lifecycle. Absolutely need to do this for my app.
- You can now use a single 1024×1024 app icon image.
- If you have details that get lost you can create specific items
- Add a simple list
- Create a data model
- Enable list updates
- Preview should show an empty list.. so now you want to add a button to add a new item
- TextFieldLink can be used to allow for text input
- Placement of items you should use at the end of list for primary action on a short list
- On a long list, you may want to add it as a ToolbarItem – this will show at the top of the list when the user pulls it down.
- App navigation structure
- On Watch you can do Hierarchical so use NavigationStack
- Page-based you use TabView – this is where all items are peers – my app uses this
- A full screen app, uses the full screen with a single view. You want to ignoresSafeArea modifier and toolbar modifier to hide the navigation view
- A modal Sheet should be an important task that covers the enter view. Deciding between this and NavigationStack should be considered based on the details.
- Use a property to control the display of the modal sheet.
- In WatchOS9 9 you can use Steppers for sequential values. (They don’t have to be numbers, just logically sequential). A stepper is huge for my app. I may have to switch to it.
- Share with a friend
- ShareLink is also supported on WatchOS 9. This will allow you to easily share items via standard sharing methods.
- Check out the Transferable session earlier today.
- Add a chart
- You can use the new Chart feature in Swift. – SwiftCharts and they can be reused across all platforms.
- Definitely check out Hello Swift Charts
- Scroll with the Digital Crown
- There is a new Digital Crown rotation modifier which allows a call back.
- You use @State variables to track the .digitalCrownRotation modifier so that you can react to it.
- It uses detent in the context it is the resting notch of the crown.
- You can apply the modifier on a chart in order to display a RuleMark()
Embrace Swift Generics
I’ve been taking a class lately – #100DaysOfSwift by Paul Hudson over at https://hackingwithswift.com … I’ve been using swift for many years, but it has all been by discovery only, so this class is really helping me fill in some gaps. One topic that comes up on the site is Generics. Having a good understanding of Generics is key. I am looking forward to this session.
- Generics are a fundamental tool for writing abstract code in swift.
- In swift you can abstract away complex Types. This is a Generic in swift.
- Model with concrete types
- You could overload methods to address things. If you do this a lot with very repetitive nature.. you should think about Generics
- Identify common capabilities
- Looking at the types you created you should see where things are common. And how they behave differently based on different types.. this is Polymorphism – allowing one piece of code to have different behavior based on how it is used.
- You can use Overloading
- Subtype Polymorphism –
- This could be done via class hierarchy with type specific overrides by sub class.
- You be forced into reference semantics
- Also requires methods to be overridden, forgetting to do so, won’t be caught until runtime.
- The more things you try to fix, the more boiler plate you will have to add.
- Parametric Polymorphism – achieved via Generics
- Build an interface
- You can build an interface to represent capabilities
- This is a protocol, allowing you to separate the idea of what it does from implementation details
- You add an assoScreen Shot 2022-06-08 at 21.04.38 (2)ciatedType to a protocol
- You then use a method to deal with the operation that the protocol needs. Concrete types have to implement that function.
- You can annotate at the protocol type or as an extension
- You have to implement the methods.
- Write Generic Code
- We can now write generic code via parametric polymorphism
- The type parameter can be named what ever you want, and use it across the signature. We then annotate the type parameter with the protocol it conforms to
- There is a simpler declaration of func functionName(_ name: some PROTOCOL)
- Some means there is a specific type you are working with and is followed by a protocol for conformance.
- This is used by “some View”
- Stepping back to understand concept of a specific abstract type.
- The abstract type is called an opaque type
- The specific type is the Underlying type
- For values with opaque type, the underlying type is fixed for the scope of the type.
- You can use opaque types for both input and output both as Parameters or Results
- Named Type parameters are always on the input side
- The underlying type always comes from the same place as the value. So local values must always have an initial value.
- It must be fixed for the scope of the variable
- It is key to understand some and any – and how they behave differently
Recommend reading the transcript many times for deeper understanding
Wrap up for the day
Wow.. what a day, there is so much for my brain to digest tonight. The one thing I need to do next year, is come with a better plan for the specific things I am looking for. Of course, announcing new major frameworks, breaks this planning. This year I was hoping for SwiftData, which did not appear, so, I should have multiple plans. The great thing about today is I discovered multiple techniques and frameworks to rewrite major portions of my apps. Hopefully making them simpler and easier to maintain.