I'm trying to use WeatherKit to just get a simple weather forecast for a location.
do {
let location = CLLocation(latitude: 37.3346, longitude: -122.0087)
let weather = try await WeatherService().weather(for: location)
} catch {
print(error)
}
When I run this on a physical device, I get an empty Weather object and the following in the console:
[WeatherDataService] Response did not contain requested dataset: .appLocationConfig. Returning default value: AppLocationConfig(reportAnIssue: ReportIssueLocationConfig(position: beforeFooter, minDaysSinceInteraction: 0), expireTime: 2022-11-27 04:31:20 +0000
Xcode is managing my provisioning profile, I've added the WeatherKit capability, and I have an active Apple Developer Program membership, so I don't think I should be having any problems accessing WeatherKit. What's going on, and how can I fix it?
Related
I'm a little bit confused about addSnapshotListener and getDocuments. As I read in the firebase docs, getDocuments() is retrieving data once and addSnapshotListener is retrieving in real-time.
What I want to ask.
If I'm using getDocuments, and im changing some documents in the Firestore , it will not make the change in the app ? But if im using addSnapshotListener it will ?
I'm making an delivery app, which is the best to use to store pictures of food , descriptions etc.
This is what im using to retrieve labels and pictures from my app :
db.collection("labels").getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let newEntry = Labels(
firstLabel: data["firstLabel"] as! String,
secondLabel: data["secondLabel"] as! String,
photoKey: data["photoKey"] as! String
)
self.labels
.append(newEntry)
}
}
DispatchQueue.main.async {
self.tableViewTest.reloadData()
}
getDocuments will return results one time, with the current Firestore data.
addSnapshotListener will return an initial result set (same as getDocuments) and get called any time that data changes.
If your data is modified in Firestore and you've used getDocuments, your app will not be notified of those changes. For example, in your delivery app, perhaps the item goes out-of-stock while the user is using it. Or, the price gets changed, the user is logged in from another device, etc -- many possibilities for why the data might change. By using a snapshot listener, you'd get notified if any of these changes happen.
However, if you're relatively confident you don't need updates to the data (like getting a user's address from the database, for example), you could opt to just use getDocuments.
In the video Configure and link your app clips Apple shows it's possible to have your AppClip being suggested by Siri based on the user's location.
I can't find this in the docs https://developer.apple.com/documentation/app_clips
Is this purely based on which location other users are using this app, or is this something a developer can configure (maybe based on a geocode region)?
According to an Apple App Clips engineer I spoke to at WWDC, in order to get your App Clip published onto Apple Maps, you need to have a registered business registered with Apple. This can be done since iOS 10, via Apple Maps Connect, and registering as a small business.
The Nearby Siri suggestion is based on location data and only appears when your App Clip is associated with a place card on Apple Maps so you do not have control over this. It's definitely possible to get the user location after downloading the App Clips, as showed in the following demo but from your question I presumed you wanted to present the App Clip suggestion before downloading (isn't in the developer's control).
If you want to register an App Clip to a location, you need to wait till App Clips are fully usable and publishable on the App Store. When TestFlight and App Store Connect get support for app clips later this year, you'll be able to invoke an app clip from NFC, QR codes, Maps and more. So you would need to register your business with Apple, register your placecard in Apple Maps and then enable App Clips to get the suggestion.
There is a sample code documentation page that has Widgets and App Clip in the code: https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui
In the link above in the App Clip code section, there is a payload that has latitude and longitude configurable. Siri should automatically suggest the App Clip based on the location you put in the latitude and longitude.
#if APPCLIP
func handleUserActivity(_ userActivity: NSUserActivity) {
guard let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems else {
return
}
if let smoothieID = queryItems.first(where: { $0.name == "smoothie" })?.value {
model.selectSmoothie(id: smoothieID)
}
guard let payload = userActivity.appClipActivationPayload,
let latitudeValue = queryItems.first(where: { $0.name == "latitude" })?.value,
let longitudeValue = queryItems.first(where: { $0.name == "longitude" })?.value,
let latitude = Double(latitudeValue), let longitude = Double(longitudeValue) else {
return
}
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: latitude,
longitude: longitude), radius: 100, identifier: "smoothie_location")
payload.confirmAcquired(in: region) { inRegion, error in
if let error = error {
print(error.localizedDescription)
return
}
DispatchQueue.main.async {
model.applePayAllowed = inRegion
}
}
}
#endif
The code snippet is from the documentation from link above.
The documentation doesn't go in specific details yet but from what you can read here:
https://developer.apple.com/documentation/app_clips
and here https://developer.apple.com/documentation/app_clips/configuring_your_app_clip_s_launch_experience
under "Review Advanced App Clip Experiences"
You should be able to associate your app clip with a physical location, which will be available in AppStore Connect and with this set, Siri suggestions should be able to pick up your App Clip based on the user location
we recently started developing an uber like app for iOS using Firebase Firestore and we need to store and constantly update the user's location on firebase and make it so that the other clients can retrieve it as well.
We are trying to store the user location in Users own document on firestore database, such like:
Collections > Users > "AutoGeneratedDocument" > UserLocation
with two key values latitude and longitude.
We've made some progress with the code, it writes the location data when we explicitly input a document path to it but we still don't know how to run a query and find the user's own document.
In order to save the location data to the users own document we need to be able to get the auto generated user document path for the currently signed in user.
So far we've come up with this:
func updateUserLocation() {
let db = Firestore.firestore()
let locman = CLLocationManager()
locman.requestWhenInUseAuthorization()
var loc:CLLocation!
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse || CLLocationManager.authorizationStatus() == .authorizedAlways{
loc = locman.location
}
let lat:Double = loc.coordinate.latitude
let long:Double = loc.coordinate.longitude
let geo = GeoPoint.init(latitude: lat, longitude: long)
let currentUID = currentUserUID
let val = db.collection("users").whereField("uid", isEqualTo: currentUserUID)
db.collection("users").document(val).updateData(["currentUserLocation" : geo])
}
We expect to get the path to the document which contains the signed in user's UID then store the user location key values in that specific document. But with our code, in the last line the document(val) part expects a string but our output with the "whereField" method apparently is a query.
You're going through users twice:
db.collection("users").whereField("uid", isEqualTo: currentUserUID).updateData(["currentUserLocation" : geo])
You can find many useful tips, tutorials on the official website.
Perform simple and compound queries in Cloud Firestore
I wanted to have same device id for the device even after re-installing the app. I was planning to save it to keychain and retrieve it every time.
I want to know if keychain data will get synced across all the devices using the same iCloud email id.
I am using the keychainwrapper in this downloadable_link.
This is what I ended up doing.
I read that the same UUID will be shared across all devices with same iCloud account.(Not sure about this.)
I had to restrict app login for upto 3 devices for each email id. If keychain data will get synced, then I cannot do this . If I have 3 different iPhones, it will be considered as a single device only if the user uses same icloud account.
After some googleing I came across SAMKeychain.
It has a property called synchronizationmode which I think will do the job of preventing the keychain key /value from syncing it to iCloud.
I use the below code to generate UUID.
func UUID() -> String {
let bundleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
let accountName = Bundle.main.bundleIdentifier! + String(Bundle.main.bundleIdentifier!.characters.reversed()) // just one extra layer of protection.. :p
var applicationUUID = SAMKeychain.password(forService: bundleName, account: accountName)
if applicationUUID == nil {
applicationUUID = (UIDevice.current.identifierForVendor?.uuidString)!
// Save applicationUUID in keychain without synchronization
let query = SAMKeychainQuery()
query.service = bundleName
query.account = accountName
query.password = applicationUUID
query.synchronizationMode = SAMKeychainQuerySynchronizationMode.no
do {
try query.save()
} catch let error as NSError {
print("SAMKeychainQuery Exception: \(error)")
}
}
return applicationUUID!
}
You can check the sample app in swift 3 here in GITHUB.If someone has a better answer , Please let me know.
NOTE: SAMKeychain from their official github page was not working properly for me. Please use the one I am using in the UniqueUUIDAPP. I had to make some code commenting to make it work.
I would like to enable the users of my iOS app to search for nearby locations (mainly streets and POIs). The behavior should be pretty much the same like when searching for an address in the native Apple Maps App. I first tried to implement this by using MKLocalSearch but I only received POIs as results and wasn't able to search for nearby streets for example. I don't see any possibility to alter the search behavior of MKLocalSearch.
Here is my code:
let request = MKLocalSearchRequest()
request.region = mapRegion!
request.naturalLanguageQuery = searchText
let localSearch = MKLocalSearch(request: request)
localSearch.startWithCompletionHandler({(response: MKLocalSearchResponse?, error: NSError?) -> Void in
if error != nil {
print("Error during local search: \(error!)")
}
if response != nil {
self.placemarks = response!.mapItems
self.tableView.reloadData()
}
})
In my second attempt I tried using CLGeocoder but the results where so bad compared to the native app results. Most of the top results where located in the US event though I'm in europe. I double checked the value for my current location and it's definitely set to my location using a circular search radius of 1000 meter.
Here is the code:
let region = CLCircularRegion.init(center: currentLocation, radius: 1000, identifier: "")
geoCoder.geocodeAddressString(searchText, inRegion: region, completionHandler:{(response: [CLPlacemark]?, error: NSError?) -> Void in
if error != nil {
print("Error during local search: \(error!)")
}
if let result = response {
self.placemarks = result
self.tableView.reloadData()
}
})
Am I doing something wrong or are both APIs really that bad? My last attempt would be to implement this functionality by using the Google maps API. As I'm currently using the Apple maps (MKMapView) I would probably have to replace the map itself as well because Google doesn't allow showing their geocoder results on an Apple map, am I right?
Would be a huge disappointment if I'm not able to get this functionality working with MapKit in Europe but maybe it works just perfect in the US.