Post

Replies

Boosts

Views

Activity

Having trouble catching a 'redirect' with URLSessionDownloadDelegate
I've implemented func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) and func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) I've put a breakpoint in each but the BP in willPerformHTTPRedirection never fires. When the didWriteData fires and I inspect downloadTask.originalRequest I see my original request URL When I inspect downloadTask.currentRequest the returned request contains a different URL. I'm the farthest thing from an HTTP wizard, but I had thought when originalRequest differs from currentRequest there had been some sort of server-side 'redirection'. Is there a way for my code to receive a callback when something like this happens? NOTE: my download code works fine, I'm just hoping to detect the case when currentRequest changes. any/all guidance greatly appreciated on the off chance it helps, are are my original and current request values: (lldb) po downloadTask.originalRequest ▿ Optional<URLRequest> ▿ some : https://audio.listennotes.com/e/p/c524803c1a90412f922948274ecc3625/ (lldb) po downloadTask.currentRequest ▿ Optional<URLRequest> ▿ some : https://26973.mc.tritondigital.com:443/OMNY_HAPPIERWITHGRETCHENRUBIN_PODCAST_P/media-session/76cfceb2-1801-4570-b830-ded57611a9cf/d/clips/796469f9-ea34-46a2-8776-ad0f015d6beb/e1b22d0b-6974-4bb8-81ba-b2480119983c/2f35a8ca-b982-44e9-8122-b3dc000ae0e1/audio/direct/t1769587393/Ep_571_Want_to_Join_Us_for_a_No-Spend_February_Plus_a_Better_Word_for_Squats.mp3?t=1769587393&in_playlist=751ada7f-ded3-44b9-bfb8-b2480119985b&utm_source=Podcast
1
0
47
4d
Stumped by URLSession behaviour I don't understand...
I have an app that has been using the following code to down load audio files: if let url = URL(string: episode.fetchPath()) { var request = URLRequest(url: url) request.httpMethod = "get" let task = session.downloadTask(with: request) And then the following completionHandler code: func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { try FileManager.default.moveItem(at: location, to: localUrl) In the spirit of modernization, I'm trying to update this code to use async await: var request = URLRequest(url: url) request.httpMethod = "get" let (data, response) = try await URLSession.shared.data(for: request) try data.write(to: localUrl, options: [.atomicWrite, .completeFileProtection]) Both these code paths use the same url value. Both return the same Data blobs (they return the same hash value) Unfortunately the second code path (using await) introduces a problem. When the audio is playing and the iPhone goes to sleep, after 15 seconds, the audio stops. This problem does not occur when running the first code (using the didFinish completion handler) Same data, stored in the same URL, but using different URLSession calls. I would like to use async/await and not have to experience the audio ending after just 15 seconds of the device screen being asleep. any guidance greatly appreciated.
7
0
348
1w
Calendar's date func is not behaving as I'd expect...
When I run this in a playground: var meDate = Calendar.current.date(from: DateComponents(year: 2024, hour: 7, weekday: 3, weekdayOrdinal: 2))! print(meDate) I see: 2024-01-09 15:00:00 +0000 This seems correct to me. jan 9th is the second Tuesday in 2024 I'm in the pacific TZ, 07:00 PDT matches 15:00GMT But then I do this: meDate = Calendar.current.date(bySetting: .weekday, value: 4, of: meDate)! print(meDate) and I see: 2024-01-10 08:00:00 +0000 I would have expected my hour value (7PST/15GMT) to have been preserved. Is there a way I can update weekday, but not lose my hour?
2
0
369
Oct ’25
Seeing some behaviour in Swift that I don't understand...
It's related to the passByValue nature of structs. In the sample code below, I'm displaying a list of structs (and I can add instances to my list using Int.random(1..&lt;3) to pick one of two possible predefined versions of the struct). I also have a detail view that can modify the details of a single struct. However when I run this code, it will instead modify all the instances (ie either Sunday or Monday) in my list. To see this behaviour, run the following code and: tap New Trigger enough times that there are multiple of at least one of the sunday/monday triggers tap one of the matching trigger rows modify either the day, or the int expected: only one of the rows will reflect the edit actual: all the matching instances will be updated. This suggests to me that my Sunday and Monday static instances are being passed by reference when they get added to the array. But I had thought structs were strictly pass by value. What am I missing? thanks in advance for any wisdom, Mike struct ContentView: View { @State var fetchTriggers: [FetchTrigger] = [] var body: some View { NavigationView { VStack { Button("New Trigger") { fetchTriggers.append(Int.random(in: 1..&lt;3) == 1 ? .sunMorning : .monEvening) } List($fetchTriggers) { fetchTrigger in NavigationLink(destination: FetchTriggerDetailView(fetchTrigger: fetchTrigger) .navigationBarTitle("Back", displayMode: .inline)) { Text(fetchTrigger.wrappedValue.description) .padding() } } } } } } struct FetchTrigger: Identifiable { static let monEvening: FetchTrigger = .init(dayOfWeek: .monday, hour: 6) static let sunMorning: FetchTrigger = .init(dayOfWeek: .sunday, hour: 3) let id = UUID() enum DayOfWeek: Int, Codable, CaseIterable, Identifiable { var id: Int { self.rawValue } case sunday = 1 case monday case tuesday var description: String { switch self { case .sunday: return "Sunday" case .monday: return "Monday" case .tuesday: return "Tuesday" } } } var dayOfWeek: DayOfWeek var hour: Int var description: String { "\(dayOfWeek.description), \(hour):00" } } struct FetchTriggerDetailView: View { @Binding var fetchTrigger: FetchTrigger var body: some View { HStack { Picker("", selection: $fetchTrigger.dayOfWeek) { ForEach(FetchTrigger.DayOfWeek.allCases) { dayOfWeek in Text(dayOfWeek.description) .tag(dayOfWeek) } } Picker("", selection: $fetchTrigger.hour) { ForEach(1...12, id: \.self) { number in Text("\(number)") .tag(number) } } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
1
0
227
Aug ’25
A wrinkle converting a UIKit Document-based app to SwiftUI Document Group
The app I'm converting includes two unique document types. UI-wise they have key similarities (eg contents are password protected) But serialization/model - wise. they are different documents. I have not been able to find any documentation on options for implementing this (eg use a (abstract?) base class derived from FileDocument, with two concrete sub classes? maybe just a single subclass of FileDocument that contains model details for both file types?) Stepping back from implementation options, am I crazy for attempting to use DocumentGroup to create a single app that would need to be able to open/modify/save multiple unique document types? any/all guidance much appreciated.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
66
May ’25
Implementing RawRepresentable for a DictionaryType has broken my Test target build. Not sure how to fix things...
For my app I've created a Dictionary that I want to persist using AppStorage In order to be able to do this, I added RawRepresentable conformance for my specific type of Dictionary. (see code below) typealias ScriptPickers = [Language: Bool] extension ScriptPickers: @retroactive RawRepresentable where Key == Language, Value == Bool { public init?(rawValue: String) { guard let data = rawValue.data(using: .utf8), let result = try? JSONDecoder().decode(ScriptPickers.self, from: data) else { return nil } self = result } public var rawValue: String { guard let data = try? JSONEncoder().encode(self), // data is Data type let result = String(data: data, encoding: .utf8) // coerce NSData to String else { return "{}" // empty Dictionary represented as String } return result } } public enum Language: String, Codable, { case en = "en" case fr = "fr" case ja = "ja" case ko = "ko" case hr = "hr" case de = "de" } This all works fine in my app, however trying to run any tests, the build fails with the following: Conflicting conformance of 'Dictionary<Key, Value>' to protocol 'RawRepresentable'; there cannot be more than one conformance, even with different conditional bounds But then when I comment out my RawRepresentable implementation, I get the following error when attempting to run tests: Value of type 'ScriptPickers' (aka 'Dictionary<Language, Bool>') has no member 'rawValue' I hope Joseph Heller is out there somewhere chuckling at my predicament any/all ideas greatly appreciated
1
0
606
Feb ’25
Trying to better understand CGAffineTransform.... and need a bit of guidance.
I have a CoreImage pipeline and one of my steps is to rotate my image about the origin (bottom left corner) and then translate it. I'm not seeing the behaviour I'm expecting, and I think my problem is in how I'm combining these two steps. As an example, I start with an identity transform (lldb) po transform333 ▿ CGAffineTransform - a : 1.0 - b : 0.0 - c : 0.0 - d : 1.0 - tx : 0.0 - ty : 0.0 I then rotate 1.57 radians (approx. 90 degrees, CCW) transform333 = transform333.rotated(by: 1.57) - a : 0.0007963267107332633 - b : 0.9999996829318346 - c : -0.9999996829318346 - d : 0.0007963267107332633 - tx : 0.0 - ty : 0.0 I understand the current contents of the transform. But then I translate by 10, 10: (lldb) po transform333.translatedBy(x: 10, y: 10) - a : 0.0007963267107332633 - b : 0.9999996829318346 - c : -0.9999996829318346 - d : 0.0007963267107332633 - tx : -9.992033562211013 - ty : 10.007960096425679 I was expecting tx and ty to be 10 and 10. I have noticed that when I reverse the order of these operations, the transform contents look correct. So I'll most likely just perform the steps in what feels to me like the incorrect order. Is anyone willing/able to point me to an explanation of why the steps I'm performing are giving me these results? thanks, mike
3
0
610
Jan ’25
Is it possible to make GeometryReader less vertically greedy?
I must be missing something here. I want to put a landscape image in a geometry reader that contains a ZStack that contains an image and an overlay centred on top of the Image. I would like the ZStack and GeoReader's sizes to be the size of Image. (ie I want geometry.size to be the size of the image, which can be used to control the offset of the overlay's position.) Unfortunately the ZStack also includes the space above the image (ie the top safeArea) and the GeometryReader also includes all the space below the Image. (so geometry.size.height is greater than the height of Image) I've gone down rabbit holes of adding other items above/below, but I don't seem to be able to prevent the GeometryReader from being vertically greedy. eg the Text(" ") above the ZStack in the VStack solves the ZStack claiming the top safe area. But adding Text(" ") below the ZStack does not prevent the GeometryReader from claiming more vertical space below the image. Any/all guidance greatly appreciated. struct ContentView: View { var body: some View { VStack { // Text(" ") GeometryReader { geometry in ZStack { Image( uiImage: .init(imageLiteralResourceName: "LandscapeSample") ) .resizable() .aspectRatio(contentMode: .fit) Text("Hello, world!") .background(.white) } .background(.red) } .background(.blue) // Text(" ") } } }
2
0
460
Jan ’25
Adding logging to a SwiftUI View's body var
Pretty sure this is a no-no, but asking just in case there's an easy way to make this work struct DocumentContentView: View { private static let logger = Logger( subsystem: "mySubsystem", category: String(describing: Self.self) ) var body: some View { VStack { Text("Hello") logger.trace("hello") } } } This code generates the following compile error at the logger.trace line buildExpression is unavailable: this expression does not conform to View I suspect every line of the body var (or any @ViewBuilder - designated code?) needs to 'return' a View. Is this correct? or more importantly any work arounds other than putting some/all of the view contents in a. func()?
2
1
2.6k
Dec ’24
Can't seem to get Unit Test target working when I create. Multiplatform project
In Xcode Version 16.1 Create a new Project, choose Multiplatform, App For testing system, choose XCTest and UI Tests In the project, open the newly generated template Unit test file Click either of the diamonds in the left margin (either to run the example test or the entire file) Expected Result: Code compiles and then Runs the test/tests Actual Result: Code compiles, but then never completes testing (the top status bar is stuck saying "Testing..." forever.) Am I missing something?
0
0
450
Dec ’24
Struggling to add a test target to an existing project in Xcode
Sorry if this question is too vague, however I've tried this multiple times and see the same result. I'm pretty sure I'm doing something wrong, but don't know what. I have a Multiplatform (iOS and macOS) project that builds, and runs I add a new target of type Unit Test Bundle I click the diamond in the margin beside the XCTestCase declaration at the top of the new Test file The target project builds, then Xcode says 'Testing...' and it stays like this forever. I've also tried creating a new scheme that targets the target created in the above steps. attempting to run my tests behaves the same. The top status bar will get stuck saying 'Testing...' and never get anywhere. I'm pretty sure this is something basic. thanks, in advance for any guidance. Mike
2
0
1.3k
Nov ’24
SwiftUI FocusState seems to 'misbehave' when Scene contains a DocumentGroup...
I have a view containing either a TextField or a SecureField. I'm hoping I can use a single FocusState value that will apply to either the TextField or SecureField. (I'm using FocusState to ensure the cursor will be in the field when it initially loads) I've verified this works in a sample project when the view is in a WindowGroup. But when I instead use a DocumentGroup ~50% of the time when the view loads/launches, it does not have focus. Here is my ContentView: struct ContentView: View { let coinFlip: Bool = .random() // used to choose between the TextField and the SecureField @State var fieldContent: String = "" // bound to the Field value @FocusState var focus: Bool var body: some View { VStack { Text("Coin Flip: \(coinFlip)") actualField .focused($focus, equals: true) } .onAppear() { focus = true } } @ViewBuilder var actualField: some View { if coinFlip { TextField("Enter text here", text: $fieldContent) } else { SecureField("Enter secure text here", text: $fieldContent) } } } and here is my App swift file @main struct ModernTurtleApp: App { var body: some Scene { // WindowGroup { // ContentView() // } DocumentGroup(newDocument: ModernTurtleDocument()) { file in ContentView() } } } When this code runs, the Field has focus about 50% of the time on initial launch. When I uncomment the WindowGroup and comment the DocumentGroup, the field always has focus on initial launch. I realize I can work around this behaviour by using an optional enum for FocusState. I would be ok going this route, but I first want to try to understand the behaviour I'm seeing, and possibly keep my simpler FocusState implementation. Thanks, in advance for any help.
0
0
444
Oct ’24
How can I programmatically have focus in a SwiftUI TextField at launch/load
I thought the following code would allow me to have focus in the TextField when the app loads. Is there something else/different that I need to do? struct ContentView: View { enum FocusField { case password } @State var fieldContent: String = "" @FocusState var focus: FocusField? var body: some View { VStack { TextField("Enter text here", text: $fieldContent) .focused($focus, equals: .password) Text("Hello, world!") } .padding() .defaultFocus($focus, .password) } }
1
0
558
Oct ’24
UIDocumentBrowserViewController create new document used to work, but...
is now broken. (but definitely worked when I originally wrote my Document-based app) It's been a few years. DocumentBrowserViewController's delegate implements the following func. func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void) { let newDocumentURL: URL? = Bundle.main.url(forResource: "blankFile", withExtension: "trtl2") // Make sure the importHandler is always called, even if the user cancels the creation request. if newDocumentURL != nil { importHandler(newDocumentURL, .copy) } else { importHandler(nil, .none) } } When I tap the + in the DocumentBrowserView, the above delegate func is called (my breakpoint gets hit and I can step through the code) newDocumentURL is getting defined successfully and importHandler(newDocumentURL, .copy) gets called, but returns the following error: Optional(Error Domain=com.apple.DocumentManager Code=2 "No location available to save “blankFile.trtl2”." UserInfo={NSLocalizedDescription=No location available to save “blankFile.trtl2”., NSLocalizedRecoverySuggestion=Enable at least one location to be able to save documents.}) This feels like something new I need to set up in the plist, but so far haven't been able to discover what it is. perhaps I need to update something in info.plist? perhaps one of: CFBundleDocumentTypes UTExportedTypeDeclarations Any guidance appreciated. thanks :-)
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
552
Sep ’24