Post

Replies

Boosts

Views

Activity

SwiftUI confirmation dialog shouldn't allow background touch; UIKit popover didn't
To me this is a clear bug (and I submitted it as one: FB11813464), unless there's something I'm missing? When the confirmationDialog is showing on an iPad, and you click outside it, the confirmationDialog disappears, as it should. This is the same behavior as the popover in UIKit; the outside-click acts in lieu of a Cancel button when you're on an iPad. HOWEVER, the outside-click also triggers behaviors elsewhere on the screen, for ex if the place you click has a Button, or an onTapGesture listener. As demonstrated in this picture, when the confirmationDialog is showing, and you click on this button, the confirmationDialog disappears, which is correct, but the print action also runs, which shouldn't. I’m running Xcode 14.1, targeting iOS 16.1, and running on an iPad 10th gen simulator.
0
0
844
Nov ’22
Does XCUIElement represent a query rather than a specific element?
This example is pretty contrived, but it illustrates the behavior. I know you can use .accessibilityIdentifier to uniquely identify a control, but I'm just trying to better understand the interplay between XCUIElement and XCUIElementQuery. Let's say you have an app like this: import SwiftUI struct ContentView: View { @State var showRedButton = true var body: some View { VStack { if showRedButton { Button("Click me") { showRedButton = false } .background(.red) } else { HStack { Button("Click me") { showRedButton = true } .background(.blue) Spacer() } } } } } And you are UI testing like this: import XCTest final class MyAppUITests: XCTestCase { func testExample() throws { let app = XCUIApplication() app.launch() print(app.debugDescription) // At this point, the Element subtree shows // a single Button: // Button, 0x14e40d290, // {{162.3, 418.3}, {65.3, 20.3}}, label: 'Click me' let btn = app.buttons["Click me"] // This tap makes the red button disappear // and shows the blue button btn.tap() print(app.debugDescription) // Now, the Element subtree shows a single Button // that has a different ID // and different x-y coordinates: // Button, 0x15dc12e50, // {{0.0, 418.3}, {65.3, 20.3}}, label: 'Click me' // This tap now works on the blue button?? // Without requerying? btn.tap() print(app.debugDescription) // The red button reappears, // but with a different ID (which makes sense). } } Why does the second tap work, even though it's a different control? This must mean that SwiftUI is automatically re-running the XCUIElementQuery to find the button that matches "Click me". Apparently the variable btn isn't linked to the control with the ID 0x14e40d290. Does this mean XCUIElement actually represents an XCUIElementQuery? I expected it to require me to explicitly re-run the query like this, btn = app.buttons["Click me"] prior to running the 2nd tap, or the tap would've said that btn was no longer available. The final print of the Element subtree shows that the red button has a different ID now. This makes sense, because when SwiftUI redraws the red button, it's not the same instance as the last time. This is explained well in the WWDC videos. Nevertheless, at the moment I connected the variable "btn" to the control, I thought there was a tighter affiliation. Maybe UI testing has to behave this way because SwiftUI redraws controls so frequently?
0
0
729
Dec ’22
BGTask running while iPad is awake--how is this possible?
We have been using the BGTask (specifically a BGProcessingTask) reliably for the last couple of years for our app. Up until now they wake up automatically while the screen is off, the iPad is plugged in, and the app is running (that is, in the background), but never while the screen is on (that is, never when the scenePhase == .active). For the last month or so, I've noticed that they are triggering now while the screen is displayed. How is this possible??? Did something change with a recent version of iOS? It's violating Apple's own documentation, which describes the BGProcessingTask as: "A time-consuming processing task that runs while the app is in the background."
2
0
791
Mar ’24
PDFKit & WebKit problem with JPEG2000 in PDF
We have some PDFs that were created with JPEG2000 images in them (*.jp2 files). Using PDFKit, and also WebKit, the images in these PDFs in some cases don't display at all, and in others cases appear badly warped. You can view the PDF using either Adobe Reader, or the Chrome app, and the images appear fine, so it's clearly not an issue of a corrupt PDF. Also, 3rd-party commercial iOS controls like PSPDF and FoxIt display the images fine, so it's clearly an issue with PDFKit and WebKit. Any known workarounds?
1
0
1.3k
Jul ’22
TLS authentication with *.pfx certificate on iOS from MDM
We are connecting to a web service that requires a certificate from a *.pfx. It works fine when the *.pfx is included in the app bundle and extracted from there, as mentioned in this discussion in thread #77694. The problem is, each device will have a unique certificate that will be pushed to it from an MDM; we don't have a single generic certificate that we can include in the bundle for all devices to use. For testing, we dragged the *.pfx certificate onto Settings, and it appears under "Configuration Profile", as shown in the attached picture. Questions: Is "Configuration Profile" the iOS equivalent of the Mac Keychain? When an MDM pushes a *.pfx certificate onto an iOS device, will it appear under "Configuration Profile"? Or somewhere else? The MDM isn't functional yet so we haven't seen how it works. If the answer to #2 is yes, is it possible to access the "Configuration Profile" certificates from within the app? Some articles I've read said this isn't possible due to security--you can only access your app's certificates. If this is true, how will the MDM make the certificates available to our app specifically and not just the device? Thanks so much for any help, James T
5
0
2.9k
Jun ’22
SwiftUI and "Simultaneous access" error
I'm using Xcode 13.4.1 and targeting iOS 15.0. I have aSwiftUI app that crashes as soon as you click a button that changes a variable from true to false: Button("Close Side by Side Mode") { mainScreenRecs.isViewingSideBySide = false } This is the only place where the variable is changed; everything else is just SwiftUI reading the variable to determine whether to show views or not, like this: var body: some View {         VStack(spacing: 0) {                 HStack {                     if mainScreenRecs.isViewingSideBySide {                         Text(catalogModel.title)                     } When I look at the debug stack, I can see that the previous modification says LayoutComputer.EngineDelegate.childGeometries(at:origin:), which makes me wonder if it's related to SwiftUI: I see this in the debug output, which has the additional note about AttributeGraph: cycle detected through attribute, another possible SwiftUI problem: I tried wrapping this code in DispatchQuery.main.async, like this: Button("Close Side by Side Mode") { DispatchQueue.main.async { mainScreenRecs.isViewingSideBySide = false } } but it didn't help. Is it possible this is a SwiftUI bug? I hate to think that because it leaves me stuck without a solution, but I can't figure out what else I could check or try.
4
0
1.9k
Jul ’22
XCUIElementQuery in SwiftUI testing returns inconsistent count
I'm doing UI testing of a SwiftUI view, and I have the following code to fetch a List element to check the count of staticTexts in it: let pred = NSPredicate(format: "identifier == 'detailViewTable'") let detailViewTable = app.descendants(matching: .any).matching(pred).firstMatch let arrOfTexts = detailViewTable.staticTexts let ct = arrOfTexts.count print("Count is: \(ct)") // This prints 0 print("Count is now: \(detailViewTable.staticTexts.count)") // Also prints 0 The count always prints as 0. The SwiftUI view basically looks like this: List { Section(header: Text("Item list")) { HStack { Text("Number") Spacer() Text(rec.recNum) } } // Lots more Sections/HStacks/Texts/etc here // ... // ... } .accessibility(identifier: "detailViewTable") .listStyle(.grouped) When I put a breakpoint as shown, and use po in the Debug Console, I get 0 for ct, but 21 if calling count directly: (lldb) po ct 0 (lldb) po detailViewTable.staticTexts.count 21 Why is the var ct set to 0, but calling the count directly gives me the correct number 21? It makes me wonder if the XCUIElementQuery takes a moment to run and returns the answer in some kind of implicit callback, and the data isn't ready at the moment the variable ct is set, but will return the correct answer in the debug console because it waits for the response. However, I don't see any discussion of a callback in the Apple documentation: https://developer.apple.com/documentation/xctest/xcuielementquery
1
0
2.2k
Aug ’22
SwiftUI Navigation Bar appears behind Status Bar
We have a NavigationView embedded within a TabView, like this: TabView(selection: $tabSelection) { NavigationView { When a view gets pushed onto the stack in the NavigationView, the NavigationBar appears too high, almost under the StatusBar, as shown in the attached picture. If you touch the StatusBar, somehow it alerts the NavigationBar to scoot downward into its correct position. I discovered a hack where I quickly toggle the StatusBar off, then back on, which accomplishes the same thing. My question, though, is why is this necessary? Why isn't the NavigationBar in the correct place to begin with? Here's the hack that fixes it: .onAppear { withAnimation(.linear(duration: 0.3)) { appViewModel.hideStatusBar.toggle() } DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { withAnimation(.easeInOut(duration: 0.3)) { appViewModel.hideStatusBar.toggle() } } }
2
0
1.1k
Dec ’23
Network.Framework vs URLSession in Background Task (BGTask)
As noted here, https://developer.apple.com/forums/thread/116799 the Network framework probably won't have a connection available when running in the background. We've been using the BGTask for a couple years now to start a URLSession and pull data from a web server. It works very nicely and reliably. Do we have any options if we want to connect to another iPad, though? I ran a test and even if I have a "server" iPad running a Network framework listener (NWListener), and the app is in the foreground and the screen on, a "client" iPad (NWBrowser) cannot connect to the NWListener when trying to connect from the BGTask; it gives a DefunctConnection error. Why does the Network framework not have the network available to it, but a URLSession does? Is this a limitation of the iPad, or the Network framework? If I had an iPad running as a web server like this project, https://github.com/swisspol/GCDWebServer and an iPad client tries to connect a URLSession to it, would that work? If this is an iPad limitation, could I use a MacBook on the network as a web server and connect to that instead?
6
0
1.4k
Nov ’23
SwiftUI and vars outside the SwiftUI world
We inherited some code that has a variable that begins in the "SwiftUI world", so to speak, and is copied over to a global variable in the "Swift world" for use in non-SwiftUI classes (POSOs? Plain Ol' Swift Objects?). Here's a contrived example showing the basic gist of it. Note how there's an AppViewModel that maintains the state, and an .onChange that copies the value to a global var, which is used in the plain class DoNetworkStuff. I would like to weed out the redundant global var, but I kind of see why it was done this way--how DO you bridge between the 2 worlds? I don't think you can add a ref to AppViewModel inside DoNetworkStuff. I was thinking you could add a function to the AppViewModel that returns devid, and stash a ref to the function in a var for use whenever devid is needed., so at least you're eliminating the var value being stored in 2 places, but that might be confusing a year from now. I'm trying to think of a way to rewrite this without ripping out too much code (it could be that maybe it's better to leave it). var gblDevID = "" //global var class AppViewModel: ObservableObject { @Published var devid = "" ... } struct ContentView: View { @StateObject var appViewModel = AppViewModel() var body: some View { TextField("Enter device id", text: $appViewModel.devid) .onChange(of: appViewModel.devid) { newVal in gblDevID = newVal } ... } } class DoNetworkStuff { func networkingTask() { doSomeTask(gblDevID) } }
5
0
2.7k
Dec ’23
BGTaskScheduler on Mac Silicon not scheduling
When I register & schedule a Background Task on an iPad, it runs properly. Running the exact same code on an M1 MacBook Pro, though, never schedules the task. There's no error, just a failure to schedule. After scheduling and calling getPendingTaskRequests, on the iPad you can see that it has a pending task, but not on the Mac. Why would this be? BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { [self] task in print("task to run") } do { try BGTaskScheduler.shared.submit(request) BGTaskScheduler.shared.getPendingTaskRequests { [self] tasks in print(tasks.count) //Prints 1 on iPad, prints 0 on Mac } } catch { //Code never comes here. print(error) }
1
0
834
Jun ’24
Jetsam memory crash during Network framework usage
I'm using Network Framework to transfer files between 2 devices. The "secondary" device sends file requests to the "primary" device, and the primary sends the files back. When the primary gets the request, it responds like this: do { let data = try Data(contentsOf: filePath) let priSecDataFilePacket = PriSecDataFilePacket(fileName: filename, dataBlob: data) let jsonData = try JSONEncoder().encode(priSecDataFilePacket) let message = NWProtocolFramer.Message(priSecMessageType: PriSecMessageType.priToSecDataFile) let context = NWConnection.ContentContext(identifier: "TransferUtility", metadata: [message]) connection.send(content: encodedJsonToSend, contentContext: context, isComplete: true, completion: .idempotent) } catch { print("\(error)") } It works great, even for hundreds of file requests. The problem arises if some files being requested are extremely large, like 600MB. You can see the memory speedometer on the primary quickly ramp up to the yellow zone, at which point iOS kills the app for high memory use, and you see the Jetsam log. I changed the code to skip JSON encoding the binary file as a test, and that helped a bit, but it still goes too high; the real offender is the step where it loads the 600MB file into the data var: let data = try Data(contentsOf: filePath) If I remark out everything else and just leave that one line, I can still see the memory use spike. As a fix, I'm rewriting this so the secondary requests the file in 5MB chunks by telling the primary a byte range such as "0-5242880" or "5242881-10485760", and then reassembling the chunks on the secondary once they all come in. So far this seems promising, but it's a fair amount of work. My question: Does Network Framework have a built-in way to stream those bytes straight from disk as it sends them? So that I could send all the data in one single request without having to load the bytes into memory?
5
0
420
Mar ’25
PolicyDenied on Simulator with Xcode 16 and Network Framework NWBrowser
I'm using Network framework for communication between devices. The first time I instantiate an NWBrowser, it will prompt the user with a popup that says: Allow <app name> to find devices on local networks? The problem is, once I upgraded from Xcode 15.4 to Xcode 16.4, the popup doesn't appear; it says in the debug window: nw_browser_fail_on_dns_error_locked [B1] nw_browser_dns_service_browse_callback failed: PolicyDenied(18,446,744,073,709,486,046) I do have the info.plist keys Privacy-Local Network Usage Description (NSLocalNetworkUsageDescription) and Bonjour Services (NSBonjourServices) so it's not that. Also, It still works on a real device. I think something changed with Xcode 16 that tightened the security on a simulator, or maybe disabled Network framework entirely. It's not the firewall on my computer because that is turned off. I'm using an M1 MacBook Pro.
1
0
131
Jun ’25
Network Framework Ad Hoc Connection via Ethernet
I have an iPad app that uses Network framework to allow iPads to wirelessly communicate via their built-in ad hoc network capability. However, our app is used in an enterprise environment and there's concern about them communicating wirelessly, so I've been tasked with looking into wired communication. Question: I've read that iOS can connect to a wifi network using an Ethernet adapter, but would this work for ad hoc networking? For ex, if I connect 2 iPads via Ethernet cables to each other (not to the wifi router), and have the NWListener start broadcasting itself, can the NWBrowser find it and establish an ad-hoc connection via the Ethernet cables (and not the wireless cards inside the iPads). The iPads don't have any wifi connections established so they wouldn't be able to communicate any other way. My guess is no...though if they did connect, how would I know it has happening via the cables and not via the wireless ad hoc capability, because I'm guessing there's no way to turn off just the wireless part of the ad hoc feature? If you disable the wifi on an iPad, you're also disabling ad hoc, right? I'm pretty sure there's no way to programmatically send data back and forth between iPads using a USB-C cable connection, so I'm trying to determine if Ethernet cables would work.
3
0
188
Jul ’25
PDFKit findString selection extend not working
With PDFKit in SwiftUI, I'm using the findString function to search the text of a PDF. That part works correctly, but when I use the extend function to get some of the text on both sides of the found word (ie, its context in the page), it doesn't extend. Am I doing this wrong? There is very little documentation or examples about the extend function; even the Apple page doesn't specify what the units refer to in the extend call (presumably it means characters, but I suppose it could also be pixels, or some other measurement specific to PDFs). Here is the code, and pictures of the app, the output (showing that the code can read all the text on the page), and the Acrobat Reader effect I'm trying to achieve. If the extend function truly is broken, and not just a problem in how I'm going about this, a workaround would be to use the text from the entire page, and extract the surrounding words from there, but that does get complicated, especially if there are multiple instances of the word on the page, or if the result straddles 2 pages. import PDFKit import SwiftUI struct ContentView: View { @StateObject var controller = PDFViewController() @State var searchResults:[PDFSelection] = [] var body: some View { VStack { Button { searchResults = controller.pdfView!.document!.findString("is", withOptions: [.caseInsensitive]) let fullPageText = controller.pdfView!.document!.string print(fullPageText) for result in searchResults { let beforeExtending = result.string ?? "" print("Before: \(beforeExtending)") result.extend(atEnd: 3) result.extend(atStart: 3) let afterExtending = result.string ?? "" print("After: \(afterExtending)") } } label: { Text("Do search") } PDFKitView(url: generateURL(), controller: controller) } .padding() } func generateURL() -> URL { let bundlePathRootAsString = Bundle.main.resourcePath! var pdfPathInBundle = URL(fileURLWithPath: bundlePathRootAsString) pdfPathInBundle.append(path: "TestPDF.pdf") return pdfPathInBundle } } struct PDFKitView: UIViewRepresentable { func updateUIView(_ uiView: PDFView, context: Context) { } let url: URL @ObservedObject var controller: PDFViewController func makeUIView(context: Context) -> PDFView { let pdfView = PDFView() pdfView.document = PDFDocument(url: self.url) pdfView.autoScales = true controller.pdfView = pdfView return pdfView } } class PDFViewController: ObservableObject { var pdfView: PDFView? }
2
0
162
Jul ’25