How can my app know if it is opened from widget? - ios13

I have set up a widget and made it able to open the main app successfully. But I can't seem to make the main app "aware" of the way it's opened. I want the app to be able to distinguish the way it's opened, be it from (1) the main screen or (2) the widget. In the case of (2), the app should then proceed to read from UserDefaults(suiteName:).
Yes, there are many similar questions here but I have not yet find a solution.
These are functions in the AppDelegate.swift did not even get called (and I have no idea why):
1.
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool
2.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
3.
func applicationWillEnterForeground(_ application: UIApplication)
4.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool
This is my first try on Today Extension and please send help if you've found the problem or want to know more of my code. Thank you in advance!

Related

watchOS 9 WidgetKit complications missing com.apple.developer.healthkit entitlement

I have an iOS/wOS app that launched last year. Now I want to add complications to it and use the new way of doing complications with WidgetKit. I have everything in place up to the point where I'm supposed to read the data from Health to display it, where it fails with Missing com.apple.developer.healthkit entitlement.
This is the new extension I've added
It's embedded in the WatchKit app NOT in the WatchKit Extension and I've added permission to read health data directly in the info.plist for the extension
I pull the data from the TimelineProvider protocol method
func getTimeline(in context: Context, completion: #escaping (Timeline<Entry>) -> ()) {
let currentDate = Date()
var entries: [WorkoutEntry] = []
ComplicationHealthManager.loadPreviousWorkouts { workout in
let workoutEntry = WorkoutEntry(date: currentDate, workout: workout)
entries.append(workoutEntry)
let timeline = Timeline(entries: entries, policy: .after(currentDate))
completion(timeline)
}
}
with the help of a small manager class
class ComplicationHealthManager: ObservableObject {
static func loadPreviousWorkouts(completion: #escaping (HKWorkout?) -> Void) {
let healthStore: HKHealthStore = HKHealthStore()
let workoutPredicate = HKQuery.predicateForWorkouts(with: .traditionalStrengthTraining)
let compound = NSCompoundPredicate(andPredicateWithSubpredicates:
[workoutPredicate])
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate,
ascending: false)
let query = HKSampleQuery(
sampleType: .workoutType(),
predicate: compound,
limit: 0,
sortDescriptors: [sortDescriptor]) { (query, samples, error) in
guard
let samples = samples as? [HKWorkout],
error == nil
else {
completion(nil)
return
}
let calendar = Calendar.current
let todaysSamples = samples.filter{ calendar.isDateInToday($0.endDate) }.last
completion(todaysSamples)
}
healthStore.execute(query)
}
}
The issue is in the closure for the health query where it returns with no workouts but an error stating
Error Domain=com.apple.healthkit Code=4 "Missing com.apple.developer.healthkit entitlement." UserInfo={NSLocalizedDescription=Missing com.apple.developer.healthkit entitlement.}
The problem here is I don't understand where and how to add an entitlement for the complication extension or the WatchKit app, as none of them have the option for health. I have a health entitlements set for the iPhone app and the WatchKit Extension.
I found the problem to be that I had the old implementation of watchkit apps, with both a Watch app and a Watch extension. That was the problem. I went and used the migration from Xcode 14 to merge the Watch App and Extension into a new watch app and everything works now.
Please file a Feedback at feedback.apple.com for this.
You can manually add the HealthKit entitlement to the Code Signing Entitlements file (create a new one if there isn't one already) associated with the target
<key>com.apple.developer.healthkit</key>
<true/>

How do I update Xcode codes I can use iOS 14 functions?

I was watching a tutorial on how to fetch user location in swift and I had a problem here:
class teste: CLLocationManager, CLLocationManagerDelegate{
#Published var lctionManager = CLLocationManager()
func locationManagerDidChangeAuthorization (_ manager: CLLocationManagerDelegate){
switch manager.authorizationStatus {
case .authorizedWhenInUse:
print("authorized")
case .denied:
print("denied")
default:
print("unkown")
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error){
print(error.localizedDescription)
}
}
The error was a in locationManagerDiChangeAuthorization (Instance method 'locationManagerDidChangeAuthorization' nearly matches optional requirement 'locationManagerDidChangeAuthorizantion' of protocol 'locationManagerDelegate') and in manager.authorizationStatus( Value of type 'CLLocationManagerDelegate' has no member 'authoizationStatus')
After some research, I found out that these are iOS 14 only, and my code may be written in iOS13 (actually, for some codes, I have to add #available(iOS 14.0, *) to make them work, but this time it didnt seem it work).
But, as a beginner, I don't know how to update my code (searched for some stuff but nothing caught my eyes). How do I update my code? Would it interfere in anything? Is it necessary or its better to write something to integrate both iOS 14 and 13?
Project -> Info -> iOS Deployment Target
here you can change deployment target to iOS 14.

RealmSwift 3.0.2 and Swift4 issue

Using RealmSwift-3.0.2, Cocoapods-1.3.1, Swift-4.0.3, iOS-11.2, XCode-9.2
I am trying to create a Realm object (as I always did the last three years).
But since Swift4, something seems off !
I get the following Error-message:
libc++abi.dylib: terminating with uncaught exception of type NSException
Below is my code:
import RealmSwift
var rlm: Realm?
override func viewDidLoad() {
super.viewDidLoad()
// instantiate Realm
self.rlm = try? Realm() // !!!!!!!!!!! Here is where the above error happens...
}
My PodFile looks like this:
project 'MyApp.xcodeproj'
workspace 'MyApp.xcworkspace'
platform :ios, '11.2'
inhibit_all_warnings!
source 'https://github.com/artsy/Specs.git'
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
def shared_pods
pod 'RealmSwift'
end
target 'MyApp' do
shared_pods
end
target 'MyAppTests' do
shared_pods
end
target 'MyAppUITests' do
shared_pods
end
Any help appreciated !!
I found the error:
My Realm object had a wrong primary-key (i.e. type-fault !!)
override static func primaryKey() -> String? {
return "myID" // !!!! Was "mID" :/ :/
}
After correcting the type-fault, it all works again nicely !
(...would be nice if the RealmSwift error message was somehow more explanatory...)

Handling user notifications on iOS 10

I have troubles determining when the user taps on a user push notification on iOS 10.
So far, I have been using the -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] which is called when
Case 1: the application is active and the push is received
Case 2: when the user launched the app after taping a received notification
This method comments explicitly say
Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented.
All this work as expected.
Now iOS 10 deprecated this delegate method and introduced the UserNotification framework which I cannot use because I'm still targeting iOS 8 and 9.
When my app is running on iOS 10 and a push is received while the app is active (Case 1), the -[AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] is called correctly.
Again on iOS 10, when the user starts the app by tapping a notification (Case 2) this method is not called.
I realise that when I implement the older -[UIApplicationDelegate application:didReceiveRemoteNotification:] it is the one that gets called in the Case 2
On iOS 8 and 9, in the Case 2 it is the -[AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] method is called.
Does it mean that I have to update my application and implement the older delegate just for iOS 10?
So the question is, what is the proper implementation of handling the user interaction of a received push on iOS 10 without using the UserNotification framework.
cheers,
Jan
Swift code for iOS 10:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.currentNotificationCenter()
center.delegate = self
}
// ...
return true
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
print(response.notification.request.content.userInfo)
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
print(notification.request.content.userInfo)
}
We were facing the same problem here and we were only able to solve this problem on iOS 10 GM release by using the code on the answer given here: https://forums.developer.apple.com/thread/54332
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
if (version.majorVersion == 10 && version.minorVersion == 0) {
[self application: application
didReceiveRemoteNotification: userInfo
fetchCompletionHandler: ^(UIBackgroundFetchResult result) {
}];
}
With this fix our code started working again both on iOS 9 and 10.
We also had to change the way we handle application state behavior (UIApplicationStateActive, UIApplicationStateInactive and UIApplicationStateBackground) on push notifications, as it seems it also changed on iOS 10
EDIT:
It seems that application state behavior is back to normal on latest iOS 10 versions.
This has been fixed in iOS 10.1 Beta 1 !!
The -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] is correctly called when the user taps on a notification.

