/r/swift

Photograph via snooOG

Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.

ATTN! Looking for work or to hire? Check out r/SwiftJobs!


About:

Dedicated to the Swift programming language released by Apple. More info in the Swift Wiki.

Please, check the FAQs before submitting.


IRC Chatrooms:

General Swift Discussion

irc.freenode.net #swift-lang

Cocoa/Cocoa Touch Discussion

irc.freenode.net #cocoa-init

Related Subreddits:


Keywords: swift, swiftlang, ios, os x, apps, apple, mac, iphone, ipad

/r/swift

121,674 Subscribers

5

I’ve updated my first app that implements the new ML APIs - Similarity and aesthetic models

8 Comments
2024/12/03
18:59 UTC

0

Why does removing the 'List' make such a big difference?

1 Comment
2024/12/03
17:58 UTC

2

How can you programmatically hide the toolbar, like the 'Hide Toolbar' menu item, in a Mac Catalyst app running on macOS Sequoia?

My Mac Catalyst app includes a tab bar that I don't want to appear as a toolbar, as it does on macOS Sequoia. Is there a way to prevent this by programmatically hiding the toolbar somehow?

0 Comments
2024/12/03
17:19 UTC

2

Combine: getting a value that was sent before subscription

Hi, Combine noob here. Here is a unit test that demonstrates what I am trying to achieve:

import XCTest
import Combine

final class CombineTests: XCTestCase {
  func testPassThroughSubject_whenSendBeforeSubecribing_theSubscriberReceivesAValue() {
    let sut = PassthroughSubject<Void, Never>()
    var cancellables = Set<AnyCancellable>()
        
    // First: send
    sut.send(())
    
    // Then: subscribe
    let expectation = expectation(description: "Subscriber receives a value")
    
    sut
      .sink { expectation.fulfill() }
      .store(in: &cancellables)
                
    wait(for: [expectation], timeout: 1)
  }
}

I've read somewhere that publishers will only emit values once they are subscribed to, and my naive interpretation of that is that this test should pass. But it fails - the expectation is never fulfilled. (The inverse test (swapping around the send and subscribe) works fine.)

In my real code situation, I can't guarantee the order in which these operations occur (sending a value to the subject vs subscribing to the subject). I want to ensure that, regardless of which happens first, if both those conditions are eventually met, then the subscriber will receive the value that was sent. How do I go about that?

UPDATE

Ok, so I thought it was OK to store my cancellables in the method scope, but it seems like all that was needed to make my test pass was to store them in a class property. This test passes:

final class PublishSubscribeTests: XCTestCase {
  private var cancellables = Set<AnyCancellable>() // NB: Store cancellables in class scope
    
  func testPublishBeforeSubscribe_shouldTriggerSubscriber() {
    let subject = PassthroughSubject<Void, Never>()
        
    let expectation = expectation(description: "Subcriber should receive event")
    subject
      .sink { expectation.fulfill() }
      .store(in: &cancellables)
        
    subject.send(())
    waitForExpectations(timeout: 1)
  }
}
11 Comments
2024/12/03
07:01 UTC

1

Crash at UITableView.reloadSections

We're getting this weird crash infrequently, not sure if it's because data source was changed incorrectly. I searched for _Bug_Detected_In_Client_Of_UITableView_Invalid_Batch_Updates but got nothing, all results said it's related to data source changing but the message seems different. Any help is appreciated! Thanks.

https://preview.redd.it/tsp3j33auj4e1.png?width=1318&format=png&auto=webp&s=8c64403a19673debbb0d181c78ab8fd57bb8907a

0 Comments
2024/12/03
03:06 UTC

2

Help with upcoming SDET Interview

Hello!

I have a junior SDET interview coming up in swift and I have no idea what I should be studying. I’ve gone thru codecademys course on ios Development but not sure what else I should do. I’ve also set up XCUITest automation for my app. They said the interview would be over swift fundamentals and heavily focused on structs vs classes and knowledge of enums. Anything helps. Maybe a guide or a list of study questions.

Thanks

