Post

Replies

Boosts

Views

Activity

Reply to Reducing storage of similar PNGs by compressing them into a video and retrieving them losslessly--possibility or dumb idea?
You again! That's three for three now; thank you for always responding to me. What sort of images are they? Are they continuous-tone, or paletted? They're regular PNG images, and they have to be PNG because JPEGs don't support alpha and HEVCs are just too computationally expensive for my purposes. I have had good experience using JXL, which has a lossless mode. Its lossy mode with a high quality setting could also be useful. Assuming you're referring to JPEG-XL, it's likely not going to work as speedily with UIImage, which is my main use case. Are you suggesting that when I should convert to JXL when I need to minimize storage and then convert back to PNG? Re video codecs, you should investigate what people are using for screen recording. Would you mind elaborating on that? I don't see your point
Topic: Media Technologies SubTopic: Video Tags:
Jun ’24
Reply to Is the issue of code-theft via decompilation or reverse engineering common for Swift iOS apps? And can I protect a small portion of my code?
[quote='791387022, CMDdev, /thread/757255?answerId=791387022#791387022, /profile/CMDdev'] This is obfuscation - one can reverse this mechanism and obtain your asset decryption key depending on how this works. So I wouldn't say they are "protected", but rather "better hidden". [/quote] Even if I store it in the enclave? My current system creates a unique key for each user-device combination, and uses that to encrypt assets at rest. The enclave key is said to never leave the enclave, so I'm convinced that this is the best I can do within the confines of the framework and platform. If someone can pull assets from memory then no amount of clever encryption will help unless the memory itself is encrypted, but this is one of the few security features that Apple hasn't implemented. But I think you should also focus on branding your product so that even if clones / alternatives appear, yours will still be the best one, the one that people choose. This is a good suggestion and I hope to succeed at this, but having two protections is better than one. Your suggestion is based on the idea that apps can have a good first-mover's advantage, and I agree, but I've heard horror stories of apps being cloned within moments of release, and the cloner has an advantage since they're just going to leap-frog off my work.
Topic: Privacy & Security SubTopic: General Tags:
Jun ’24
Reply to Is the issue of code-theft via decompilation or reverse engineering common for Swift iOS apps? And can I protect a small portion of my code?
Thank you both for responding! Since most of my questions on the forum go unanswered, I feel spoiled just by having two responders. [quote='791275022, CMDdev, /thread/757255?answerId=791275022#791275022, /profile/CMDdev'] Yes, though some class / method names will still be visible. [/quote] Is there a way to tell which ones will be? [quote='791275022, CMDdev, /thread/757255?answerId=791275022#791275022, /profile/CMDdev'] Also, the IPA is not encrypted on your iPhone, but using such methods was needed to get the IPA, as you couldn't download iOS apps on devices other than iPhones. [/quote] Sorry, I meant decrypted binary. Basically, I read up on how people obtain and tweak IPAs, and the process seems to be to: Obtain an IPA via jailbroken iDevice. While the IPA is accessible (so don't store secrets in there), the compiled app binary is decrypted Start the app on the iDevice, which loads the decrypted app into memory Using various tools, capture the decrypted app from memory Tweak and repackage [quote='791318022, endecotp, /thread/757255?answerId=791318022#791318022, /profile/endecotp'] Of more concern is extracting non-code, for example the expensively-designed graphical or sound resources in a good game. [/quote] I encrypt all assets at rest, but decrypt them to load into memory when needed. I think I'm protected by this process, but If there's a way to pull the assets from memory nothing I do would help. Is this assumption true? P.S. There seems to be an issue with how quotes are handled by this forum; multiple quotes can lead to misaligned formatting
Topic: Privacy & Security SubTopic: General Tags:
Jun ’24
Reply to [iOS 17.4, XCode 15.3] Previously working NWConnection for peer-to-peer connection now permanently stuck on "Preparing"
After restarting my Mac and the devices, things seem to be working fine (with no change to the code) Does anyone else experience strange, transient behavior on update day, especially before restarting? This isn't the first time this happened to me Also, if there's a janitor on this board, would you kindly delete this thread?
Mar ’24
Reply to Wired data transfer between an app on two iOS/iPadOS devices--Possible or pipe dream?
tl;dr - Connect the devices and use the Network framework as usual. So I was figuring out another problem when I stumbled upon this thread: https://forums.developer.apple.com/forums/thread/658393 In it, Quinn demonstrates how to use the Network framework over pure USB (no ethernet dongle) to connect to a Mac. It turns out this also applies to two iOS devices (and maybe beyond). So far I've only tested it with two devices with Lightning ports connected by a Lightning-to-USB adaptor (no power attached) plus a USB-to-Lightning cable. Code to reproduce: class NetworkManager: ObservableObject { static var shared = NetworkManager() @Published private(set) var text = "" @Published private(set) var listenerQ: NWListener? @Published private(set) var browserQ: NWBrowser? var isListenerStarted: Bool { listenerQ != nil } var isBrowserStarted: Bool { browserQ != nil } func log(_ string: String) { print(string) text.append(string + "\n") } func startBrowser() -> NWBrowser { let browser = NWBrowser(for: .bonjour(type: "_customService._tcp", domain: nil), using: .tcp) browser.stateUpdateHandler = { self.log("Browser did change state, new: \($0)") } browser.browseResultsChangedHandler = { self.log("Browser did change results, new: \($0) \($1)") } browser.start(queue: .main) return browser } func stopBrowser(_ browser: NWBrowser) { log("Browser will stop") browser.stateUpdateHandler = nil browser.cancel() } func startStopBrowser() { if let browser = browserQ { browserQ = nil stopBrowser(browser) } else { browserQ = startBrowser() } } func startListener() -> NWListener { print("Listener will start") let listener = try! NWListener(using: .tcp) listener.service = .init(type: "_customService._tcp") listener.stateUpdateHandler = { print("Listener did change state, new: \(($0))") } listener.newConnectionHandler = { connection in let remotePeer = connection.currentPath?.remoteEndpoint self.log("Listener did receive connection, from: \(remotePeer)") connection.cancel() } listener.start(queue: .main) return listener } func stopListener(_ listener: NWListener) { log("Listener will stop") listener.stateUpdateHandler = nil listener.cancel() } func startStopListener() { if let listener = self.listenerQ { self.listenerQ = nil self.stopListener(listener) } else { self.listenerQ = self.startListener() } } } struct ContentView: View { @ObservedObject var netMan = networkManager var body: some View { VStack { HStack { Button("\(netMan.isListenerStarted ? "Stop" : "Start") listener") { netMan.startStopListener() } Button("\(netMan.isBrowserStarted ? "Stop" : "Start") browser") { netMan.startStopBrowser() } } .padding() Text("Log") .font(.title.bold()) ScrollView { Text(netMan.text) } } .padding() } }
Topic: App & System Services SubTopic: Hardware Tags:
Feb ’24
Reply to Wired data transfer between an app on two iOS/iPadOS devices--Possible or pipe dream?
Reposting as reply since Quinn said that comments are lower-visibility to him Hi Quinn, I get what you're saying, but that would mean my users would have to get two USB dongles and an ethernet cable as opposed to just using the USB cable they already own. This is complicated by the fact that devices with a Lightning port need to attach the USB dongle to a Lightning-to-USB adaptor. At this point I'm not looking for ways to implement a USB-to-USB connection using just a single USB cable--I just want to know if the system(s) involved permit this sort of direct connection
Topic: App & System Services SubTopic: Hardware Tags:
Feb ’24
Reply to Is the code in 'Building a custom peer-to-peer protocol' insecure?
I was away but I finally filed a report: FB13589481 Since it seems the code that was touted as secure is questionable at best, are there any alternatives? To get around some issues I'm attaching passwords to the Bonjour context and using a single, shared PSK (not stored as a string) to secure connections, but this is just a stopgap measure. Also, I reposted my comment to your reply to my other thread on wired data transfer between devices.. I'd be grateful if you would be kind enough to take a second look at my thread.
Topic: App & System Services SubTopic: Core OS Tags:
Feb ’24
Reply to ScrollView behaves as though Sheet is always expanded when mutiple detents enabled
One solution is to stick everything in a TabView (with the .page style) struct Playground: View { @State private var detent = PresentationDetent.fraction(1/3) @State private var isSheetPresented = true var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() TabView { ScrollView { VStack(spacing: 0) { ForEach(0...10, id: \.self) { e in Rectangle() .fill(.white) .frame(height: 50) .overlay { Text("\(e)") } } } } } .tabViewStyle(.page(indexDisplayMode: .never)) } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’24
Reply to Scrolling sticker browser on a Messages App sheet causes sheet to move
One solution is to stick everything in a SwiftUI TabView (with the .page style). You should be able to use either MSStickerBrowserView or MSStickerViews wrapped in a UIViewRepresentable struct Playground: View { @State private var isSheetPresented = true @State private var detent = PresentationDetent.fraction(1/3) var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() TabView { ScrollView { VStack(spacing: 0) { ForEach(0...100, id: \.self) { e in Rectangle() .fill(.white) .border(.gray, width: 0.3) .frame(width: 50) .overlay { Text(e.description) } } } } } .tabViewStyle(.page(indexDisplayMode: .never)) } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’24
Reply to Scrolling sticker browser on a Messages App sheet causes sheet to move
I'm glad I added the SwiftUI tag, because I replicated the exact same issue using pure SwiftUI Unfortunately there doesn't seem to be anything published on how to fix the issue, even in pure SwiftUI--the ScrollView behaves as though the sheet is constantly expanded and transfers the drag gesture to the sheet when scrolled to the top (i.e. when first displayed), causing the user to move the sheet when intending to scroll in any direction. I can slap a band-aid on this by having ScrollViewReader scroll down a tiny bit upon appearing, but this is far from ideal since the issue re-emerges after the user has scrolled to the top. This is complicated by the fact that you can't disable detents in your Messages App. A workaround would be to abandon ScrollView (and MSStickerBrowserView) in favor of TabView with pages. struct Playground: View { @State private var detent = PresentationDetent.fraction(1/3) @State private var isSheetPresented = true var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() ScrollView { ScrollViewReader { scrollProxy in VStack(spacing: 0) { ForEach(0...10, id: \.self) { i in Rectangle() .fill(.white) .frame(height: 50) .id(i) .overlay { Text(i.description) } } } } } .frame(height: 200) .padding() } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Jan ’24
Reply to Reducing storage of similar PNGs by compressing them into a video and retrieving them losslessly--possibility or dumb idea?
You again! That's three for three now; thank you for always responding to me. What sort of images are they? Are they continuous-tone, or paletted? They're regular PNG images, and they have to be PNG because JPEGs don't support alpha and HEVCs are just too computationally expensive for my purposes. I have had good experience using JXL, which has a lossless mode. Its lossy mode with a high quality setting could also be useful. Assuming you're referring to JPEG-XL, it's likely not going to work as speedily with UIImage, which is my main use case. Are you suggesting that when I should convert to JXL when I need to minimize storage and then convert back to PNG? Re video codecs, you should investigate what people are using for screen recording. Would you mind elaborating on that? I don't see your point
Topic: Media Technologies SubTopic: Video Tags:
Replies
Boosts
Views
Activity
Jun ’24
Reply to Is the issue of code-theft via decompilation or reverse engineering common for Swift iOS apps? And can I protect a small portion of my code?
[quote='791387022, CMDdev, /thread/757255?answerId=791387022#791387022, /profile/CMDdev'] This is obfuscation - one can reverse this mechanism and obtain your asset decryption key depending on how this works. So I wouldn't say they are "protected", but rather "better hidden". [/quote] Even if I store it in the enclave? My current system creates a unique key for each user-device combination, and uses that to encrypt assets at rest. The enclave key is said to never leave the enclave, so I'm convinced that this is the best I can do within the confines of the framework and platform. If someone can pull assets from memory then no amount of clever encryption will help unless the memory itself is encrypted, but this is one of the few security features that Apple hasn't implemented. But I think you should also focus on branding your product so that even if clones / alternatives appear, yours will still be the best one, the one that people choose. This is a good suggestion and I hope to succeed at this, but having two protections is better than one. Your suggestion is based on the idea that apps can have a good first-mover's advantage, and I agree, but I've heard horror stories of apps being cloned within moments of release, and the cloner has an advantage since they're just going to leap-frog off my work.
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jun ’24
Reply to Is the issue of code-theft via decompilation or reverse engineering common for Swift iOS apps? And can I protect a small portion of my code?
Thank you both for responding! Since most of my questions on the forum go unanswered, I feel spoiled just by having two responders. [quote='791275022, CMDdev, /thread/757255?answerId=791275022#791275022, /profile/CMDdev'] Yes, though some class / method names will still be visible. [/quote] Is there a way to tell which ones will be? [quote='791275022, CMDdev, /thread/757255?answerId=791275022#791275022, /profile/CMDdev'] Also, the IPA is not encrypted on your iPhone, but using such methods was needed to get the IPA, as you couldn't download iOS apps on devices other than iPhones. [/quote] Sorry, I meant decrypted binary. Basically, I read up on how people obtain and tweak IPAs, and the process seems to be to: Obtain an IPA via jailbroken iDevice. While the IPA is accessible (so don't store secrets in there), the compiled app binary is decrypted Start the app on the iDevice, which loads the decrypted app into memory Using various tools, capture the decrypted app from memory Tweak and repackage [quote='791318022, endecotp, /thread/757255?answerId=791318022#791318022, /profile/endecotp'] Of more concern is extracting non-code, for example the expensively-designed graphical or sound resources in a good game. [/quote] I encrypt all assets at rest, but decrypt them to load into memory when needed. I think I'm protected by this process, but If there's a way to pull the assets from memory nothing I do would help. Is this assumption true? P.S. There seems to be an issue with how quotes are handled by this forum; multiple quotes can lead to misaligned formatting
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jun ’24
Reply to [iOS 17.4, XCode 15.3] Previously working NWConnection for peer-to-peer connection now permanently stuck on "Preparing"
After restarting my Mac and the devices, things seem to be working fine (with no change to the code) Does anyone else experience strange, transient behavior on update day, especially before restarting? This isn't the first time this happened to me Also, if there's a janitor on this board, would you kindly delete this thread?
Replies
Boosts
Views
Activity
Mar ’24
Reply to Interaction between iPhone and Mac/PC via USB - How?
For future reference, the general solution above also applies to two iOS/iPadOS devices, even if they both have Lightning ports (and you don't even need to supply power to the Lightning-to-USB adaptor!) https://developer.apple.com/forums/thread/744559 Anyone have any hints on how to get a Windows PC to connect to a Bonjour listener/server?
Topic: App & System Services SubTopic: Drivers Tags:
Replies
Boosts
Views
Activity
Feb ’24
Reply to Wired data transfer between an app on two iOS/iPadOS devices--Possible or pipe dream?
tl;dr - Connect the devices and use the Network framework as usual. So I was figuring out another problem when I stumbled upon this thread: https://forums.developer.apple.com/forums/thread/658393 In it, Quinn demonstrates how to use the Network framework over pure USB (no ethernet dongle) to connect to a Mac. It turns out this also applies to two iOS devices (and maybe beyond). So far I've only tested it with two devices with Lightning ports connected by a Lightning-to-USB adaptor (no power attached) plus a USB-to-Lightning cable. Code to reproduce: class NetworkManager: ObservableObject { static var shared = NetworkManager() @Published private(set) var text = "" @Published private(set) var listenerQ: NWListener? @Published private(set) var browserQ: NWBrowser? var isListenerStarted: Bool { listenerQ != nil } var isBrowserStarted: Bool { browserQ != nil } func log(_ string: String) { print(string) text.append(string + "\n") } func startBrowser() -> NWBrowser { let browser = NWBrowser(for: .bonjour(type: "_customService._tcp", domain: nil), using: .tcp) browser.stateUpdateHandler = { self.log("Browser did change state, new: \($0)") } browser.browseResultsChangedHandler = { self.log("Browser did change results, new: \($0) \($1)") } browser.start(queue: .main) return browser } func stopBrowser(_ browser: NWBrowser) { log("Browser will stop") browser.stateUpdateHandler = nil browser.cancel() } func startStopBrowser() { if let browser = browserQ { browserQ = nil stopBrowser(browser) } else { browserQ = startBrowser() } } func startListener() -> NWListener { print("Listener will start") let listener = try! NWListener(using: .tcp) listener.service = .init(type: "_customService._tcp") listener.stateUpdateHandler = { print("Listener did change state, new: \(($0))") } listener.newConnectionHandler = { connection in let remotePeer = connection.currentPath?.remoteEndpoint self.log("Listener did receive connection, from: \(remotePeer)") connection.cancel() } listener.start(queue: .main) return listener } func stopListener(_ listener: NWListener) { log("Listener will stop") listener.stateUpdateHandler = nil listener.cancel() } func startStopListener() { if let listener = self.listenerQ { self.listenerQ = nil self.stopListener(listener) } else { self.listenerQ = self.startListener() } } } struct ContentView: View { @ObservedObject var netMan = networkManager var body: some View { VStack { HStack { Button("\(netMan.isListenerStarted ? "Stop" : "Start") listener") { netMan.startStopListener() } Button("\(netMan.isBrowserStarted ? "Stop" : "Start") browser") { netMan.startStopBrowser() } } .padding() Text("Log") .font(.title.bold()) ScrollView { Text(netMan.text) } } .padding() } }
Topic: App & System Services SubTopic: Hardware Tags:
Replies
Boosts
Views
Activity
Feb ’24
Reply to Wired data transfer between an app on two iOS/iPadOS devices--Possible or pipe dream?
Reposting as reply since Quinn said that comments are lower-visibility to him Hi Quinn, I get what you're saying, but that would mean my users would have to get two USB dongles and an ethernet cable as opposed to just using the USB cable they already own. This is complicated by the fact that devices with a Lightning port need to attach the USB dongle to a Lightning-to-USB adaptor. At this point I'm not looking for ways to implement a USB-to-USB connection using just a single USB cable--I just want to know if the system(s) involved permit this sort of direct connection
Topic: App & System Services SubTopic: Hardware Tags:
Replies
Boosts
Views
Activity
Feb ’24
Reply to Is the code in 'Building a custom peer-to-peer protocol' insecure?
I was away but I finally filed a report: FB13589481 Since it seems the code that was touted as secure is questionable at best, are there any alternatives? To get around some issues I'm attaching passwords to the Bonjour context and using a single, shared PSK (not stored as a string) to secure connections, but this is just a stopgap measure. Also, I reposted my comment to your reply to my other thread on wired data transfer between devices.. I'd be grateful if you would be kind enough to take a second look at my thread.
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Feb ’24
Reply to ScrollView behaves as though Sheet is always expanded when mutiple detents enabled
One solution is to stick everything in a TabView (with the .page style) struct Playground: View { @State private var detent = PresentationDetent.fraction(1/3) @State private var isSheetPresented = true var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() TabView { ScrollView { VStack(spacing: 0) { ForEach(0...10, id: \.self) { e in Rectangle() .fill(.white) .frame(height: 50) .overlay { Text("\(e)") } } } } } .tabViewStyle(.page(indexDisplayMode: .never)) } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jan ’24
Reply to Scrolling sticker browser on a Messages App sheet causes sheet to move
One solution is to stick everything in a SwiftUI TabView (with the .page style). You should be able to use either MSStickerBrowserView or MSStickerViews wrapped in a UIViewRepresentable struct Playground: View { @State private var isSheetPresented = true @State private var detent = PresentationDetent.fraction(1/3) var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() TabView { ScrollView { VStack(spacing: 0) { ForEach(0...100, id: \.self) { e in Rectangle() .fill(.white) .border(.gray, width: 0.3) .frame(width: 50) .overlay { Text(e.description) } } } } } .tabViewStyle(.page(indexDisplayMode: .never)) } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Jan ’24
Reply to Scrolling sticker browser on a Messages App sheet causes sheet to move
I'm glad I added the SwiftUI tag, because I replicated the exact same issue using pure SwiftUI Unfortunately there doesn't seem to be anything published on how to fix the issue, even in pure SwiftUI--the ScrollView behaves as though the sheet is constantly expanded and transfers the drag gesture to the sheet when scrolled to the top (i.e. when first displayed), causing the user to move the sheet when intending to scroll in any direction. I can slap a band-aid on this by having ScrollViewReader scroll down a tiny bit upon appearing, but this is far from ideal since the issue re-emerges after the user has scrolled to the top. This is complicated by the fact that you can't disable detents in your Messages App. A workaround would be to abandon ScrollView (and MSStickerBrowserView) in favor of TabView with pages. struct Playground: View { @State private var detent = PresentationDetent.fraction(1/3) @State private var isSheetPresented = true var body: some View { Rectangle() .fill(Color(.systemGray5)) .sheet(isPresented: $isSheetPresented) { VStack { Text("ScrollView-in-Sheet Experiment") .padding() ScrollView { ScrollViewReader { scrollProxy in VStack(spacing: 0) { ForEach(0...10, id: \.self) { i in Rectangle() .fill(.white) .frame(height: 50) .id(i) .overlay { Text(i.description) } } } } } .frame(height: 200) .padding() } .background { Color(.systemGray6) } .presentationDetents([.large, .fraction(1/3)], selection: $detent) } } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Jan ’24