fleetingpixels.com Ads.txt file









Coding & Tech with David Caddy | Fleetings Pixels



















  • Introducing DCSettings


    David Caddy | Published May 22, 2023

    DCSettings is a Swift package that simplifies the configuration of user preferences with an easy-to-use result builder syntax and a drop-in SwiftUI user interface.

    You can quickly configure settings in UserDefaults, NSUbiquitousKeyValueStore or a custom key-value store like so:

    DCSettingsManager.shared.configure {
    DCSettingGroup("General") {
    DCSetting(key: "refreshInterval") {
    DCSettingOption(value: 5, label: "5 mins")
    DCSettingOption(value: 10, label: "10 mins")
    DCSettingOption(value: 15, label: "15 mins")
    DCSettingOption(value: 30, label: "30 mins", isDefault: true)
    DCSettingOption(value: 60, label: "60 mins")
    }
    DCSetting(key: "articleListLayout") {
    DCSettingOption(value: "List", label: "List", systemImage: "list.bullet")
    DCSettingOption(value: "Grid", label: "Grid", systemImage: "square.grid.2x2")
    }
    DCSetting(key: "showImages", defaultValue: true)
    DCSetting(key: "showFullContent", defaultValue: false)
    DCSetting(key: "markAsReadOnScroll", defaultValue: true)
    DCSetting(key: "maxSyncItems", defaultValue: 1000)
    }
    DCSettingGroup("Appearance") {
    DCSetting(key: "theme", label: "Theme", options: ["Light", "Dark"], defaultIndex: 0)
    DCSetting(key: "fontSize", options: [12, 14, 16, 18, 20], defaultIndex: 2)
    DCSetting(key: "lineSpacing", defaultValue: 1.2, lowerBound: 1.0, upperBound: 1.6, step: 0.1)
    DCSetting(key: "highlightColor", defaultValue: Color.blue)
    }
    }

    Once your settings are set up, you can quickly add a settings view to your app using DCSettingsView. This view displays a list of all settings that grouped as configured:

    DCSettings screenshot

    For more information on how to use DCSettings, check out the GitHub repository.






  • Control Sizing in SwiftUI


    David Caddy | Published October 23, 2022

    Especially when working on Mac apps, controlSize) is a handy property to know about that allows you to change the size of controls within a SwiftUI view. The default size is .regular, but there's also .large, .small, and .mini.

    You may have noticed that in the new System Settings app on macOS Ventura, the switch controls are smaller than they would be by default. This is because the control size has been set to .mini.

    As an example, let's say you have a view that contains a number of controls, like so:

    struct ControlsView: View {
    var label: String
    @State private var value = 3.0
    @State private var selected = 1
    @State private var active = true

    var
    body: some View {
    VStack {
    HStack {
    Text(label)
    Spacer()
    }
    .foregroundColor(.secondary)
    .italic()
    Picker("Selection", selection: $selected) {
    Text("option 1").tag(1)
    Text("option 2").tag(2)
    }
    Slider(value: $value, in: 1...10) {
    Text("Slider")
    }
    HStack {
    Toggle("Check box", isOn: $active)
    Spacer()
    Button("Button") { }
    Spacer()
    Toggle("Switch", isOn: $active)
    .toggleStyle(SwitchToggleStyle())
    }
    }
    }
    }

    Then, sepcifying the control size is as simple as using the .controlSize() modifier on the view, along with the desired size:

    struct ControlSizeView: View {
    var body: some View {
    VStack {
    ControlsView(label: "Mini")
    .controlSize(.mini)
    Divider()
    ControlsView(label: "Small")
    .controlSize(.small)
    Divider()
    ControlsView(label: "Regular")
    .controlSize(.regular)
    Divider()
    ControlsView(label: "Large")
    .controlSize(.large)
    }
    .padding()
    }
    }

    The result running on macOS:






  • App Analytics Usage Data for Mac Menu Bar Applications


    David Caddy | Published June 12, 2021

    Back on March 15, 2021, Apple put out a release to developers stating:

    App Analytics now provides usage metrics for Mac apps, including data on installations, sessions, active devices, crashes, and deletions. And now you can measure user retention to see how often users return to your app after downloading it. Data is only available from users who have agreed to share their diagnostics and usage information with app developers.

    As with most things to do with App Analytics, Apple has done a fantastic job of enabling this without any action required from developers. However if you, like me, have been puzzled to not see this new data come through for your menu bar apps, I learned from a helpful WWDC lab session that agent applications (LSUIElement) are excluded from these new metrics.

    Admittedly this use case is more challenging to capture in a meaningful way, but menu bar apps are different to entirely background processes in that the user does interact with them on screen, so I’m hopefully some form of usage metrics will be enabled for this class of apps in the future.






  • Pop-Up Buttons in Mac Catalyst v3


    David Caddy | Published June 10, 2021

    Starting with macOS Monterey, Catalyst apps will now be able to use pop-up buttons.

    Simply set a menu to the target button and enable both showsMenuAsPrimaryAction and changesSelectionAsPrimaryAction:

    let button = UIButton(type: .system)
    button.menu = UIMenu()
    button.showsMenuAsPrimaryAction = true
    button.changesSelectionAsPrimaryAction = true





  • Tooltips in Mac Catalyst v3


    David Caddy | Published June 10, 2021

    Starting with macOS Monterey, Catalyst apps will now be able to display tooltips; little messages that display on hover to provide the user with helpful hints and context.

    Any UIView can be given a tooltip using UIToolTipInteraction like so:

    let toolTipView = UIView()
    let toolTipMessage = "Tool Tip text"
    let toolTipInteraction = UIToolTipInteraction(defaultToolTip: toolTipMessage)
    toolTipView.addInteraction(toolTipInteraction)

    As one of the most common use cases is to help clarify the function of buttons and other controls, UIControl been given a convenience property, that makes it even easier to had tooltips to any control that conforms:

    let button = UIButton(type: .system)
    button.toolTip = "Tool Tip Text"





  • Platform Conditional Modifiers in SwiftUI v3


    David Caddy | Published June 9, 2021

    SwiftUI version 3 (coming in iOS 15 & macOS Monterey) has brought with it many nice features, including the ability to use #if conditional statements for postfix member expressions and modifiers:

    Text("Title")
    #if os(iOS)
    .font(.title)
    #else
    .font(.headline)
    #endif





  • Markdown in SwiftUI v3


    David Caddy | Published June 9, 2021

    SwiftUI version 3 (coming in iOS 15 & macOS Monterey) has brought with it many nice features, including the ability to easily work with Markdown. Text elements now support Markdown natively, like so:

    VStack {
    Text("Regular text")
    Text("*Italic text*")
    Text("**Bold text**")
    Text("~~Strikethrough text~~")
    Text("[Link](apple.com) text")
    }





  • Load Images Asynchronously in SwiftUI v3


    David Caddy | Published June 9, 2021

    SwiftUI version 3 (coming in iOS 15 & macOS Monterey) has brought with it many nice features, including AsyncImage, which greatly simplifies the process of downloading and displaying remote images from the internet:

    let imageURL = URL(string: "<exampleURL>")
    //...
    AsyncImage(url: url) { image in
    image
    .resizable()
    .aspectRatio(contentMode: .fill)
    } placeholder: {
    Color.red
    }
    .frame(width: 200, height: 200)

    In the above example a red placeholder view is shown while the image is loading.








  • How to Add Chapters and Other Metadata to Your Podcasts on macOS


    David Caddy | Published August 6, 2020

    If you have a podcast, a Mac and want to take your show to the next level then this post is for you.

    PodWise is a simple and intuitive app for the Mac that allows you to quickly and easily add chapter markers and other metadata to your MP3 episode files (using ID3 tags). Chapters are a fantastic addition to any podcast, especially those that are longer form, and your listeners will thank you for their inclusion.

    PodWise is available now on the Mac App Store.

    The video below shows PodWise in action, check it out to see how simple adding a little extra polish to your show can be:






  • Developer Sat


    David Caddy | Published June 22, 2020

    The recent App Store rejection of Basecamp's new email app Hey has triggered much overdue conversation around Apple's relationship with third-party developers.

    As a very brief recap of the situation, Apple has a number of rules that developer's must comply with in order for their apps to ever grace a customer's iDevice, including mandatory use of Apple's payment mechanisms when selling any digital goods or services. And while there are exceptions if certain conditions are met and hoops jumped through, this issue essentially boils down to Basecamp wanting to charge customer's directly and Apple not allowing it.

    As a developer who's enjoyed some success on iOS, Apple has been good to me, and like many I'd prefer not to rock the boat but I would like some choice. And given Apple is one-half of a mobile operating system duopoly with Google – currently under investigation by the EU on antitrust concerns – perhaps now is the time for the Cupertino tech giant to revisit some of its policies.

    One part of the controversy revolves around money; Apple takes 30% of all App Store revenue, which some have grumbled about for years and congressman David Cicilline in a recent interview labeled as "highway robbery" and "unconscionable". In comparison, as of early last year, Microsoft takes 15% of sales revenue on its Windows App Store, and just 5% of those generated from a direct link (presumedly from external marketing exercises from the company behind the product). Another comparison one could make is with content creators and Youtube, where Google takes a massive 45% of advertising revenue on the platform, making 30% all of a sudden seem quite reasonable.

    I think the actual figure here is not the key issue though, it's the fact that the App Store is the only way to distribute iOS software to customers that's the problem. Given the shear size of Apple these days and their immense influence on the technology sector, the company does have a duty to be transparent and competitive in its business operations.

    Imagine a world where Apple takes 5% of App Store sales revenue, would most developers be far happier? Of course. Imagine another world where Apple takes 30% but allows an alternate means to distribute applications, would most be happier then? I think so.

    If Apple does change course towards either scenario it will lose some revenue, and for a for-profit company any move in that direction on the surface doesn't make sense. Third-party developers have been and will continue to be part of Apple's long-term success, however, and how they feel should be important to the company.

    John Gruber discussed an undercurrent of App Store dissatisfaction from developers in a piece from earlier this week:

    This resentment runs deep and is stunningly widespread. You have to trust me on the number of stories I’ve been told in confidence, just this week. Again, putting aside everything else — legal questions of antitrust and competition, ethical questions about what’s fair, procedural questions regarding what should change in the written and unwritten App Store rules, acknowledgement of all the undeniably great things about the App Store from the perspective of users and developers — this deep widespread resentment among developers large and small is a serious problem for Apple.

    This issue is a complex one and while ultimately I feel Apple can do what it likes, I also think those in charge should reflect on their values and reconsider the company's current position. I'd say it's unlikely but maybe, just maybe, Apple will go some way to addressing these concerns at WWDC, their imminent developers conference.

    I'll leave you with the thoughts of Russell Ivanovic, of Shifty Jelly and Pocket Casts fame:

    As a developer, who has put up with this for over a decade now, I’m only asking one thing. Please consider how many of us feel this way, and how bad this will be for developers and eventually, customers, if Apple keeps being allowed to move the goal posts further and further without us pushing back.







  • David Caddy | Published June 17, 2020

    Filipe Espósito reporting for 9To5Mac:

    Following yesterday’s release of a new update to the Apple Developer app with a macOS version, Apple today revamped the App Store Connect portal with a modern design just a few days before WWDC 2020.

    Finally! I had lost all hope Apple would ever fix App Store Connect on mobile. I can’t tell you how many frustrated minutes I’ve spent trying to carefully pinch, scroll and zoom, just trying to check or change one simple thing on my phone from bed. This bodes well for more welcome changes for developers come Monday.






  • How to Adopt UIScene APIs in an Existing iOS Project


    David Caddy | Published June 17, 2020

    With iOS 13, Apple introduced the idea of scenes to enable apps having and managing multiple windows. If you create a new Xcode project this new lifecycle paradigm will be set up for you, in this post I’ll walk you through the few simple steps needed to add UIScene support to an existing project.

    First, add the following two UISceneSession methods to your App Delegate:

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create
    // the new scene with.

    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application
    // was not running, this will be called shortly after
    // application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were
    // specific to the discarded scenes, as they will not return.

    }

    Next, create a scene delegate that conforms to UIResponder and UIWindowSceneDelegate, like so:

    import UIKit

    class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the
    // UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will
    // automatically be initialized and attached to the scene.
    // This delegate doesn't imply the connecting scene or session are new
    // (see `application:configurationForConnectingSceneSession` instead).

    guard let _ = (scene as? UIWindowScene) else { return }
    }

    func sceneDidDisconnect(_ scene: UIScene) {}
    func sceneDidBecomeActive(_ scene: UIScene) {}
    func sceneWillResignActive(_ scene: UIScene) {}
    func sceneWillEnterForeground(_ scene: UIScene) {}
    func sceneDidEnterBackground(_ scene: UIScene) {}
    }

    Once your scene delegate is in place, the project’s Info.plist needs to be edited to reference it:

    <key>UIApplicationSceneManifest</key>
    <dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
    <key>UISceneConfigurations</key>
    <dict>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
    <dict>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UISceneConfigurationName</key>
    <string>Default Configuration</string>
    <key>UISceneDelegateClassName</key>
    <string>SceneDelegate</string>
    <key>UISceneStoryboardFile</key>
    <string>Main</string>
    </dict>
    </array>
    </dict>
    </dict>

    And that’s it, if everything’s hooked up correctly you should now be up and running with scenes.






  • How to Create a Mac Menu Bar App With NSPopover


    David Caddy | Published June 15, 2020

    In this tutorial I'm going to walk you through creating a menu bar app for macOS, which displays a custom view inside an NSPopover.

    The goal of this tutorial

    Basic Set Up

    In Xcode, go to File > New > Project… then select App from the macOS tab and click Next. Fill in the project details as you like, click Next again, choose where to save the project and click Create.

    To be a proper menu bar app, the interface should only be accessible from the menu bar. To archive this we need to hide the dock icon and main window. First, simply open the Main.Storyboard file of the project then select and delete the Window Controller Scene (not the View Controller Scene). This will prevent the main window from displaying.

    To disable the dock icon, open the Info.plist file of the project and add Application is agent (UIElement) as a new key and set its value to YES.

    Before we move on to the fun stuff, let's just take care of one more thing. In order to display an NSPopover, we will need a reference to an NSViewController, so let's quickly set up a way to get one.

    Open the Main.Storyboard again, select the View Controller Scene and click the small triangular disclosure button on the left to reveal its View Controller object. Select that, and then in the Identity Inspector (press Option + Command + 4 to show the inspector) make sure the Storyboard ID property is set to "ViewController".

    Now jump over to the ViewController.swift file and add the following inside the ViewController class.

    static func newInsatnce() -> ViewController {
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
    let identifier = NSStoryboard.SceneIdentifier("ViewController")

    guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? ViewController else {
    fatalError("Unable to instantiate ViewController in Main.storyboard")
    }
    return viewcontroller
    }

    I won't explain this in great detail as we have bigger fish to fry, suffice to say it's a convenience method we will use later to create an instance of the ViewController class from our main storyboard. Once finished, this class will be the main interface for your app and can be customised as needed.

    Displaying the Popover

    Enough of the tedious stuff, let's get a popover going already!

    Go to the AppDelegate.swift file and copy the following inside and at the top of the AppDelegate class.

    let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)

    This code asks the system to create and return a new, empty status item object of a specified width.

    Menu items that occupy the right side of the macOS status bar are called status items, those on the left - used to perform actions in the currently focused application - are just referred to as menu items (NSMenuItem and NSStatusItem respectively).

    For the length parameter we pass in NSStatusItem.squareLength to make the item as wide as it is heigh (a.k.a square).

    Now that we have a reference to the newly created status bar item, we can customise its appearance and listen for click events.

    Add the following inside the applicationDidFinishLaunching function, still in AppDelegate.swift.

    if let button = self.statusItem.button {
    button.image = NSImage(named: NSImage.Name("ExampleMenuBarIcon"))
    button.action = #selector(AppDelegate.togglePopover(_:))
    }

    Here we are getting a reference to the NSStatusBarButton object of the status item and setting its image to a custom one.

    Make sure you have an image set inside the Assets.xcassets folder with a @2x image of size 32x32px, and use its name in place of "ExampleMenuBarIcon".

    We then set the button's action to trigger the togglePopover function, that we will write next, to fire whenever the status item is clicked.

    Add the following function inside and at the bottom of the AppDelegate class.

    @objc func togglePopover(_ sender: NSStatusItem) {
    }

    Now that we are capturing click events, it's finially time to display the promised popover. Add an initialised NSPopover variable under the status item declaration, still inside AppDelegate.swift, like so:

    let popover = NSPopover()

    And then add the following two lines at the end of the applicationDidFinishLaunching function:

    self.popover.contentViewController = ViewController.newInsatnce()
    self.popover.animates = false

    The first line sets the content of the popover to be a new instance of the ViewController class, using the convenience method we set up earlier. The second just prevents the popover from animating when opened or closed, which I find distracting.

    Now add the following function at the end of the on AppDelegate class:

    func showPopover(sender: Any?) {
    if let button = self.statusItem.button {
    self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
    }
    }

    func closePopover(sender: Any?) {
    self.popover.performClose(sender)
    }

    As the names suggest, these will be used to actually show and hide the popover.

    Now add the following inside the previously written and empty togglePopover function.

    if self.popover.isShown {
    closePopover(sender: sender)
    }
    else {
    showPopover(sender: sender)
    }

    This code will trigger the appropriate action - either open or close - depending on the current status of the popover, creating the toggling behaviour.

    That's it! Now try to build and run. If everything was set up correctly, you should see a status icon with your custom icon, that when clicked shows and hides a view inside a popover.

    Demo code is available here, which also includes a simple EventMonitor class that ensures the popover is dismissed when the user clicks outside its bounds. As well as some commented out code that could be used to capture right mouse click events, which you might want use to display a separate view upon detection of that action.






  • How to Use Swift Packages in Objective-C Targets


    David Caddy | Published June 14, 2020

    If, as I have, you’ve started using Swift packages to reuse code amongst your projects, you may have wondered if it’s possible to use them in Objective-C projects. Fortunately, the answer is yes, provided you’re using Xcode 11.4 or newer. Just make sure you use the @import syntax in your ObjC file, not the older #import style, and it should work as expected.

    One thing to note, I’ve found that autocomplete doesn’t seem to work consistently, which is understandable for such a recent feature addition. Bearing that in mind, if you start to think things aren’t hooked up properly because Xcode doesn’t seem aware of the package contents, just write some code, double check the syntax, build and it should run fine.

    If you’re new to Swift packages in general, also be aware that classes and functions should be marked as public to be visible and usable outside the package, as they are designated as internal by default. And, of course, remember to use the @objc attribute so your Swift code is accessible within the Objective-C runtime.






  • Menulog Rebrand Coming Soon


    David Caddy | Published June 13, 2020

    Menulog - the Australian and New Zealand online food ordering and delivery platform - has just announced a new logo that will soon be used on all branding going forward. Ditching the distinctive bright green for what the company is calling a "new signature orange", the redesign is certainly different, although I'm not entirely sure it's an improvement.

    The full announcement from the company reads as follows:

    MENULOG WILL SOON HAVE A FRESH NEW LOOK (Here’s) a sneak peek at Menulog's bright new brand. The Menulog brand is getting a fresh new look and we wanted to give you a sneak peak of our new signature orange colour and updated, modern logo. Over the next few weeks, you will start to see the new colour, new logo and updated visual appear on things such as your Menulog App, in-store restaurant branding and more - stay tuned!




View All







Ads.Txt Alerts - A trading name of Red Volcano Limited

Unit 6, Leylands Business Park, Colden Common, Hampshire, SO211TH

© Red Volcano 2020. All Rights Reserved.