9 Comments
2024/12/03
01:38 UTC

0

🦺 Making your own custom Optional 👌

7 Comments
2024/12/02
13:39 UTC

3

Swift6 compatibility issue

I am trying to make my code swift6 compatible. When I set "Strict Concurrency Checking" to "complete" I get the following error:

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure; this is an error in the Swift 6 language mode

for the this code:

class S6Class {
    var number:Int = 0
    init(){
        Task{ //-- warning: Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure; this is an error in the Swift 6 language mode
            number += 1
        }
    }
}

Any suggest how to resolve this.

Thanks Reza

17 Comments
2024/12/02
13:18 UTC

4

Anybody else have 75% of their Free Trials go to "Billing Retry" issues?

Hey everyone,

Recently built an app that got decent traffic coming to it and going into free trial. All US iOS users.

But most the uncanceled free trials go into a "Billing Retry" state on App Store Connect. If anybody has any ideas they want to share to solve this, it would be amazing.

Some things I tried:
- Doing $1 trials, and same thing happened (Billing Retry) after the $1 trial ended.
- Switched fully to RevenueCat instead of my own StoreKit2 implementation, problem still continued.

Just having a hard time thinking that 75% of US users would invalidate their CCs when almost no other app developer has this same issue online.

2 Comments
2024/12/02
07:15 UTC

6

Eager to learn but keep getting stuck...

Hello fellow iOS enthusiasts. I'm currently taking Angela Yu's iOS course and am loving it thus far. The only issue is when it comes time for me to do some of the challenges, I hit a road block and feel stuck. It's so easy to get down on yourself and be self critical because I know I'm very capable of learning new things when I really put my mind to it and when I get stuck it makes me feel like I'm not cut out for this.

I'm so eager to learn the basics and start building a portfolio so that I can achieve my goal of getting my first job as an iOS dev in a year, so that's why thinking about going back to review past sections of the course bothers me because I want to grind through and move on to actually building my own projects.

At the same time I feel like it's a really bad idea to rush through this because I want to genuinely understand the principles and really lock them into my brain so that I can scale these fundamentals and do whatever my vision is for any given project I'm working on in the future.

I'm on a challenge now that I just can't crack and I would feel foolish if I just looked at the solution, but trust me this is the 4th session of me coming back to my computer and trying again and I just feel defeated. I'm sure every single developer goes through this or has gone through it so, any advice would be greatly appreciated.

Nothing worth doing is easy and I truly get that, I'll never give up. Just so easy to be hard on yourself...

Thanks for reading if you did,

Nick

11 Comments
2024/12/02
05:15 UTC

2

Help with SwiftUI preview canvas

Currently learning SwiftUI and the tutorial I am following can use the magnifying icon to zoom in on the preview canvas, and it will zoom in towards the middle. For some reason, mine will only zoom in towards the top left corner of the virtual canvas when zooming close up. Any way to fix this?

0 Comments
2024/12/02
05:12 UTC

10

Optimizing Swift to prevent leaks and hangs

I've been working on an ML project in Swift, and through all of it, I've tried to ensure that it was as well optimized for performance as possible. Now, however, I'm actually trying a full scale test, and I'm seeing large memory leaks and seemingly constant severe hangs. I've tried using Instruments to see the root causes of the leaks and hangs, but I can't see anything that I understand. The framework is available on GitHub here.

If anyone is able to identify issues with my code that could cause it to run slow, or induce memory leaks, it is greatly appreciated.

27 Comments
2024/12/01
22:47 UTC

1

Darwin/Glibc for Windows

Is there any C library for Swift that has the same features like Darwin/Glibc?

1 Comment
2024/12/01
17:21 UTC

0

Flutter vs react native vs native swift

Hello my name is victor I would like to develop a productivity application that interacts with the reading of NFC and access the screen time api to make reports of the improvement of time of use of the phone, I would also like to know if you would have problems to access the parental control and that people can block applications while they are in focus mode.

My doubt lies in whether to do it with cross-platform technology or I would find too many problems when accessing native modules of swift sdk, I'm new to mobile any recommendation or help would be good.

