Post

Replies

Boosts

Views

Activity

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
360
Oct ’25
Not sure how to add Prev/Next buttons in my SwiftUI List's Detail view.
I have a SwiftUI app with a List displaying an array of model objects. When the user taps a list item we see its detail view. I want to add previous and next buttons to my detail view, but I'm not sure what needs to happen when previous/next are tapped. (see code below for what I'm looking to do) My first thought is to make the model variable in the DetailView be a binding, but I'm not sure how this would tie in with the NavigationLink 'stuff' any/all suggestions appreciated. thanks! class Model: Identifiable {     var modelValue: Int     init(modelValue: Int) {         self.modelValue = modelValue     }     static let testData = [Model(modelValue: 3), Model(modelValue: 7), Model(modelValue: 31)] } class ModelManager {     static let shared = ModelManager()     let modelList = Model.testData     func previous(for model: Model) - Model? {         if let index = modelList.firstIndex(where: {$0.modelValue == model.modelValue}) {             if index 0 {                 return modelList[index - 1]             }         }         return nil     }     func next(for model: Model) - Model? {         if let index = modelList.firstIndex(where: {$0.modelValue == model.modelValue}) {             if index modelList.count - 1  {                 return modelList[index + 1]             }         }         return nil     } } struct ContentView: View {     let manager:ModelManager = ModelManager.shared     var body: some View {         NavigationView {             List(manager.modelList) { object in                 NavigationLink(                     destination: DetailView(model: object, previous: manager.previous(for: object), next: manager.next(for: object)),                     label: {                         Text("fred \(object.modelValue)")                     })             }         }     } } struct DetailView: View {     var model: Model     var previous: Model?     var next: Model?     var body: some View {         VStack {             HStack {                 if previous != nil {                     Button("Previous") {                         // goto previous                     }                 }                 Spacer()                 if next != nil {                     Button("Next") {                         // goto next                     }                 }             }             Text("value: \(model.modelValue)")             Spacer()         }     } }
1
0
1.6k
Mar ’21
In SwiftUI I would like to declare an @ObservedObject var with a type defined in a protocol...
See sample code below... Basically it's a galleryView with a dataSource that can add/remove items dynamically. It works as expected when GalleryView's dataSource variable has a type (that conforms to ObservableObject) However when I change dataSource's type to be a protocol, I can't seem to get my code to compile. Any guidance on how to use a protocol in GalleryView, and continue to keep the UI updating when the model object's item list changes? thanks! Mike protocol GalleryDataSource: ObservableObject {     var itemCount: Int { get }     func item(for index: Int) - String } class GalleryModel: ObservableObject {     static let test1: GalleryModel = GalleryModel(items: ["A","B","C"])     @Published var items: [String]     init(items: [String]) {         self.items = items     } } extension GalleryModel: GalleryDataSource {     var itemCount: Int {         return items.count     }     func item(for index: Int) - String {         return items[index]     } } struct ContentView: View {     var model: GalleryModel = GalleryModel.test1     var body: some View {         VStack {             GalleryView(dataSource: model)             Button("Add Item") {                 model.items.append("\(model.items.count)")             }         }     } } struct GalleryView: View {     @ObservedObject var dataSource: GalleryModel //GalleryDataSource     var body: some View {         ScrollView(.horizontal, content: {             HStack {                 ForEach(0..self.dataSource.itemCount, id:\.self) { index in                     Text(dataSource.item(for: index))                         .padding()                 }             }         })     } }
1
0
4.7k
May ’21
Can I put a swiftUI container's content in a func/var/let?
I'm trying to find a syntactically correct way to put the contents of a Container in a separate variable (or function). Can anyone steer me in the right direction? thanks, in advance, mike struct ContentView: View { var body: some View { VStack(content: containerContent) .padding() } var containerContent: () -> Content { return { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } } }
1
0
569
Nov ’23
Problems in the iOS Simulator's Photos app?
When I: open a simulator (eg iPhone 15, iOS 17.0) open the Photos app tap on an image (either one that comes included, or something I've saved to PhotoRoll) tap Edit I see the typical Photos Edit view with two key differences. the image is not visible, the middle of the view is all black there are now Cancel/Done/Dismiss buttons. I need to force quit to get back to the Springboard (Is that still the correct term?) Am I doing something wrong, or should the simulator's Photo's app be providing a better edit experience?
1
0
846
Jan ’24
Should Photo Extensions work in iOS simulators?
When I: open an existing project create a new PhotoExtensions target run the new target in an iOS simulator (eg iPhone 15, iOS 17.0) Select photos as the app to run Open a photo Tap the ... button at the top right I see: Copy, Duplicate, Hide, etc. But I do not see my new Extension. Is there something else I need to be doing in order to see my new Extension in 'action'?
1
0
759
Jan ’24
I want to move a CoreImage task to the background...
It feels like this should be easy, but I'm having conceptual problems about how to do this. Any help would be appreciated. I have a sample app below that works exactly as expected. I'm able to use the Slider and Stepper to generate inputs to a function that uses CoreImage filters to manipulate my input image. This all works as expected, but it's doing some O(n) CI work on the main thread, and I want to move it to a background thread. I'm pretty sure this can be done using combine, here is the pseudo code I imagine would work for me: func doStuff() { // subscribe to options changes // .receive on background thread // .debounce // .map { model.inputImage.combine(options: $0) // return an object on the main thread. // update an @Published property? } Below is the POC code for my project. Any guidance as to where I should use combine to do this would be greatly appreciate. (Also, please let me know if you think combine is not the best way to tackle this. I'd be open to alternative implementations.) struct ContentView: View { @State private var options = CombineOptions.basic @ObservedObject var model = Model() var body: some View { VStack { Image(uiImage: enhancedImage) .resizable() .aspectRatio(contentMode: .fit) Slider(value: $options.scale) Stepper(value: $options.numberOfImages, label: { Text("\(options.numberOfImages)")}) } } private var enhancedImage: UIImage { return model.inputImage.combine(options: options) } } class Model: ObservableObject { let inputImage: UIImage = UIImage.init(named: "IMG_4097")! } struct CombineOptions: Codable, Equatable { static let basic: CombineOptions = .init(scale: 0.3, numberOfImages: 10) var scale: Double var numberOfImages: Int }
1
0
958
Jan ’24
Does running a single test in a Target containing unit tests start by running the actual app?
In V 0.1 of my app, I went with a simple option for a piece of business logic in my app. I then changed something else that caused my simplified business logic to now crash the app at startup. Excellent, a chance to use Test. Driven Design to replace my flawed business logic. So I wrote my first test TDD test, but when I tried to run the test... It doesn't run because running the test target seems to start by actually running my full app (which as I described in chapter 1 is currently crashing) Have I configured something incorrectly? or is it normal that when I attempt to run a single test, step 1 is running the full app? (note: it is very easy for me to disable/avoid the business logic causing my crash. This question is more about my lack of understanding of what it means to run a test target.) thanks in advance for any and all responses. Mike
1
0
859
May ’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
530
Sep ’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
533
Oct ’24
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
579
Feb ’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
214
Aug ’25
Unable to deploy CloudKit Dev Schema to production
This will be the initial production schema for this container. When I attempt to start deployment, the Confirm Deployment dialog appears and spins for a while. It then reports "There was a problem loading the environment's status." When I clear the error the Confirm Deployment dialog reports: "No Changes to Deploy" "The schema in the development environment is the same as production." (spoiler, they are not the same) Any suggestions?
0
0
628
May ’21
I'm seeing inconsistent results with different types of Binding<>
I've created a UserDefaults extension to generate custom bindings. extension UserDefaults { func boolBinding(for defaultsKey: String) -> Binding<Bool> { return Binding ( get: { return self.bool(forKey: defaultsKey) }, set: { newValue in self.setValue(newValue, forKey: defaultsKey) }) } func cardPileBinding(for defaultsKey: String) -> Binding<CardPile> { return Binding ( get: { let rawValue = self.object(forKey: defaultsKey) as? String ?? "" return CardPile(rawValue: rawValue) ?? .allRandom }, set: { newValue in self.setValue(newValue.rawValue, forKey: defaultsKey) }) } } For the sake of completeness, here is my enum enum CardPile: String, CaseIterable { case allRandom case numbers case numbersRandom case daysMonths case daysMonthsRandom } I've also created UI elements that use these bindings: var body: some View { VStack { Toggle("Enable", isOn: UserDefaults.standard.boolBinding(for: "enable")) Picker("Card Pile", selection: UserDefaults.standard.cardPileBinding(for: "cardPile")) { ForEach(CardPile.allCases, id: \.self) { Text("\($0.rawValue)") .tag($0.rawValue) } } } } When I tap the toggle, it updates correctly. However when I tap the picker and select a different value, the binding setter gets called, but the view does not refreshed to reflect the change in value. (If I force quit the app and re-run it, the I see the change.) I would like to find out why the Binding works as I'd expected (ie updates the UI when the value changes) but the Binding behaves differently. any/all guidance very much appreciated. Note: I get the same behavior when the enum use Int as its rawValue
0
0
583
Jun ’24