writeCopyToPath Realm Doesn't work

I try to follow "Bundling a Realm with an App" Documentation.I've try to use method Realm().writeCopyToPath(_:encryptionKey:)) but the problem is i can't make a file on a specific location on my OSX. It's show error that file already exits. Please give me a correct way to use writeCopyToPath
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = UIViewController()
window?.makeKeyAndVisible()
NSFileManager.defaultManager().removeItemAtPath(Realm.Configuration.defaultConfiguration.path!, error: nil)
// Create a standalone object
var mydog = Dog()
// Set & read properties
mydog.name = "Rex"
mydog.age = 9
println("Name of dog: \(mydog.name)")
// Realms are used to group data together
let realm = Realm() // Create realm pointing to default file
println(realm.writeCopyToPath("/Users/taforyou/CU-TEP",encryptionKey: nil))
// Save your object
realm.beginWrite()
realm.add(mydog)
realm.commitWrite()
return true
}
}
Output Log When running
Name of dog: Rex
Optional(Error Domain=io.realm Code=4 "open() failed: File exists" UserInfo=0x7fbc704a8cd0 {NSLocalizedDescription=open() failed: File exists, Error Code=4})
Thank you
realm 0.95
The error message getting printed says it all: the file you're trying to create (/Users/taforyou/CU-TEP) already exists. Note that the path that writeCopyToPath is expecting is a full path to the resulting realm file (/path/to/file.realm, not /path/to) just in case CU-TEP is actually a directory.

Resources