Best regards

21 Comments
2024/12/01
15:42 UTC

1

How were your interviews and technical tests? What kind of tasks were assigned to you when you were JRs?

Hello everyone,

Well, that's my doubt. I've been practicing and trying to improve my skills by building a portfolio with some simple apps and I want to know if I'm ready or not to apply to JR roles. Is that difficult to code in live due to the nervousness? What kind of questions did the recruiters ask to you? What type of tasks did you have to do while you were a JR?

Thanks for reading me.

I'll be attentive to any suggestion.

2 Comments
2024/12/01
12:46 UTC

3

Memory issues while processing photo library

Hi, I am trying to process all the images in my photo library. I have the following function:

func analyzeImages(_ inputIDs: [String])
{
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isSynchronous = true
    option.isNetworkAccessAllowed = true
    option.resizeMode = .none
    option.deliveryMode = .highQualityFormat
    let concurrentTasks=1
    let clock = ContinuousClock()

    let duration = clock.measure {
        
        let group = DispatchGroup()
        let sema = DispatchSemaphore(value: concurrentTasks)
        for entry in inputIDs {
            if let asset=PHAsset.fetchAssets(withLocalIdentifiers: [entry], options: nil).firstObject {
                print("analyzing asset: \(entry)")
                group.enter()
                sema.wait()
                manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: option) { (result, info) in
                    if let result = result {
                        Task {
                            print("retrieved asset: \(entry)")
                            let aestheticsRequest = CalculateImageAestheticsScoresRequest()
                            let fingerprintRequest = GenerateImageFeaturePrintRequest()
                            let inputImage = result.cgImage!
                            let handler = ImageRequestHandler(inputImage)
                            let (aesthetics,fingerprint) = try await handler.perform(aestheticsRequest, fingerprintRequest)
// save results
                            print("finished asset: \(entry)")
                            sema.signal()
                            group.leave()
                        }
                    }
                    else {
                        group.leave()
                    }
                    
                }
            }
        }
        group.wait()
    }
    print("analyzeImages: Duration \(duration)")
}

If I pass this an array with <100 or so image IDs, memory grows, but the function completes. When the function completes, all memory is freed. If I pass this with more than 100 images, memory grows and the app crashes. I added the semaphore to ensure that only two images are being processed simultaneously. But, when I use the memory analyzer in Instruments, there are a ton of 35MB IOSurfaces that haven't been freed. I'd have thought that at the end of each Task, the image being analyzed would be freed? Any thoughts/help?

Thx,

7 Comments
2024/12/01
01:25 UTC

1

Where to start with Accessing MacOs Display information. Libraries/frameworks/etc.?

I've been following some swift guides, many focus on the beginner stuff and accessing the UI. I get this and feel like I could make something simple, but for the app I have planned I need to access the OS's display data. Is there a way to get access to the current displays? For example, I need to detect if there is a 2nd or third monitor and then be able to shift the focus to those displays when needed. Is this possible? I haven't exactly made a practical app like this before, especially on MacOS.

I'm not looking to have my hand held, but just a pointer in the right direction, because I can't seem to figure out where to start.

2 Comments
2024/12/01
00:26 UTC

22

Is Combine hard to learn?

Hi guys, in the past few months I’ve tried to learn combine following countless tutorials and reading two books. I learned a huge amount of stuff but still I wouldn’t know how to use it and I don’t fully understand the code I write when following the guided projects in the book I’m reading now. It makes me fell bad about myself because I usually learn stuff much faster.

Is it just me or is Combine actually hard to learn?

55 Comments
2024/11/30
23:25 UTC

0

Need help with CORE NFC write/read / Screen api

Hello, my name is victor im traying to create productivity app, i need to interact with a nfc both to write on it and to read, im a bit lost as i dont know too much about mobile development (im a web developer) and well i would like some advice on these topics
-If I have the application open in the xcode emulator I understand that I need an nfc reader plugged to the computer to be able to read from the emulator?

