Cocoa Switch
CV Archive Photos Also on Micro.blog
  • For those who updated to 18.2, go to Settings > Display & Brightness > CAMERA CONTROL. Set “Require Screen On” as disabled. You’re welcome. 📸

    → 3:40 PM, Dec 17
  • Building interactive Apple Watch widget

    With watchOS 10, we are able to add widgets into Smart Stack or use them in large complications. The Modular watch face offers one large complication. I use it to display my passwords and PIN codes using my own app Pinbook ($4.99). But there’s a problem: this complication is always visible, especially with Always On screens, and you potentially can reveal sensitive information. And I couldn’t make the complication interactive until watchOS 11.

    Now in watchOS 11, Apple added interactive widgets, and I began working on updating the app. Finally, I was able to build my original vision of this product. Development took longer than expected because I also wanted to include a bunch of other features. I am using the Modular watch face with Pinbook 1.1 every day, and I find it convenient.

    Now let’s dive deep into technical implementation. I am not sure my implementation is right, but it took some time to figure out and is not obvious. It is possible I am not using the most optimal strategy.

    At the core, I use the NSUserDefaults flag to toggle between two states: locked and unlocked. You can only see passwords in the unlocked state. And you see a -- placeholder in the locked state.

    @AppStorage("unlocked") private var unlocked = false
    

    The @AppStorage is used in the widget View.

    The only way to make the widget interactive is to use the App Intents API.

    Button(intent: RevelPasswords()) {
    	// Widget View
    }
    

    Here’s the entire app intent.

    import Foundation
    import AppIntents
    import WatchKit
    
    struct RevelPasswords: AppIntent {
    
        static var title: LocalizedStringResource = "Revel passwords"
        static var description = IntentDescription("Used for widget")
    
        func perform() async throws -> some IntentResult {
            if UserDefaults.standard.bool(forKey: "unlocked") {
                UserDefaults.standard.set(false, forKey: "unlocked")
            } else {
                UserDefaults.standard.set(true, forKey: "unlocked")
            }
            return .result()
        }
    }
    

    Finally, my widget view.

    struct ColumnView: View {
    
        let pin: Pin
    
        @Binding var unlocked: Bool
    
        var body: some View {
            Label {
                if unlocked {
                    PasswordView(password: pin.code)
                } else {
                    PasswordView(password: "--")
                        .privacySensitive(true)
                }
            } icon: {
                Image(systemName: pin.symbol)
                    .font(.caption)
                    .frame(width: 8, height: 8, alignment: .center)
                    .widgetAccentable()
            }
            .onDisappear() { // This does not work.
                unlocked = false
            }
        }
    }
    

    I use @Binding linked to @AppStorage in a parent view. Unfortunately, I have not yet found a way to toggle between the 2 states programmatically. For example, when the Apple Watch screen is not active, I could automatically hide passwords. I have tried to use .onDisappear(), and it didn’t work. I am sure there’s a way to do it, but I just didn’t have enough time to figure it out yet.

    → 8:33 PM, Dec 16
  • Some Apple Vision Pro optimism

    Although I don’t own AVP yet, the latest episode of Vision Pro made me feel like I am missing out. The guest was so excited about the platform and closer to the end he said one thing which resonated with me. Santiago works from the office four days a week and one day from home. The guest said that after a full day working in AVP, he feels no discomfort in his eyes, and after a day in the office he feels eye strain. It has to do with the focal distance. AVP is set to more natural further away focal distance than any desktop setup. The host Tim mentioned that in our day more and more people wear glasses and it is due to the smartphone and computer screens being so close to us. AVP changes the game completely. A combination of high resolution and natural focal distance makes it much more comfortable than any computer display.

    I am very intrigued about the headset’s uninventive update, and I likely will buy it instead of Studio Display or a newer Mac. I own an M1 Max MacBook Pro, and it has plenty of performance.

    → 1:18 PM, Nov 17
  • Another war crime. Two boys were killed by a glind bomb strike. The USA needs to permit long-range strikes and allow Ukraine to defend its people. Learn more about the attack in the first five minutes of Ukraine: The Latest overcast.fm/+AA36OBSi…

    → 10:39 PM, Nov 6
  • I just bought a PS5 game using the PlayStation app, right in the app using web view. It’s very fluid.

    → 9:14 PM, Oct 14
  • Northern lights from yesterday.

    → 11:37 AM, Oct 12
  • Adjusting to new iPhone

    I have upgraded from beloved 13 mini to 16 Pro, and here are my notes.

    • Tried and disabled “Tap or Swipe to Wake”. Reduces the urge to pick up my phone when working. Reduces accidental awakes.
    • Tried and disabled keyboard sounds and haptics
    • I shoot all my videos using LOG PRORES format and applying colour profiles with Kino app. Keep the Instant Grade toggle off.
    • New photo styles are separated into “Undertones” and “Mood”, and they are not the same thing.
    • Always On display — I like it because I can see notifications without picking up my phone. Every pickup is a potential time sinker.
    • PRO motion – don’t notice and can live without it.
    • Limited battery charge to 80%, don’t need more.
    • I bought the Beats case with an open bottom, it matters, and I feel the difference every time I use my phone.
    • Action Button set to mute. I am a boring person, I know.
    • Lock screen: The right button is set to Torch.
    • Lock screen: The right button is set to Halide.
    • Camera Control set to open the Camera app.
    → 3:52 PM, Oct 10
  • This is good news — “cozy” WWDC with live presenters and coding. Wish I could be there. It makes sense to have this format for the next frontier tech where innovation needed. I hope the tradition will continue. It is like the whimsical hearth of the old Apple is still beating.

    → 10:10 AM, Oct 9
  • Finished reading: Presumed Innocent: A Kindle County Legal Thriller Book 1 by Scott Turow 📚

    → 8:57 PM, Oct 3
  • Let’s say you have two targets: iOS and watchOS. Talking SwiftUI, would you prefer to reuse views and litter your code with #if os(), or duplicate your views? I was tempted to use separate files but worried it would introduce a long term burden for code maintenance.

    → 4:19 PM, Sep 23
← Newer Posts Page 12 of 37 Older Posts →
  • RSS
  • JSON Feed