Post

Replies

Boosts

Views

Activity

Reply to Alternative option to initial onChange callback for EmptyView
I changed my approach to use ViewModifiers as which allows me to use existing view for callback: @MainActor struct AsyncStateModifier<T: Equatable>: ViewModifier { let input: T let action: (T) async -> Void let queue: AsyncActionQueue func body(content: Content) -> some View { return content .onChange(of: input, initial: true) { old, new in queue.process(action: action, with: new) } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to Check whether app is built in debug or release mode
Thanks for the replay @DTS Engineer. You are right on my requirement, currently I am looking for iOS but I would be happy with a solution that works across apple platforms as well. If so, to what end? To answer your query on why I want to detect debug build I won't be able to share my exact use-case but I will share a parallel use-case that currently Apple uses: Currently Apple allows developers to send push notifications to iOS with APNS. From what I understand, APNS exposes sandbox and production environments which are controlled with aps-environment entitlement. Since, Apple controls the tooling side of iOS development, they can inject entitlement based on the provisioning profile. I want to achieve something similar to this where the REST API domain used by my framework is decided based on either provisioning profile or build type. A lot of the time it’s not the build configuration that matters, it’s the way that the app was signed. Or the way that’s it’s run (from Xcode or like a user would). And those questions have different answers. I think more appropriate solution for me will be deciding based on the way app was signed, something like what Apple does for APNS. I did look into it but was unable to find any way to parse the included provisioning profile. Would appreciate any help with this.
3w
Reply to Check whether app is built in debug or release mode
Thanks @DTS Engineer for the detailed snippet. The usage of get-task-allow entitlement gave me idea for updating my previous parsing entitlement approach and I came up with this: struct MobileProvision: Codable { static let current: MobileProvision = { let profileExtension = "mobileprovision" guard let profilePath = Bundle.main.path(forResource: "embedded", ofType: profileExtension), let profileString = try? String(contentsOfFile: profilePath, encoding: .isoLatin1), case let scanner = Scanner(string: profileString), scanner.scanUpToString("<plist") != nil, let extractedPlist = scanner.scanUpToString("</plist>"), let plist = extractedPlist.appending("</plist>").data(using: .isoLatin1) else { return .simulatorDefault() } let decoder = PropertyListDecoder() do { return try decoder.decode(MobileProvision.self, from: plist) } catch { return .simulatorDefault() } }() static func simulatorDefault() -> Self { return Self(entitlements: Entitlements(isDebuggable: true, apsEnvironment: .development)) } let entitlements: Entitlements enum CodingKeys: String, CodingKey { case entitlements = "Entitlements" } struct Entitlements: Codable { let isDebuggable: Bool let apsEnvironment: APSEnvironment enum APSEnvironment: String, Codable { case development, production } enum CodingKeys: String, CodingKey { case isDebuggable = "get-task-allow" case apsEnvironment = "aps-environment" } } } This snippet has the same drawback as your snippet in the sense that it will not work on simulators (which is an acceptable compromise for me), but this works with tvOS as well (which is more priority for me than macOS). Do you think any drawback for this approach? Personally the one drawback I see is this relies on un-documented provisioning profile structure which might break in future if Apple changes it but I doubt that will ever happen. I will try to compare performance of both approaches and come up with some numbers.
2w
Reply to Check whether app is built in debug or release mode
Thanks for pointing out these issues, I have modified my snippet according to your suggestion: struct MobileProvision: Codable { static let current: MobileProvision = { guard let profilePath = Bundle.main.url( forResource: "embedded", withExtension: "mobileprovision" ), let profileData = try? Data(contentsOf: profilePath), let statrtRange = profileData.firstRange( of: "<plist".data(using: .isoLatin1)! ), let endRange = profileData.range( of: "</plist>".data(using: .isoLatin1)!, in: statrtRange.endIndex..<profileData.endIndex ) else { return .`default`() } let decoder = PropertyListDecoder() do { let plist = profileData.subdata( in: statrtRange.startIndex..<endRange.endIndex ) return try decoder.decode(MobileProvision.self, from: plist) } catch { return .`default`() } }() static func `default`() -> Self { #if targetEnvironment(simulator) return Self(entitlements: Entitlements(isDebuggable: true, apsEnvironment: .development)) #else return Self(entitlements: Entitlements(isDebuggable: false, apsEnvironment: .production)) #endif } let entitlements: Entitlements enum CodingKeys: String, CodingKey { case entitlements = "Entitlements" } struct Entitlements: Codable { let isDebuggable: Bool let apsEnvironment: APSEnvironment enum APSEnvironment: String, Codable { case development, production } enum CodingKeys: String, CodingKey { case isDebuggable = "get-task-allow" case apsEnvironment = "aps-environment" } } }
3d