-Recommendations for nfc readers and writers for computers?I was looking at this website which is where I purchased the NFC https://www.shopnfc.com/es/38-lectores-nfc-usb

-I need the NFC to interact with FamilyControls to block certain applications, if anyone has any advice I would appreciate it.

Thanks

2 Comments
2024/11/30
15:44 UTC

0

SwiftUI not sending firebase analytics!

I’ve integrated another SwiftUI iOS app with Firebase. Have several working correctly. With this one I’ve tried everthing

  • downloaded google.plist to root on project
  • added -Objc to linker flags
  • added argument on lunch for -FIR
  • all data seems to be ok, bundle identifier etc

I don’t have any other ideas. No information is being sent to firebase.

7 Comments
2024/11/30
10:19 UTC

2

Choosing the Right iPhone for iOS Development: New or Second-Hand?

I’m an iOS developer, but I don’t have an iPhone at the moment. I’m considering buying one, either a brand-new model to use as for testing and as my personal phone or a second-hand one just for testing, even if it’s WiFi-only. What would you do in my position?

7 Comments
2024/11/29
23:52 UTC

2

Advice on making an app adaptable to different iOS devices and screen sizes?

Hey everyone,

I’m working on an iOS app, and I’m struggling to make it look good across different devices and screen sizes. I’ve tried a few things, but I’m still running into issues. Here’s what I’ve done so far:

• Used Auto Layout for constraints, but sometimes elements still don’t align properly, especially in landscape mode or on smaller devices like the iPhone SE.

• Tried Stack Views, but they sometimes mess up my spacing when the content grows or shrinks dynamically.

• Used scalable assets (@1x, u/2x, u/3x), but I feel like the UI still doesn’t look sharp on certain devices.

• Played around with Size Classes in Interface Builder, but I’m not sure I’m using them correctly.

Even with all this, the app still doesn’t feel fully responsive, and I want to make sure it looks great on everything from an iPhone SE to the latest iPhone 15 or even iPads.

Has anyone had success with this? Any tips, frameworks, or tools you’d recommend?

Thanks in advance for the help! 🙏

3 Comments
2024/11/29
22:20 UTC

59

SwiftUI is a really good framework (a rant)

So I have been developing on SwiftUI since I started my journey as an iOS dev. I have coded before, some c++ there, some python here, but it has never sticked to me, I have never got past of creating something more than a learning path accepted. I have learned some minimal principles and stuff like if/else, functions etc. (It all happened before I was 16)

At 17 one of my parents friends introduces me to iOS development (UIKit), my father asked him to teach me, to be my mentor in some way. After about 2 weeks, of learning mainly swift language instead of the UIKit, I separated my ways with the mentor, because I was a kid and wanted to do it alone (Also played a lot of video games at the time).

After some time I decided to teach myself SwiftUI, mostly it were courses, one after another I did better and better, the final and the best course I took was hackingwithswift 100 days of SwiftUI. It was really good, because it showed not only separate features, but what SwiftUI can do.

