Posts

Post not yet marked as solved
1 Replies
57 Views
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?
Posted
by andre07.
Last updated
.
Post not yet marked as solved
0 Replies
196 Views
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?
Posted
by andre07.
Last updated
.
Post not yet marked as solved
1 Replies
297 Views
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()
Posted
by andre07.
Last updated
.
Post not yet marked as solved
1 Replies
207 Views
I wanted to use the new CLLocationButton. It works fine as long as the iPhone language is set to English, but when I change it to German, the button is empty and not presenting the location access message anymore. I already filed a feedback: FB9951235 Are there any workarounds?
Posted
by andre07.
Last updated
.
Post marked as solved
3 Replies
384 Views
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?
Posted
by andre07.
Last updated
.
Post not yet marked as solved
1 Replies
493 Views
If I use the Apple training app for indoor swim workouts, I can see the distance by each swimming stroke style later in the Fitness app. However, if I build my own swim app, the distance by stroke style is not listed. What do I have to add, to have it listed there? The information are saved correct in the HKWorkoutEvent array in the workout.
Posted
by andre07.
Last updated
.
Post not yet marked as solved
2 Replies
548 Views
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.
Posted
by andre07.
Last updated
.
Post not yet marked as solved
0 Replies
316 Views
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?
Posted
by andre07.
Last updated
.
Post not yet marked as solved
1 Replies
705 Views
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) } }
Posted
by andre07.
Last updated
.