Post

Replies

Boosts

Views

Activity

Reply to Receive error when attempting to use .listStyle() function.
Thanks for showing your code. You may need to use Answers to show additional info well formatted. I do not have enough time to watch the session video carefully, but your code seems to be taken from the session video or the sample code for the session. It is intended to be compiled with Swift 5.5/Xcode 13. Please try changing .listStyle(.carousel) to .listStyle(CarouselListStyle()). But there may be other parts you need Swift 5.5.
Topic: App & System Services SubTopic: Core OS Tags:
Jun ’21
Reply to Form vs Vstack for SwiftUI for iOS
So my question is, is there any reason I should put up with the trouble and use Form? In my opinion, Form is a collection of bunch of styles or behaviors which Apple's designer thinks is appropriate for input forms. So, many of the modifiers do not work as expected for Form or components inside Form. If you want to make many components customized, not using Form seems to be a practical way than hacking the implementation details. From what I can tell, there don't seem to be any real benefits, right? Form is a good container if you want to implement the default styles or behaviors. Seems you do not think it a real benefit, but not all developer would think as you do. One clear thing is, you can have your own opinion.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’21
Reply to Trouble with @escaping Competion Handler when passing data in a shared data container
Any advice would be greatly appreciated! If you can target your app for iOS 15+ and are planning to release it after the released version of Xcode 13 is out, you may try using new async/await feature. Meet async/await in Swift Use async/await with URLSession (There are more session videos about async/await and I recommend to watch all if you have enough time.) If you need to make your app target iOS 14.x and earlier, working with completion handler would be necessary. I assume your loadInitialFireMapData is working fine in normal cases. (Hope you are not ignoring any warnings.) But it has some flaws considering error cases: It ignores some error cases without showing any debug info It does not call completion handler on errors You should better pass an Optional<Error> to the completion handler to indicate error cases. I would write it as follows: class FireDataManager { enum Errors: Error { case urlInvalid case dataIsNil } func loadInitialFireMapData(completion: @escaping (Error?) -> Void) { //<- guard let url = URL(string: "https://opendata.arcgis.com/datasets/68637d248eb24d0d853342cba02d4af7_0.geojson") else { completion(Errors.urlInvalid) return } URLSession.shared.dataTask(with: url) {data, response, error in if let error = error { print("FireMap URL Session error: ", error) //Use `error` instead of `error.localizedDescription` to show debug info completion(error) return } guard let data = data else { completion(Errors.dataIsNil) return } do { let features = try MKGeoJSONDecoder().decode(data) .compactMap { $0 as? MKGeoJSONFeature } let validWorks = features.compactMap(Fire.init) DataContainer.shared.fires.append(contentsOf: validWorks) DataContainer.shared.totalFireCount = validWorks.count print("Fire Data Manager Count of Total Fires: ", DataContainer.shared.totalFireCount) DispatchQueue.main.async { completion(nil) //<- no error here } } catch let error { print("FireMap decoding error: ", error) completion(error) } } .resume() } } In this case, meaning the type of completion is (Error?)->Void, you need to write a closure like { (error: Error?)->Void in ... } or in a simplified form { error in ... } . So, the caller side code would be something like this: class ViewController: UIViewController, CLLocationManagerDelegate { @IBOutlet weak var fireStatusLabel: UILabel! let dataContainer = DataContainer.shared let fireDataManager = FireDataManager() override func viewDidLoad() { super.viewDidLoad() //Retrieve Fire API data from Fire Data Manager fireDataManager.loadInitialFireMapData (completion: { error in if let error = error { print(error) return } self.fireStatusLabel.text = "\(DataContainer.shared.totalFireCount) fires within 100 miles of your location." }) //... } //... } (I renamed FireStatusLabel to fireStatusLabel as only type names start with Capital letter in Swift. If you have any reasons you cannot rename it, please re-interpret the lines with fireStatusLabel.) Or you can use the trailing closure notation like this: fireDataManager.loadInitialFireMapData { error in //<- no opening parenthesis here if let error = error { print(error) return } self.fireStatusLabel.text = "\(DataContainer.shared.totalFireCount) fires within 100 miles of your location." } //<- no closing parenthesis Please try.
Topic: Programming Languages SubTopic: Swift Tags:
Jun ’21