Post

Replies

Boosts

Views

Activity

Which workouts have a GPS track?
The session Build custom swimming workouts with WorkoutKit mentions Outdoor activities supporting distance goals and lists: Cycling Running Hiking Walking Swimming Wheelchair walk + run And new: Golf Rowing Downhill skiing Snowboarding Lacrosse Hockey Disc Sports Skating Paddle sports Soccer American football Australian football Rugby Cross country skiing I know the previous 6 have GPS tracks saved with the workout in Health. Do all of the other ones now also save the GPS track to Health? If not all of them, which do?
1
0
703
Jun ’24
default calendar for new event in iOS17
It looks like the delegate function eventEditViewControllerDefaultCalendar(forNewEvents controller: EKEventEditViewController) -> EKCalendar of the EKEventEditViewDelegate protocol is not called in iOS 17 anymore. The app does have the new NSCalendarsFullAccessUsageDescription key set and full access is granted. Is this the intended behaviour for iOS 17? Does anybody else have the same problem?
1
1
593
Sep ’23
Workouts with route data
Is there a list which workout types on Apple Watch record the route during workout and store it in Health? Looking at the HKWorkoutActivityType enum I know the following do record a route: walking (if it is outdoor) running (if it is outdoor) wheelchairWalkPace wheelchairRunPace cycling hiking swimming (if it is outdoor) swimBikeRun I can imagine skiing and snowboarding would also record the route? Maybe surfing, sailing, rowing and skating as well?
0
0
767
Jan ’23
SwiftUI sheet dismiss warning
I wanted to add a dismiss button to a sheet on SwiftUI. Since I also want to control the presentation from code, I put the presented state in a view model. Here is a simplified version of the code: final class ViewController: ObservableObject { @Published var showSheet: Bool = false } struct ContentView: View { @StateObject private var viewController = ViewController() var body: some View { Button("Show sheet") { viewController.showSheet = true } .padding() .sheet(isPresented: $viewController.showSheet, content: { MySheetView() }) } } struct MySheetView: View { @Environment(\.dismiss) private var dismiss var body: some View { NavigationView { Text("Hello from the sheet") .toolbar { ToolbarItem(placement: .navigationBarTrailing, content: { Button("Dismiss") { dismiss() } }) } } } } If I use the dismiss button, I get the warning: Publishing changes from within view updates is not allowed, this will cause undefined behavior. just swiping down the sheet works fine. Am I using something wrong here? Xcode Version 14.0 (14A309)
7
2
2.8k
Sep ’22
NSMetadataQuery on tvOS
I wanted to use NSMetadataQuery on tvOS to query for a file changed through iCloud. However, the app crashes directly when instantiating a NSMetadataQuery object. Documentation says its available since tvOS 9.0. https://developer.apple.com/documentation/foundation/nsmetadataquery It crashes in the simulator (tvOS 15.4 and tvOS 16) as well as on a real device with the latest tvOS version. I just created it like this: private let metadataQuery = NSMetadataQuery() Is it not possible to use NSMetadataQuery on tvOS? I also filed a feedback FB11422512
1
1
1.1k
Aug ’22
MKPolyline loses border when zooming
I added multiple MKPolyline to a MKMapView. It looks fine on the beginning, but when I start zooming, the border of the MKPolyline gets lost on some poly lines. zoomed out: zoomed in: here is the code I used: import MapKit import UIKit class ViewController: UIViewController {     @IBOutlet weak var mapView: MKMapView!     override func viewDidLoad() {         super.viewDidLoad()         mapView.delegate = self         mapView.mapType = .mutedStandard         mapView.pointOfInterestFilter = .excludingAll         let tiles = [             MapTile(x: 8586, y: 5514),             MapTile(x: 8587, y: 5514),             MapTile(x: 8588, y: 5514),             MapTile(x: 8587, y: 5515),         ]         let polygons = tiles.map { tile in             MKPolygon(coordinates: tile.locations, count: tile.locations.count)         }         mapView.addOverlays(polygons, level: .aboveLabels)     } } extension ViewController: MKMapViewDelegate {     func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {         if let mapTile = overlay as? MKPolygon {             let renderer = MKPolygonRenderer(polygon: mapTile)             renderer.fillColor = .systemBlue.withAlphaComponent(0.15)             renderer.strokeColor = .systemBlue             renderer.lineWidth = 0.7             return renderer         }         return MKOverlayRenderer(overlay: overlay)     } } struct MapTile: Identifiable, Hashable {     let x: Int     let y: Int     var id: String { "\(x)-\(y)" }     static let zoomFactor = Double(1 << 14)     static func locationOrigin(tileX: Int, tileY: Int) -> CLLocationCoordinate2D {         let lon = (Double(tileX) / MapTile.zoomFactor) * 360.0 - 180.0         let lat = atan( sinh (.pi - (Double(tileY) / MapTile.zoomFactor) * 2 * Double.pi)) * (180.0 / .pi)         return CLLocationCoordinate2D(latitude: lat, longitude: lon)     }     var locationOrigin: CLLocationCoordinate2D {         MapTile.locationOrigin(tileX: x, tileY: y)     }     var locations: [CLLocationCoordinate2D] {         let topLeft = locationOrigin         let topRight = MapTile.locationOrigin(tileX: x + 1, tileY: y)         let bottomRight = MapTile.locationOrigin(tileX: x + 1, tileY: y + 1)         let bottomLeft = MapTile.locationOrigin(tileX: x, tileY: y + 1)         return [             topLeft,             topRight,             bottomRight,             bottomLeft         ]     } } any ideas why this happens?
5
0
1.4k
Jul ’22
MapKit bus stations
I want to see all the public transport stations on my MKMapView. With the following code I get train stations on the map: mapView.pointOfInterestFilter = MKPointOfInterestFilter(including: [.publicTransport]) But the bus stops are missing. If I use the Apple Maps app and chose Transit as the map, the bus stops are available there. How can I get the bus stops in my app using MKMapView?
0
0
1.1k
Apr ’22
Open Maps app from Safari extension
With a Safari extension I add a link to certain websites to open the Maps app with coordinates found on the website. In the content script I detect clicks on my added link and forward the message to the background script with browser.runtime.sendMessage({ coordinates: "some coordinates I found on the website" }). The background script receives this message in its listener function and forwards the message to the extension handler like so browser.runtime.onMessage.addListener((request, sender, sendResponse) => { browser.runtime.sendNativeMessage( { message: request.coordinates }, function(response) { }); } The extension handler receives the message in its func beginRequest(with context: NSExtensionContext) function as expected. In this function I convert the coordinates I receive to a valid CLLocationCoordinate2D object. However, if I want to use the following code inside the beginRequest function to open the Maps app, it does not work on iOS. The same code works fine with a macOS Safari extension. MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 50.1234, longitude: 8.1234))).openInMaps()
1
0
1.1k
Apr ’22
Storing AttributedString
I was playing around a bit with the new AttributedString and a few questions came up. I saw this other forum question "JSON encoding of AttributedString with custom attributes", but I did not completely understand the answer and how I would need to use it. I created my custom attribute where I just want to store additional text like this: enum AdditionalTextAttribute: CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {     typealias Value = AttributedString     static let name = "additionalText" } I then extended the AttributeScopes like this: extension AttributeScopes {     struct MyAppAttributes: AttributeScope {         let additionalText: AdditionalTextAttribute         let swiftUI: SwiftUIAttributes     }     var myApp: MyAppAttributes.Type { MyAppAttributes.self } } and I also implemented the AttributeDynamicLookup like this: extension AttributeDynamicLookup {     subscript&lt;T: AttributedStringKey&gt;(dynamicMember keyPath: KeyPath&lt;AttributeScopes.MyAppAttributes, T&gt;) -&gt; T { self[T.self] } } So next I created my AttributedString and added some attributes to it: var attStr = AttributedString("Hello, here is some text.") let range1 = attStr.range(of: "Hello")! let range2 = attStr.range(of: "text")! attStr[range1].additionalText = AttributedString("Hi") attStr[range2].foregroundColor = .blue attStr[range2].font = .caption2 Next I tried to create some JSON from my string and took a look at it like this: let jsonData = try JSONEncoder().encode(attStr) print(String(data: jsonData, encoding: .utf8) ?? "no data") //print result: ["Hello",{},", here is some ",{},"text",{"SwiftUI.ForegroundColor":{},"SwiftUI.Font":{}},".",{}] I guess it makes sense, that both SwiftUI.ForegroundColor and SwiftUI.Font are empty, because they both do not conform to Codable protocol. My first question would be: Why does my additionalText attribute not show up here? I next tried to extend Color to make it codable like this: extension Color: Codable {     enum CodingKeys: CodingKey {         case red, green, blue, alpha         case desc     }     public func encode(to encoder: Encoder) throws {         var container = encoder.container(keyedBy: CodingKeys.self)         guard let cgColor = self.cgColor,               let components = cgColor.components else {                   if description.isEmpty { throw CodingErrors.encoding }                   try container.encode(description, forKey: .desc)                   return               }         try container.encode(components[0], forKey: .red)         try container.encode(components[1], forKey: .green)         try container.encode(components[2], forKey: .blue)         try container.encode(components[3], forKey: .alpha)     }     public init(from decoder: Decoder) throws {         let container = try decoder.container(keyedBy: CodingKeys.self)         if let description = try container.decodeIfPresent(String.self, forKey: .desc) {             if description == "blue" {                 self = Color.blue                 return             }             throw CodingErrors.decoding         }         let red = try container.decode(CGFloat.self, forKey: .red)         let green = try container.decode(CGFloat.self, forKey: .green)         let blue = try container.decode(CGFloat.self, forKey: .blue)         let alpha = try container.decode(CGFloat.self, forKey: .alpha)         self.init(CGColor(red: red, green: green, blue: blue, alpha: alpha))     } } But it looks like even though Color is now codable, the encoding function does not get called when I try to put my attributed string into the JSONEncoder. So my next question is: Does it just not work? Or do I also miss something here? Coming to my last question: If JSONEncoder does not work, how would I store an AttributedString to disk?
4
0
1.7k
Jan ’22
Location information on HKWorkout?
If I use the Apple training app on Apple Watch, indoor trainings like swimming in a pool will also store a location which I can see later in the Fitness app on the iPhone. My question: How do I store these location information with my own workout app on the watch? I tried creating a HKWorkoutRoute with the HKWorkoutRouteBuilder and added only one location. It saves fine, but the location does not appear in the Fitness app. If I query a workout recorded with the Apple training app on the iPhone, it also looks like there is no connected HKWorkoutRoute data stored. I also can not find any metadata key or something which I can use instead.
2
0
1.3k
Oct ’21
CoreSpotlight catalyst preview
I created some objects and pusehd them to core spotlight using the CSSearchableIndex.default().indexSearchableItems function.Now I also wanted the app to run on macOS, so I enabled the Mac target in my Deployment Info.So far so good. The objects also show up in the spotlight search on macOS.My question is: how do I set up the preview?The default is just an empty view and when I try to use my iOS "Quick Look Preview Extension" I get a compiler error:Quick Look Preview extensions are not available when building for Mac Catalyst.I also tried adding a macOS "Quick Look Preview Extension" target. But it also does not work. I guess it is not working, because I do not have a macOS app. What is the correct way to provide the preview on mac catalyst?
0
0
875
Jun ’20
NSFetchedResultsController with UITableViewDiffableDataSource update value
I have a NSFetchedResultsController combined with a UITableViewDiffableDataSource.There is a bool attribute "marked" in my entity which I want to change by clicking on the table view cell. To display the status, I change the background color of the cell. However, the reload is not working as expected. The background color of the cell won't change.I first tried UITableViewDiffableDataSource&lt;String, NSManagedObjectID&gt;, but obviously that won't work for changes, because the NSManagedObjectID doesn't change. I then updated it to UITableViewDiffableDataSource&lt;Int, Test&gt;, but that also didn't work as expected.Any ideas how to solve this? Or is it just not (yet) possible?import UIKit import CoreData class MainViewController: UITableViewController { lazy var fetchedResultController: NSFetchedResultsController&lt;Test&gt; = { let fetchRequest: NSFetchRequest&lt;Test&gt; = Test.fetchRequest() fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)] let fetchedResultController = NSFetchedResultsController&lt;Test&gt;(fetchRequest: fetchRequest, managedObjectContext: self.viewContext, sectionNameKeyPath: nil, cacheName: nil) fetchedResultController.delegate = self return fetchedResultController }() var persistentContainer: NSPersistentContainer { get { return (UIApplication.shared.delegate as! AppDelegate).persistentContainer } } var viewContext: NSManagedObjectContext { get { return self.persistentContainer.viewContext } } lazy var dataSource: UITableViewDiffableDataSource&lt;Int, Test&gt; = { return UITableViewDiffableDataSource&lt;Int, Test&gt;(tableView: self.tableView) { (tableView, indexPath, cdObject) -&gt; UITableViewCell? in let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "\(cdObject.name!) (\(cdObject.id))" cell.detailTextLabel?.text = DateFormatter.localizedString(from: cdObject.timestamp!, dateStyle: .short, timeStyle: .short) cell.backgroundColor = cdObject.clicked ? UIColor.systemOrange : UIColor.systemBackground return cell } }() @IBAction func barButtonPressed_insert(_ sender: UIBarButtonItem) { for i in 0 ..&lt; 7 { let newCDEntry = Test(context: self.viewContext) newCDEntry.id = Int16(i) newCDEntry.name = "Name \(i)" newCDEntry.timestamp = Date() } self.viewContext.transactionAuthor = "regular insert" defer { self.viewContext.transactionAuthor = nil } do { try self.viewContext.save() } catch { let nserror = error as NSError if let conflicts = nserror.userInfo["conflictList"] as? [NSConstraintConflict] { for conflict in conflicts { for conflictObject in conflict.conflictingObjects { self.viewContext.delete(conflictObject) } } } do { try self.viewContext.save() } catch { print("##### error saving insert") } } } override func viewDidLoad() { super.viewDidLoad() do { try self.fetchedResultController.performFetch() } catch { print("could not fetch data") } self.applyFetchedDataToDataSource(animated: false) } private func applyFetchedDataToDataSource(animated: Bool) { var snapshot = NSDiffableDataSourceSnapshot&lt;Int, Test&gt;() snapshot.appendSections([0]) snapshot.appendItems(self.fetchedResultController.fetchedObjects ?? []) self.dataSource.apply(snapshot, animatingDifferences: animated) } @objc private func managedObjectContextObjectDidSave(notification: Notification) { print("received save notification") self.viewContext.mergeChanges(fromContextDidSave: notification) } // MARK: - TableView override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let cdObject = self.fetchedResultController.object(at: indexPath) cdObject.clicked = !cdObject.clicked do { self.viewContext.transactionAuthor = "click toggled" defer { self.viewContext.transactionAuthor = nil } try self.viewContext.save() } catch { print("could not save clicked toggle") } } } extension MainViewController: NSFetchedResultsControllerDelegate { func controllerDidChangeContent(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;) { self.applyFetchedDataToDataSource(animated: true) } }
1
0
1.4k
Apr ’20