After that I developed my first app (was more like a learning project, this app is still unfinished, but has a lot of potential) Monday Calendar - calendar app, but more simpler and with some add-ons, like dynamic weather fetch for the day (still haven't done it), different backgrounds for events (For example I did a village background that slightly changes every hour displaying the day/night cycle). Looking back, honestly, I did a lot for my first project, I abounded it for now, only because of the messy code I have written learning while creating.

After publishing my app, I decided to do another one called Streakify (I am working on rn). I am not persistent at all, sometimes I can develop a new feature day/night and sometimes a month can pass without doing ANYTHING at all. I have been developing this app almost half a year and 5/6 of this time I didn't do anything. This is an app to create/complete streaks to build consistency.

Both of these apps are 100% fully made by SwiftUI. Why? Learning it, was quite a strait forward experience, previews are very helpful to see the minor changes in the UI. Yeah, I didn't developed another Facebook or Youtube, but still, I pictured the apps in my head and I DID THEM. Of course there was 10000 things that was breaking all the time, Xcode bugs, SwiftUI limitations, but every single time I found my/somebody else's workarounds.

I think, SwiftUI vs UIKit is pointless, both have their uses. I am 100% sure I will use UIKit at some point to add some features, that are not available with SwiftUI. But I kinda also understand the hate both of frameworks have, my theory is that it is mainly induced by fear of losing/not finding a job by choosing the "wrong framework", by learning something for that long for it to be swapped under the rug.

So yeah, this is my journey for now, right now I am a 18 y.o living alone with no job & friends, but have a lot of ambitions to create something special even for oversaturated and not interesting market of mobile apps, this post is mainly about my journey, but also I wanted to say about my experience with SwiftUI.

(Sorry if my grammar sometimes isn't right, I am not a native eng speaker)

12 Comments
2024/11/29
20:41 UTC

3

UI Testing and Selecting a Menu Bar Extra

I am trying to select a menu bar extra to perform ui testing and have been having some trouble selecting the icon to open the menu bar with an accessibility identifier

import AVFoundation
import SwiftUI
import UserNotifications
import SettingsAccess

@main
struct TimeLapzeApp: App {
    @NSApplicationDelegateAdaptor(TimeLapzeAppDelegate.self) var appDelegate
    
    // Top-Level View Model
    @ObservedObject var recorderViewModel = RecorderViewModel.shared
    @ObservedObject var preferencesViewModel = PreferencesViewModel()
    @ObservedObject var onboardingViewModel = OnboardingViewModel()
    
    var body: some Scene {
        // onboarding view (order matters here)
        WindowGroup(id: "onboarding"){
            if !onboardingViewModel.onboarded {
                OnboardingView()
                    .environmentObject(onboardingViewModel).environmentObject(recorderViewModel)
                    .openSettingsAccess()
            }
        }.windowResizability(.contentSize)
            .windowStyle(.hiddenTitleBar)
            .windowToolbarStyle(.unifiedCompact)
        
        // main view
        MenuBarExtra {
            ContentView().environmentObject(recorderViewModel)
        } label: {
            Image(systemName: recorderViewModel.state.description).accessibilityLabel(
                "ScreenTimeLapse MenuBar").accessibilityIdentifier("menuBarApp")
        }.onChange(of: recorderViewModel.state, initial: false){
            Task {
                await recorderViewModel.getDisplayInfo()
            }
        }

        Settings {
            PreferencesView().environmentObject(preferencesViewModel)
            .onAppear{
              NSApplication.shared.activate(ignoringOtherApps: true)
            }
        }
    }
}

/// General purpose `NSApplicationDelegate` and `UNUserNotificationCenterDelegate`
/// Abstracts away custom features unable to be set in `info.plist` or any other config files
class TimeLapzeAppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate
{
    /// Triggered when the application finished launching and receives a launch notification `Notification` on the event
    func applicationDidFinishLaunching(_ notification: Notification) {
        // Hide the dock icon
        if UserDefaults.standard.bool(forKey: "hideIcon") {
            NSApp.setActivationPolicy(.accessory)
        }
        
        // Notifications
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            switch settings.authorizationStatus {
            case .authorized:
                logger.log("Authorized notification settings")
            case .denied:
                logger.log("Denied notification settings")
            case .provisional:
                logger.log("Provisional notifications present")
            case .notDetermined:
                logger.log("Requesting Notification Permissions")
                
                let center = UNUserNotificationCenter.current()
                center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
                    if granted {
                        logger.log("Permissions granted")
                    } else {
                        logger.error("Permissions denied")
                    }
                }
            @unknown default:
                logger.error("Unknown default")
            }
        }
        
        // Setting the notification delegate
        UNUserNotificationCenter.current().delegate = self
    }
    
    /// Creates a custom dock menu with the `play`, `pause` and `settings` buttons in a Spotify-like manner
    /// Not used.
    @MainActor
    func applicationDockMenu(_ sender: NSApplication) -> NSMenu? {
      let menu = NSMenu()
     
      let recorderViewModel = RecorderViewModel.shared
      let disabled = recorderViewModel.recordersDisabled()

      if recorderViewModel.state == .stopped {
        let startItem = NSMenuItem(title: String(localized: "Start Recording"), action: disabled ? nil : #selector(startRecording), keyEquivalent: "")
        startItem.target = self
        menu.addItem(startItem)
      }
     
      if recorderViewModel.state == .recording {
        let pauseItem = NSMenuItem(title: String(localized: "Pause Recording"), action: disabled ? nil : #selector(pauseRecording), keyEquivalent: "")
        pauseItem.target = self
        menu.addItem(pauseItem)
      }

      if recorderViewModel.state == .paused {
        let pauseItem = NSMenuItem(title: String(localized: "Resume Recording"), action: disabled ? nil : #selector(resumeRecording), keyEquivalent: "")
        pauseItem.target = self
        menu.addItem(pauseItem)
      }
      
      if recorderViewModel.state == .recording || recorderViewModel.state == .paused {
        let stopAndSave = NSMenuItem(title: String(localized: "Exit and Save Recording"), action: disabled ? nil : #selector(pauseRecording), keyEquivalent: "")
        stopAndSave.target = self
        menu.addItem(stopAndSave)
      }
      
      return menu
    }

    @objc func startRecording() {
        RecorderViewModel.shared.startRecording()
    }
    
    @objc func pauseRecording() {
        RecorderViewModel.shared.pauseRecording()
    }
  
    @objc func resumeRecording() {
      RecorderViewModel.shared.resumeRecording()
    }
  
    @objc func stopRecording() {
      RecorderViewModel.shared.saveRecordings()
    }

    /// Handles when a user clicks on a notification uses the `response.notification.request.content.userInfo` to read attached data to open the `fileURL` key
    func userNotificationCenter(
        _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        
        // opens the file just saved
        if let filePath = response.notification.request.content.userInfo["fileURL"] as? String,
           let fileURL = URL(string: filePath)
        {
            workspace.open(fileURL)
        }
        
        // completion handler things: `nil` in this case
        completionHandler()
    }
}

I have been trying to select the menu bar extra in the following way:



//
//  TimeLapzeUITests.swift
//  TimeLapzeUITests
//
//  Created by William Kaiser on 11/21/24.
//

import XCTest

final class TimeLapzeUITests: XCTestCase {

    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false

        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    @MainActor
    func testExample() throws {
        // UI tests must launch the application that they test.
      let app = XCUIApplication()
      app.launch()
      
      let menuBarExtra = app.menuItems["menuBarApp"]
      
      print(app)
      print(app)
      
      print("Windows------------")
      print(app.windows.allElementsBoundByAccessibilityElement)
      print("Getting the Menu bars------------")
      print(app.menuBars.allElementsBoundByAccessibilityElement)
      print("Menu Buttons------------")
      print(app.menuButtons.allElementsBoundByAccessibilityElement)
      print("Menu bar items------------")
      print(app.menuBarItems.allElementsBoundByAccessibilityElement)
      print("menus------------")
      print(app.menus.allElementsBoundByAccessibilityElement)
      print("browsers------------")
      print(app.browsers.allElementsBoundByAccessibilityElement)
      print("menu buttons------------")

      print(app.menuButtons.allElementsBoundByAccessibilityElement)
      print(app.alerts.allElementsBoundByAccessibilityElement)
      
      for item in app.menuBars.allElementsBoundByAccessibilityElement {
          print(item)
          if item.identifier == "menuBarApp" {
            XCTAssertTrue(false, "Found")
          }
      }
      
      for item in app.menuBarItems.allElementsBoundByAccessibilityElement {
        print(item)
        if item.identifier == "menuBarApp" {
          XCTAssertTrue(false, "Found")
        }
      }
      
      for element in app.menuBarItems.allElementsBoundByAccessibilityElement {
          print("Element: \(element), Identifier: \(element.identifier), Title: \(element.label)")
      }
      for element in app.menuBars.allElementsBoundByAccessibilityElement {
          print("Element: \(element), Identifier: \(element.identifier), Title: \(element.label)")
      }
        XCTAssertTrue(menuBarExtra.waitForExistence(timeout: 10), "Menu bar extra did not appear")
      
      

    }
}

I would appreciate anyone's help with this!

1 Comment
2024/11/29
18:56 UTC

7

Performance Question: Swift on M1 Max/macOS vs VB.NET on i9-9900K/Windows

I have an application that I have written in VB.NET that I run on my i9-9900K/Windows 11 machine. I’ve recently been looking at upgrading my machine to get better performance (don’t judge… it’s a good excuse for me to get a new toy). In the midst of shopping for my new AMD 9950X system, Apple announce the new M4 Mac Minis, so I thought I’d consider one of those instead. Looking at the performance benchmarks (Geekbench 6, Cinebench R23 & R24, single core scores), it looked like the M4 Pro in the Mac Mini should perform better than even the 9950X. But, before I committed I thought I’d try my program on my M1 Max Macbook Pro (latest versions of OS and Xcode), so I used ChatGPT and Claude to help me do a straight conversion of my VB.NET code to Swift.

The conversion of the functional parts of the program was pretty straightforward – nothing special needed to be done, just convert to the different language. Same functions. Same function calls and program logic. I had to do some work to get the UI working, but I finally got the program to run on the Macbook Pro and give me the results so I could compare to the i9/Windows system.

So, my question… again looking at synthetic benchmarks, my M1 Max should be at least 10% faster than the i9-9900K (e.g., Geekbench 6: i9 1800’ish vs M1 Max 2000’ish). However, when I ran my program, the Macbook Pro was actually about 5% slower. So, have any of you done a similar thing (convert an existing application on Windows to a Swift equivalent implementation) and seen similar results? I’ve been using Claude to identify possible optimizations for the Swift version to improve performance, but I should be able to do similar things on the Windows app to also improve that one. I expected differences in UI coding, but once the program is running and it drops into the primary function, both applications are running functionally the same. Any ideas why I’m seeing such a drop in performance in the Swift code? Is that just the way it is?

17 Comments
2024/11/29
15:54 UTC

2

SwiftUI .onTapGesture works with Text but not AsyncImage

I have a View like this:


struct SelectionView: View {
    
    @ObservedObject var viewModel: ViewModel
    
    let rows = [GridItem(), GridItem(), GridItem()]
    
    init(_ viewModel: ViewModel) {
        self.viewModel = viewModel
        
    }
    
    var body: some View {
        ScrollView(.vertical) {
            LazyVGrid(columns: rows) {
                ForEach(viewModel.priorityWildlife, id: \.id) { wildlife in
                    // ...
                }
            }
        }
    }
}

When I double-tap the Text View for each item below, the correct item is selected:

var body: some View {
    ScrollView(.vertical) {
        LazyVGrid(columns: rows) {
            ForEach(viewModel.priorityWildlife, id: \.id) { wildlife in
                Text("\(wildlife.commonName)")
                    .frame(width: 120, height: 180)
                    .onTapGesture(count: 2) {
                        viewModel.selectWildlife(wildlife.taxonID)
                    }
                    .clipShape(.rect(cornerRadius: 16))
                    .background(Color.red)
            }
        }
    }
}

However, when I double-tap the AsyncImage View for each item below, the correct item is NOT selected:

var body: some View {
    ScrollView(.vertical) {
        LazyVGrid(columns: rows) {
            ForEach(viewModel.priorityWildlife, id: \.id) { wildlife in
                AsyncImage(url: URL(string: wildlife.photoURL))
                    .frame(width: 120, height: 180)
                    .onTapGesture(count: 2) {
                        viewModel.selectWildlife(wildlife.taxonID)
                    }
                    .clipShape(.rect(cornerRadius: 16))
                    .background(Color.red)
            }
        }
    }
}

Any idea what’s going on here and how I can fix it so that the double-tap on AsyncImage will select the correct image?

Thanks.

3 Comments
2024/11/29
06:04 UTC

Back To Top