<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Francesco on Medium]]></title>
        <description><![CDATA[Stories by Francesco on Medium]]></description>
        <link>https://medium.com/@fraancessco?source=rss-c87a8bf31dbc------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*J3u8XcNopBW-PLOC1onDnQ.png</url>
            <title>Stories by Francesco on Medium</title>
            <link>https://medium.com/@fraancessco?source=rss-c87a8bf31dbc------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 28 Apr 2026 20:40:44 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@fraancessco/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[8 Tidbits from WWDC23]]></title>
            <link>https://medium.com/@fraancessco/8-tidbits-from-wwdc23-fb5110ed4bb7?source=rss-c87a8bf31dbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb5110ed4bb7</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[wwdc]]></category>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Francesco]]></dc:creator>
            <pubDate>Mon, 26 Jun 2023 13:30:31 GMT</pubDate>
            <atom:updated>2023-06-26T18:25:07.871Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7jsLaV3sbwS4tYmYTYU2_Q.jpeg" /><figcaption>iPhone with iOS 17</figcaption></figure><p>visionOS, Swift Macros, SwiftData, Observation and Symbols frameworks: these are just some of the most important news from the Apple WWDC23. But as every year, there’re also a bounce of minor features and improvements: let’s discover 8 tidbits that could be interesting for your daily work.</p><h4>1. Xcode Cloud test notes</h4><p>You’ll be able to include notes for your beta distributed from Xcode Cloud through TestFlight: just create a TestFlight folder in your project’s root and add a WhatToTest.en-US.txt file with the notes.</p><p>Thanks to scripting, you can also automate what to write in the notes: in the <a href="https://developer.apple.com/wwdc23/10224">session</a> and <a href="https://developer.apple.com/documentation/Xcode/including-notes-for-testers-with-a-beta-release-of-your-app">related documentation</a>, it’s explained how to include the last commit message with a post build script. But let’s say you’re defining a workflow where a new build is made for every feature pr opened and your branch naming convention includes the id of the ticket you’re working on: instead of the commit message, with git rev-parse --abbrev-ref HEAD the full branch name will be written in the test notes, so tester can reference to the pr associated ticket easily.</p><h4>2. XCTest screen recording</h4><p>XCTest now supports automatic screen recordings, particulary useful with UITests; it’s one of the many improvements in testing in Xcode 15, including an improved test navigator, test report and a new Test Details view.</p><h4>3. New viewIsAppearing callback</h4><p>This new view controller callback is a really good addition: it’s called once each time a controller’s view appears, between viewWillAppear and viewDidAppear. Unlike viewWillAppear, it’s called when controller’s view has already been added to the view hierarchy, so with updated trait collections and accurate geometry. Unlike viewDidAppear, it’s called way before animations/transitions are completed. Most importantly: it back-deploys to iOS 13 🎉. You can find the full documentation <a href="https://developer.apple.com/documentation/uikit/uiviewcontroller/4195485-viewisappearing">here</a>.</p><h4>4. Palette Menu</h4><p>UIMenu has a new option to display menu items in a row: just use .displayAsPalette as UIMenu.Options in your menu init.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cSyjX2LhfhqUgE_uty6LtQ.png" /></figure><h4>5. UIPageControl progress</h4><p>By setting the new progress property of UIPageControl, the active indicator will show the page progress. UIPageControlTimerProgress has a built-in timer to set the duration and a UIPageControlTimerProgressDelegate to control the page scroll, but there’s also UIPageControlProgress to follow external timers or video playback:</p><pre>let progress = UIPageControlTimerProgress(preferredDuration: 5)<br>progress.delegate = yourDelegate<br>progress.resetsToInitialPageAfterEnd = true<br>pageControl.progress = progress<br>progress.resumeTimer()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*HuIMrwwqKoSyKsxRhFfFlA.gif" /></figure><h4>6. Widgets background handling</h4><p>To better align your widgets UI with new places where it can be added, like iPad Lockscreen, iPhone StandBy mode or Apple Watch Smart Stack, it could be useful to remove its background. The new .containerBackground modifier automatically removes the background you define depending on the kind of the widget is being displayed:</p><pre>struct NewsWidgetEntryView: View {<br>    var entry: Provider.Entry<br>    <br>    var body: some View {<br>        VStack() {<br>            ...<br>        }<br>        .containerBackground(for: .widget) {<br>            Color.yourBackgroundColor<br>        }<br>    }<br>} </pre><h4>7. SwiftUI Haptic feedback</h4><p>Thanks to the new .sensoryFeedback modifier, you can easily add an haptic feedback in response to an event, like a tap on a button:</p><pre>struct ContentView: View {<br>    @State private var saved = false<br><br>    var body: some View {<br>        Button(&quot;Save&quot;) {<br>            saved = true<br>        }<br>        .sensoryFeedback(.success, trigger: saved)<br>    }<br>}</pre><h4>8. New Font TextStyles</h4><p>There’re 2 new UIFont TextStyle: .extraLargeTitle which is 36 points bold; .extraLargeTitle2 which is 28 points bold. In SwiftUI, these new styles seem to be available only for visionOS target (probably a beta bug).</p><h4>Bonus: UIStatusBar default behavior</h4><p>This is great: on iOS 17, status bar using a .default style will continuously adapt to the underneath content and automatically change between light and dark, even by split style between right and left sides. You can see the effect in the UIPageControl progress GIF above.</p><p>And that’s a wrap, hope you enjoyed Dub-Dub as much as I did: there’re so many updates to dive into over the next months. Feel free to connect with me on <a href="https://twitter.com/fraancessco">Twitter</a> and <a href="https://techhub.social/@francesco24">Mastodon</a>; thank you for reading! ☕️</p><ul><li><a href="https://developer.apple.com/documentation/updates/wwdc2023">WWDC23 | Apple Developer Documentation</a></li><li><a href="https://developer.apple.com/news/?id=cj1fjit2">WWDC23 highlights - Discover - Apple Developer</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb5110ed4bb7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[10 Tips on Developing iOS 14 Widgets]]></title>
            <link>https://medium.com/swlh/10-tips-on-developing-ios-14-widgets-f17b865fbdbc?source=rss-c87a8bf31dbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/f17b865fbdbc</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[widget]]></category>
            <dc:creator><![CDATA[Francesco]]></dc:creator>
            <pubDate>Thu, 20 Aug 2020 10:00:37 GMT</pubDate>
            <atom:updated>2023-08-01T10:39:42.065Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kH4aYZS2ZCezt9uO5FOCjA.png" /></figure><p>➡️ <strong>UPDATE</strong>: read <a href="https://medium.com/@fraancessco/8-tidbits-from-wwdc23-fb5110ed4bb7">8 Tidbits from WWDC23</a> ⬅️</p><p>Widgets have been one of the top features of iOS 14 during WWDC 2020, where the biggest change ever of iOS Home Screen has been unveiled. On the user point of view, they represent a new type of interaction, a new entry point for apps; on a technology point of view, they are a <em>manifesto</em> of the way chosen by Apple, where SwiftUI (the only way to build widget’s views) and an optimized universality (widgets are available on iOS, iPadOS and macOS) are key elements. <br>After experimenting with the <a href="https://developer.apple.com/documentation/widgetkit/">WidgetKit framework</a> on iOS 14 and Xcode 12, I want to share 10 interesting tips that could be useful for many use cases when coding widgets for your apps. Disclaimer: I assume you already know how to create a simple widget and basic related APIs. Let’s start! 👨🏼‍💻</p><h4>1. UserDefaults Suite</h4><p>Very likely, you’ll need to use UserDefaults from your widgets, in order to read user preferences or some other small amount of data. To do so, the standard container isn’t the way, because its content isn’t shared between different targets; instead, as for any other app extension, you have to rely (from the app and from widgets) to the shared <em>“suite”,</em> named with the <strong>App Group ID</strong>, using the dedicated api:</p><pre>let userDefaults = UserDefaults(suiteName: “your-app-group-id”)</pre><p>The App Group is a capability available in the “Signin &amp; Capabilities” tab of your targets: remember to add the App Group capability both in the app’s target <em>and in the widget’s target</em>, otherwise it won’t work.</p><h4>2. Location permission</h4><p>As a general rule, widgets inherit every permission status from the parent app and it’s not allowed to prompt requests from the widget itself. Location permission represents an exception: when a widget using location is added to the home screen, the user will be <em>automatically</em> requested to grant permission through an alert; the choice can be changed anytime from the Settings, as a new <em>“While Using the App or Widgets”</em> option is available.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SKOXrbJEaHLXrXwmn1jjSw.png" /></figure><p>To get location services work properly, you have to put the boolean key NSWidgetWantsLocation in the widget extension Info.plist: you can check the status by using CLLocationManager’s authorizedForWidgetUpdates property. In addition, remember that the app must request location authorization from the user anyway, before widget can receive data.</p><h4>3. Maps with MKMapSnapshotter</h4><p>Talking about location, another question could come up: <em>what is the best way to present a map view inside a widget?</em> The recommended option is to use a MKMapSnapshotter in place of a MKMapView; in fact, the standard map view doesn&#39;t work at all. The snapshot captures the map’s contents in a simple image. To get the desired MKMapSnapshotter.Snapshot:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9411682abec0bb506cd02c8d223108a5/href">https://medium.com/media/9411682abec0bb506cd02c8d223108a5/href</a></iframe><p>The closure is perfect to be used in the getTimeline(in:completion:) function of TimelineProvider protocol: once the image is loaded, you can create your entries and define the timeline. The snapshot is highly customizable and you find the full documentation <a href="https://developer.apple.com/documentation/mapkit/mkmapsnapshotter">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dR6eruOJoC12woRjxtBK7Q.png" /></figure><h4>4. Memory limit</h4><p>The map shapshot is a great example of how light should be widget’s content. Videos, animations and so on aren’t available in widgets: moreover, UIKit views wrapped in UIViewRepresentable don’t work in widgets. Related to this topic, you should take into consideration the limit on memory allocation: it’s not explicitly stated in docs, but widgets exceeding <strong>30 Mb</strong> seems to crash, so keep in mind this.</p><h4>5. Updates policy</h4><p>I’m not going through different ways to update your widget and manage the associated timeline (it would request a dedicated article 😁), but another interesting point is: <em>how often can a widget be updated? </em>Apple updated his documentation with details, common behaviors and side cases about this and you can find everything <a href="https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date#Plan-Reloads-Within-a-Budget">here</a>. As general rule: a daily budget includes 40 to 70 refreshes, which means reloads every 15 to 60 minutes depending on many factors.</p><h4>6. ContainerRelativeShape</h4><p>A simple UI trick is relative to views’ shape inside widgets. To be consistent with the widget corner radius (which changes across different devices), Apple suggests to use the SwiftUI ContainerRelativeShape api, instead of defining custom radius: it will automatically make shapes concentric with the widget corner radius. Here’s an example:</p><pre>Image(&quot;map-placeholder&quot;)<br>    .clipShape(ContainerRelativeShape())</pre><h4>7. Link vs widgetUrl</h4><p>Once the user interacts (taps) with a widget, the parent app is launched to handle the request: you can specify an url to be passed to the app, in order to do specific actions. There are 2 ways: by using widgetUrl(_:) modifier to define a unique behavior, as it will be applied to all the widget target, or by using the Link control to define different urls for different targets in the view’s hierarchy. As the small widget allows just one single tap target, it’s preferable to use the widgetUrl modifier for it. Let’s see an example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eeaa9e29eec7200b6f40d4d628a10ec9/href">https://medium.com/media/eeaa9e29eec7200b6f40d4d628a10ec9/href</a></iframe><p>In the case of medium or large widgets, you can use the two options together: each Link’s url is used for taps in its target view and the widgetUrl for taps anywhere else. The url is handled by the application(_:open:options:) method for apps with classic AppDelegate, or by the onOpenUrl(perform:) api for SwiftUI life cycle apps introduced with iOS 14.</p><h4>8. Widgets Bundle</h4><p>Another great feature is the ability to distribute more than a widget for the same app, using the WidgetBundle api:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6c7c148a4697d53517ed187814077415/href">https://medium.com/media/6c7c148a4697d53517ed187814077415/href</a></iframe><p>After some experiments, it seems you can bundle up to 5 different widgets, each with the 3 sizes available, but in <a href="https://developer.apple.com/forums/thread/652897">this thread</a> there’s a way to overcome this limit.</p><h4>9. WidgetPreviewContext</h4><p>While coding your widget, it comes really handy to have a preview of what you’re creating in the canvas area of Xcode Previews. You achieve this by specifying a PreviewProvider; the preview is the widget’s view where the PreviewContext is set as a WidgetPreviewContext:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/df45b568626c52e6d8e142935ccd8c4c/href">https://medium.com/media/df45b568626c52e6d8e142935ccd8c4c/href</a></iframe><p>It’s possible to define more than a single preview, to see widgets in all available family types, as well as modify some environment’s keys: in the example, I previewed a widget in dark mode.</p><h4>10. Placeholders</h4><p>Placeholders are used to show a generic representation of the widget view while it loads the first time is added to the homescreen. Through betas, the way to define a placeholder has been simplified and now you just have to implement the required placeholder(in:) function of TimelineProvider, returning a normal TimelineEntry: the redacted(reason: .placeholder) view modifier will be automatically applied. 2 points about this: as now, images aren’t modified by the redacted effect. The second: you can prevent views from being redacted by using the unredacted() view modifier.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2Q9Cp3N7Z5mc_AEraVyJ5Q.png" /></figure><p>To wrap up, I strongly suggest to check Apple’s resources, including the <em>“Widget code-along”</em> collection and <em>“Design great widgets”</em> session from WWDC20. Feel free to connect with me on <a href="https://twitter.com/fraancessco">Twitter</a> and <a href="https://techhub.social/@francesco24">Mastodon</a>; hope to see lots of widgets ready for the fall, thanks for reading!</p><ul><li><a href="https://developer.apple.com/news/?id=yv6so7ie">Widgets code-along - WWDC20 - Apple Developer</a></li><li><a href="https://developer.apple.com/videos/play/wwdc2020/10103/">Design great widgets - WWDC 2020 - Videos - Apple Developer</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f17b865fbdbc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/10-tips-on-developing-ios-14-widgets-f17b865fbdbc">10 Tips on Developing iOS 14 Widgets</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[10 Code Snippets  from WWDC20]]></title>
            <link>https://medium.com/swlh/10-code-snippets-from-wwdc20-5dba158e2903?source=rss-c87a8bf31dbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/5dba158e2903</guid>
            <category><![CDATA[wwdc]]></category>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Francesco]]></dc:creator>
            <pubDate>Thu, 02 Jul 2020 10:34:01 GMT</pubDate>
            <atom:updated>2023-08-01T10:39:01.753Z</atom:updated>
            <content:encoded><![CDATA[<h3>10 Code Snippets from WWDC20</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Qhnej-TA3xNPpmydRBf7zw.jpeg" /></figure><p>➡️ <strong>UPDATE</strong>: read <a href="https://medium.com/@fraancessco/8-tidbits-from-wwdc23-fb5110ed4bb7">8 Tidbits from WWDC23</a> ⬅️</p><p>The week of online <strong>WWDC 2020</strong> has unveiled big features and exciting announcements; among with important news, there’re many other notable additions coming with new SDKs. Here’s a list of 10 code snippets will be available with the next iOS’s major release: no more than 5 lines of code each. Let’s start 🧑🏼‍💻</p><h4>1. SKOverlay</h4><p>The first api enables us to display an overlay to recommend another app, allowing the user to download it immediately. You can configure the position and set a delegate, in order to respond to events such as appearance, dismissal and errors.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/708724147dfaca1e8b7b0ceafa210a4a/href">https://medium.com/media/708724147dfaca1e8b7b0ceafa210a4a/href</a></iframe><p>It differs from SKStoreProductViewController because it’s tailored for apps and it’s an overlay rather than a full view. Using the dedicated configuration for clips, the SKOverlay.AppClipConfiguration, you’re able to recommend the app clip’s corresponding app, as showed in demos about App Clips.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XzHBTV4HRM2SLH7EQ-kR8w.png" /></figure><h4>2. Configurations</h4><p>Configurations is a brand new api to specify content and appearance of views and cells. It’s very flexible, because it can be applied to any UIView, including collection and table view cells, and very simple to use at the same time. This is an example of using UIListContentConfiguration:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c5946272362b5f7d9ee2ac670112323/href">https://medium.com/media/5c5946272362b5f7d9ee2ac670112323/href</a></iframe><p>List content configuration comes with many default configurations. Configurations covers state, content and background specifications; in addition, it’s replacing deprecated tableview cell’s textLabel, detailTextLabel and imageView attributes. Dive into the <a href="https://developer.apple.com/documentation/uikit/views_and_controls/configurations">documentation</a> to learn about all features and use cases.</p><h4>3. Lists in Collection View</h4><p>Starting from iOS 14, collection views can now be configured with a list layout, which has a UITableView like appearance (someone marked this as the end of table view’s era), the simple setup is:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/656c7b09192f97a9d326d4989bd9942d/href">https://medium.com/media/656c7b09192f97a9d326d4989bd9942d/href</a></iframe><p>Lists come with different styles and list cells with swipe gestures, separators, accessories: <a href="https://developer.apple.com/wwdc20/10026"><em>Lists in UICollectionView</em></a> session covers much of these details.</p><h4>4. Location accuracy</h4><p>There’re many news about Core Location, included the new accuracy permission, which allows users to choose between full and reduced accuracy when they share their location with apps. What if you need the precise location for a particular feature of your app and the user shared only the approximate one? You’re able to ask for it by using:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0457030f28600cbfd4e06e28fe7d45ce/href">https://medium.com/media/0457030f28600cbfd4e06e28fe7d45ce/href</a></iframe><p>The temporary accuracy lasts for the running session only; the key must be added in the NSLocationTemporaryUsageDescriptionDictionary<em> </em>inside the app’s Info.plist and you can add as much keys as you need, to cover different use cases. If you’re interested, I suggest to watch <a href="https://developer.apple.com/wwdc20/10660"><em>What’s new in location</em></a> and <a href="https://developer.apple.com/wwdc20/10162"><em>Design for location privacy</em></a> sessions from WWDC20.</p><h4>5. Tracking authorization (2021)</h4><p>This year focus on user’s privacy didn&#39;t cover only location and web browsing, but also data used by apps. If you access the user’s IDFA and other sensible data for tracking purpose, you’re now required to ask permission to users using the new AppTrackingTrasparency framework:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/30e488e87b54e745b8e3a026f5b92fdf/href">https://medium.com/media/30e488e87b54e745b8e3a026f5b92fdf/href</a></iframe><p>You also need to specify the NSUserTrackingUsageDescription key in the Info.plist. Users can even opt-out entirely from this request, meaning that alerts from any apps will not be fired: the <a href="https://developer.apple.com/wwdc20/10676"><em>Build trust through better privacy</em></a> session shows more about this topic.</p><h4>6. Init UIControls with an action parameter</h4><p>UIControls can now be instantiated with a handy primary action as parameter using a closure (no more selectors 🎉), like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/01b95bf75fe18f3347d4879f51a48135/href">https://medium.com/media/01b95bf75fe18f3347d4879f51a48135/href</a></iframe><p>Same for UIBarButtonItem or UISegmentedControl (with an array of actions in this case); segmented controls get some other useful methods, like the ability to insert a segment with an action at a specified index.</p><h4>7. Menu from buttons</h4><p>Menus can now be shown from any buttons and the Human Interface Guidelines encourages this for many use cases: a good example is the “history menu” showed with a long tap on the back button in a navigation bar. Showing a UIMenu from a button is really easy thanks to the new initializer:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2d20fd63274cf21101a3306224292158/href">https://medium.com/media/2d20fd63274cf21101a3306224292158/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uX9jNqQnUo8MFa7mQWqYhg.png" /></figure><h4>8. UIColorPickerViewController</h4><p>Yes, an easy to use controller to manage the selection of a color from a UIColorWell 🎨 using colorPickerViewControllerDidFinish(_:) and colorPickerViewControllerDidSelectColor(_:) delegate’s methods:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e8ddfe1a1d49769d5b0effdf62d6ec4c/href">https://medium.com/media/e8ddfe1a1d49769d5b0effdf62d6ec4c/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j3N--k1rYBxVSoA9E8u51g.png" /></figure><h4>9. UIPageControl and UIDatePicker additions</h4><p>UIPageControl has new nice features, included the ability to set images as custom page indicators. UIDatePicker comes with a brand new UI, a pop-up menu and the new .inline style:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/15d6f3012f441f9c32f9aa2899066f3c/href">https://medium.com/media/15d6f3012f441f9c32f9aa2899066f3c/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pfdyD-MEWCRw7iGkYnABwQ.png" /></figure><h4>10. Mac Idiom</h4><p>Thanks to the new mac user interface idiom, it’s now more convenient to optimize UIs and behaviors for Catalyst apps (well, not only Catalyst apps, as any apps will potentially be able to run on Macs powered by Apple Silicon):</p><pre>if UIDevice.current.userInterfaceIdiom == .mac { //Your code }</pre><p>And that&#39;s all! Hope you enjoyed Dub-Dub as me, we have big features and small improvements to dive in during next months. Feel free to connect with me on <a href="https://twitter.com/fraancessco">Twitter</a> and <a href="https://techhub.social/@francesco24">Mastodon</a>; thanks for reading and catch up on the next article ☕️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5dba158e2903" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/10-code-snippets-from-wwdc20-5dba158e2903">10 Code Snippets  from WWDC20</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Evolution of Swift Playgrounds]]></title>
            <link>https://medium.com/swlh/the-evolution-of-swift-playgrounds-39bf168be8f?source=rss-c87a8bf31dbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/39bf168be8f</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[playground]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Francesco]]></dc:creator>
            <pubDate>Thu, 11 Jun 2020 10:06:01 GMT</pubDate>
            <atom:updated>2021-04-07T18:15:57.432Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IyznlPF9L69QSzWba_Y7Sg.png" /></figure><p><em>“An amazing platform to learn coding, a great developer tool”</em> is a good definition for Swift Playgrounds, because it summarises two main use cases the platform gives us: on one hand, a way to learn coding (in Swift) with a <strong>challenge based</strong> approach, where learners are guided in the learning process with incremental steps, concepts and tools, tailored to get programming to more people. On the other hand, a great developer tool to <strong>run Swift code</strong> on iPad or outside a classic Xcode project/workspace, giving developers the chance to prototype features, easily test interactions which require device capabilities (like accelerometer), isolate issues from large codebase, create learning experiences: in few words, it’s <em>the fastest way</em> to code with Apple’s APIs.</p><p>I enjoy using Swift Playgrounds in my developer life and since I won a WWDC Scholarship back in 2018. In this article, I want to dive into the evolution of playgrounds and point to some interesting features, use cases and ways to craft a good playground.</p><h4>From the Introduction to the Mac app</h4><p>Playgrounds were first introduced in 2014: <em>Xcode &gt; New Playground</em> was the easier way to start experimenting with the brand new Swift language. One year later, Playground in Xcode 7 was updated with inline results, pages, markup. In 2016, the <strong>Swift Playgrounds iPad app</strong><em> </em>was launched, with code challenges designed by Apple to learn coding and the new playgroundbook format. From there, the app has gained new features every year: ARKit and camera access, Playground Support and Bluetooth frameworks, most of iOS SDK frameworks, 3rd-party subscriptions, just to mention some of them.</p><p>With the 3.0 version, <em>modules</em> arrived in Swift Playgrounds: folder of Swift files shared across the book with multiple access control levels available, enabling modularization, scalable and reusable code. While Xcode Playground remains a great developer tool, the Swift Playgrounds app has covered during time not only the learn coding side, but even many developers use cases, as mentioned in the introduction, with a important issue: playground books were running only on iPad. Until March 2020, when Swift Playgrounds for Mac was released.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qBLCAVEalJnSkS0Sq4d69g.png" /><figcaption>Swift Playgrounds Mac and iPad apps, Xcode Playground</figcaption></figure><h4>.playground vs .playgroundbook</h4><p>As you may already know, a playground usually comes with an <em>editor view</em> on the left, which contains code and (eventually) prose with markup and annotation features; and the <em>live view </em>on the right (if setted). The result sidebar shows a representation of values on corresponding line, customizable using the CustomPlaygroundDisplayConvertible protocol. But, as I wrote above, when we talk about playgrounds, there are two available formats: the .playground and the .playgroundbook. What are the differences?</p><p>The .playground is available from the very beginning: it’s the <em>only</em> format compatible between Swift Playgrounds apps and Xcode, enabling seamless workflow. In fact, you can create a .playground right on the iPad, using the <em>“Playground Xcode”</em> template, and then open the file on the Mac, both on Xcode or from the app. With a standard playground you can create multiple pages, write prose with markup, but modules are missing (even if there are shared and page relative sources). It’s the right choice if you need to switch between Xcode and iPad frequently, with full compatibility, having an immediate on-device feedback while implementing features. Some other powerful features of .playground come from the integration with Xcode: you can read more about them in the last section.</p><p>On the other hand, there’s .playgroundbook: the default format when you create a new document from standalone apps, it has a package-based structure defined by folders and plist files.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8jv-bhq7Ici27dtWCrvqrQ.png" /><figcaption>.playgroundbook structure</figcaption></figure><p>It comes with exclusive features, including already mentioned <em>modules</em>, to organize and modularize code; <em>chapters</em>, to group playground pages with the same topic, and <em>cutscenes</em>, which are fullscreen pages (in HTML or Swift) to show introductions or explanations; a key-value persistent storage, to save data and load it across multiple sessions; a <em>glossary</em>, to define terms cited in the page’s prose; and a system of hints, spoilers and solutions to help learners progress through page’s challenges.</p><p>With the exception of modules, these features are focused on learning experiences. For this reason, the book format is the right choice if you want to create rich <em>learning experiences</em> and tutorials; but it’s a powerful tool to code and prototype without Xcode as well. As now, Xcode can’t even run a .playgroundbook, even if it’s possible to open a book, navigate and modify its structure and files.</p><h4>PlaygroundSupport Framework</h4><p>In order to take advantage of all playground’s features, you should use the PlaygroundSupport framework, which enables you, according Apple’s documentation, to:</p><blockquote>Access a playground page and manage its execution, as well as manage live views; access and share persistent data; assess the progress of the learner, update hints, and show success text</blockquote><p>First, setting the live view: by doing so, playground is able to render your UI stuffs. Live view can be any UIView, a controller, or even SwiftUI View:</p><pre>PlaygroundPage.current.setLiveView(Text(&quot;🤓&quot;))</pre><p>Playground runs in a synchronous way, so it terminates once the last line of code has been executed: this is a problem if you want to work with asynchronous code. To run playground asynchronously, you either set a live view or use the dedicated api:</p><pre>PlaygroundPage.current.needsIndefiniteExecution = true</pre><p>You can import files in playgrounds and use the Bundle.main api to access them. As said, books are able to persist data across sessions, by get or set:</p><pre>PlaygroundKeyValueStore.current[&quot;your-key&quot;]</pre><p>By default, live views run in the same process of playgroundpage’s code: the good is you can access them directly, the bad is that run command reset everything. Playground book offers the feature to run an <em>always-on</em> live view in a <em>dedicated process</em>: this means it persists through different runs, enabling you to edit and run code on the editor. How to communicate between an always-on live view and the playground page? Let’s see an example: we want to send our mood to an always-on view responsible to display it. To configure an always-on live view, we have to put a Live.swift file inside the playgroundpage, where we call the setLiveView function: unfortunately, we can’t do this on standalone apps, so we need to edit the structure of the book from the Mac or use the Xcode template (see next section for more details). After that, we can send our Mood from the playground page using:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9564fb27c27674295913500e2e8b3c81/href">https://medium.com/media/9564fb27c27674295913500e2e8b3c81/href</a></iframe><p>The full list of types you can send as messagges is available <a href="https://developer.apple.com/documentation/playgroundsupport/playgroundvalue">here</a>. To handle messages, just adopt the PlaygroundLiveViewMessageHandler protocol on the object set as live view, in our case a UIViewController:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/32cc4ea73bcec80dc12a44dacde7506a/href">https://medium.com/media/32cc4ea73bcec80dc12a44dacde7506a/href</a></iframe><p>And we did it! Use Messenger.send(.happy) from the page, run it and the live view will be updated. Similarly, to send messages from the live view to the page, there’s the PlaygroundRemoteLiveViewProxyDelegate protocol: you can find full framework doc <a href="https://developer.apple.com/documentation/playgroundsupport">here</a>; the Moods book is at the end of this article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*flmZDxFIQ_oba6atODG2cA.gif" /><figcaption>The Moods book in action</figcaption></figure><h4>Standalone apps, Authoring Books, Xcode Playground</h4><p>Other than formats, the tool you decide to use makes the difference in the playground world. With standalone apps, you’re able to create complex books; code from iPad and then continue on Xcode using the .playground format; more in general, to handle many use cases other than learn coding. And of course, it’s <em>the only way to run books</em>.</p><p>When talking about authoring books with rich learning experiences, you can’t rely just to the app. First, you can’t edit the prose in the editor; well, you can, for example, type /*:This is a sentence*/, close the book, open it again and the sentence will be rendered as prose but… you can’t modify/delete it anymore 🤯. Same happens to annotations like editable regions or hiding: there’s not a rendered-raw markup switch. Moreover, from the apps you can’t create chapter, cutscenes, glossary, hints, handle messages between always-on live view and editor (as we saw above).</p><p>For these purposes, you have to edit the book by modifying its structure, plists, sources and resources on a code editor. If you want to start a new book from scratch, Apple provides an <a href="https://developer.apple.com/download/more/?=Swift%20Playgrounds%20Author%20Template"><strong>Author Template</strong></a>: it’s a Xcode project where you create the entire book’s structure and contents. When you build the project, a .playgroundbook is created, ready to be exported. Being integrated in Xcode, the template offers many benefits: for example, an easier way to use storyboards (compiled stoyboards are packaged in the book) and test the UI.</p><p>Before the conclusion, Playground in Xcode deserves few more words, because it covers some other powerful use cases for developers. First, before the introduction of CreateML, playground in Xcode was the easier way to <em>train a CoreML model</em> right on the Mac. The editor is able to show <em>formatted or raw markup</em>: a unique feature to create prose and check it immediately. In addition, there’s dedicated api to customize TouchBar contents; and the <em>step by step execution</em> (using the tool on the left of the editor) allows to run single lines of code, having the chance to respond to live data. Playground in Xcode can even <em>import 3rd-party frameworks</em> as showed in a <a href="https://developer.apple.com/videos/play/wwdc2018/402/">WWDC18 session</a>, in order to show or test framework’s api: having a framework target, drag the framework project into the playground’s window and it will be converted in a workspace, build the framework and you can import it into the playground.</p><p>Someone pointed to Swift Playgrounds app as a sort of “light Xcode for the iPad”; the release of Swift Playgrounds for Mac (and the rumoured Xcode porting for the iPad?) clarifies one more time they are two different products, with different use cases. <em>But what about next steps?</em> I would love to see an easier way for authoring playground books; a better integration with Swift Package Manager; or some brand new APIs in the PlaygroundSupport framework.</p><p>Here’s some useful resources, including the link to download the playgroundbook sample, full Apple’s documentation and a playlist of WWDC videos about playgrounds. Thanks for reading! ☕️</p><ul><li><a href="https://github.com/francesc-o/PlaygroundBookSample">francesc-o/PlaygroundBookSample</a></li><li><a href="https://developer.apple.com/documentation/swift_playgrounds">Swift Playgrounds</a></li><li><a href="https://developer.apple.com/videos/all-videos/?q=playgrounds">All Videos</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=39bf168be8f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/swlh/the-evolution-of-swift-playgrounds-39bf168be8f">The Evolution of Swift Playgrounds</a> was originally published in <a href="https://medium.com/swlh">The Startup</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dark Mode Tips for iOS]]></title>
            <link>https://levelup.gitconnected.com/dark-mode-one-year-later-d8b01c3a0d8c?source=rss-c87a8bf31dbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/d8b01c3a0d8c</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[dark-mode]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[apps]]></category>
            <dc:creator><![CDATA[Francesco]]></dc:creator>
            <pubDate>Tue, 26 May 2020 08:32:01 GMT</pubDate>
            <atom:updated>2023-02-04T15:18:10.443Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="iPhone screens on Dark Mode" src="https://cdn-images-1.medium.com/max/1024/1*zTInBhoUwGdHy7Dcz3vk5g.jpeg" /></figure><p>It has been <em>a while</em> since the introduction of the Dark Mode with iOS 13 and a lot has been written about dynamic colors, color sets, dynamic images/materials and other tools to support this new style.</p><p>After facing some challenges, I want to dive in with some UIKit tools which may be useful for particular needs. Let’s start! 🧑🏼‍💻💡</p><h4>The basics: custom dynamic color</h4><p>As you may already know, dynamic colors are available through 3 different ways: by using system-defined semantic colors (like <em>systemBackground</em>, <em>label</em>, <em>systemRed</em> and so on), by defining custom UIColor sets in the Assets.xcassets or by coding your dynamic colors like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9116605b1cf1b707031c542743157a27/href">https://medium.com/media/9116605b1cf1b707031c542743157a27/href</a></iframe><h4>User Interface Level and Traits</h4><p>Think about Apple’s apps, like Messages, in Dark Mode: the same <em>backgroundColor</em> looks black on the main view, but dark gray on a controller presented with the new .automatic modal style. It’s a little detail that gives to users (combined with the animation) the <strong>sense of modality</strong>. By defining in code your custom dynamic colors, you’re able to achieve the same result, just use the userInterfaceLevel property along with the already known userInterfaceStyle<em> </em>of UITraitCollection:</p><pre>case .dark: return traits.userInterfaceLevel == .elevated ? elevatedDark : dark</pre><p>These kinds of customizations are available not only for colors, but for other UI elements, like images, that you may want to adapt to different styles.</p><p>More in general, the style and level of the user interface are just the most common traits you may use to adapt your UI to Dark Mode, but UITraitCollection offers a complete set of tools to fine-tune our UI, based on many different environment conditions: you can find more about it in the <a href="https://developer.apple.com/documentation/uikit/uitraitcollection">official documentation</a>.</p><h4>Resolve dynamic color/image</h4><p>There are some use cases where you may need to know the current RGB value of a dynamic color, for particular needs; in some other use cases, like working with CALayer, you <em>have to</em> know the current value of a dynamic color. In these situations, we can resolve dynamic colors (as well as images) using the system defined API:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2faa8c7a8bd29fa5cc8542d8408079e0/href">https://medium.com/media/2faa8c7a8bd29fa5cc8542d8408079e0/href</a></iframe><h4>Let the user choose (overriding)</h4><p>Following the system defined style is the main (and always good) way to adapt our app’s style; but let’s say we want to give our users the freedom to choose which style the app should adopt among light, dark and system, because of the particular type of the app or just as a customization option. The UIUserInterfaceStyle<em> </em>key of Info.plist doesn&#39;t help us, because it locks the UI to a single style. The overrideUserInterfaceStyle<em> </em>method overrides style on screen, windows, views and controllers (and their descendants), but how would we use it efficiently? Let’s see this reeeally simple implementation:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9599a41750c2d4e21932395e6f3c56a7/href">https://medium.com/media/9599a41750c2d4e21932395e6f3c56a7/href</a></iframe><ul><li>the user can choose among light, dark and system styles: the last one refers to the UIScreen’s userInterfaceStyle, which is always the system level style;</li><li>when the user switch style, we override the keyWindow’s<em> </em>style by calling the updateTheme<em> </em>function, so the change automatically spreads across the app and we store the user’s preference;</li><li><strong>NB</strong>: if you’re using the new UISceneDelegate to manage multiple windows, you should rely on that API instead of keyWindow.</li></ul><p>And that’s all, thanks for reading! ☕️ You can find some official resources about Dark Mode at these links:</p><ul><li><a href="https://developer.apple.com/documentation/xcode/supporting_dark_mode_in_your_interface">Apple Developer Documentation</a></li><li><a href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode/">Dark Mode - Visual Design - iOS - Human Interface Guidelines - Apple Developer</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d8b01c3a0d8c" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/dark-mode-one-year-later-d8b01c3a0d8c">Dark Mode Tips for iOS</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>