Watch OS keychain sharing - ios

Is it possible to access the shared keychain in WatchOS 4+?
I've set the exact same Keychain Sharing > Keychain Group of the iOS app (which syncs perfectly with a MacOS app), but all it finds is an empty object.
I'm using this library (https://github.com/kishikawakatsumi/KeychainAccess) which works really well on iOS and MacOS, but not on WatchOS.
I shared the Target Membership of the classes involved to the Watch Extension (and I think it works, otherwise it would throw an error that was able to get the method or so), added the pod to watchOS like this
use_modular_headers!
def shared_pods
pod 'KeychainAccess'
end
target 'Watch Extension' do
platform :watchos, '4.0'
shared_pods
end
My question is: am I missing some configurations? It looks like it is able to access the local keychain, but cannot sync with the shared one.
Thanks

I was attempting to do the same thing, and it's a great pod to use to make the keychain easy to work with. However the part that needs to work is the iCloud Synchronizing for it move the data like you are thinking.
According to the current Apple Docs, in the notes under the Storing Data Securely in the Keychain
NOTE
The kSecAttrSynchronizable key is not available in watchOS.
Without that, the WatchOS can not get the keychain data you have stored over on the iOS side. So you're doing the pods right, and it's a good pod, but WatchOS doesn't want us doing that.
TLDR; - You can't do it at this time.

Related

SKAdNetwork using Firebase SDK and Firebase Analytics

I am looking to integrate Firebase Analytics SDK into my apps, to be able to link with Google Ads so we can track ad campaign and attribution. Since our apps target kids space, we are not allowed to use any IDFA capabilities by Apple, so using anything like AdSupport.framework or ATT (App Tracking Transparency) it will risk app rejection. So, that leaves SKAdNework. According to Firebase Notes (https://firebase.google.com/support/release-notes/ios#version_6290_-_july_28_2020), SKAdNetwork will register for AdNetwork attribution automatically called on first open by default, and by setting the following key GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED YES in our Info.plist file, should opt in to this default behaviour. However, I have no way to verify this on device (i.e. I see no console message on the device, nor can't find this call in the code [SKAdNetwork registerAppForAdNetworkAttribution])
Is there anything else I am missing? Do I need to add SKAdNetwork Identifiers to my plist file, like this (https://developers.google.com/admob/ios/ios14#skadnetwork)?
Bellow is a sample copy of my pod file:
target 'UnityFramework' do
pod 'Firebase/AnalyticsWithoutAdIdSupport', '8.6.0'
pod 'Firebase/DynamicLinks', '8.6.0'
pod 'Firebase/InAppMessaging'
pod 'Firebase/Messaging', '8.6.0'
pod 'Firebase/RemoteConfig', '8.6.0'
end

AVFAudio Framework not present on macOS causes warning for iOS app (app should also be available on AS Macs)

My iOS app uses the AVFAudio framework to provide spoken feedback to the user while running. I would like this app to also run on Apple Silicon Macs (where the spoken feedback is not really necessary).
However, just importing the framework results in the following warning email after I upload to App Store Connect:
We identified one or more issues with a recent delivery for your app,
"App Name" 7.0 (24). Your delivery was successful, but you may wish to
correct the following issues in your next delivery:
ITMS-90863: Apple silicon Macs support issue - The app links with
libraries that are not present on Mac:
/System/Library/Frameworks/AVFAudio.framework/AVFAudio
I guess that this means the app will not be able to run on Macs.
How should I get this app to use the AVFAudio framework for iOS and still be available to run on macOS (AS Macs) with or without the framework on macOS?
Relevant code is:
import AVFoundation
class Speaker {
var speechSynth: AVSpeechSynthesizer
class func establishAudioSession() {
do {
try AVAudioSession.sharedInstance().setCategory(.playback, options: [.interruptSpokenAudioAndMixWithOthers, .duckOthers])
try AVAudioSession.sharedInstance().setMode(.voicePrompt)
try AVAudioSession.sharedInstance().setActive(true, options: [])
UPDATE / CLARIFICATION:
Note that my project does not include multiple targets. With multiple targets, this would be fairly straightforward. I am wondering if there is a way to achieve this by taking advantage of the newer AS Macs’ ability to run apps built for iOS without a separate target.
Is this possible when using this framework?
UPDATE 2:
I have submitted a support request to Apple for this now and their first suggestion was replacing
import AVFoundation
with
import AVFAudio
and then re-uploaded to App Store Connect, but after trying this, I get the same warning email back again. Will post an update (or hopefully an answer) when I hear back from them again.
I suppose your project has multiple targets defines (i.e. one for iOS and one for macOS). In the "General" tag of your target settings you can select which frameworks should be included under "Frameworks, Libraries and Embedded Content". Add your library for iOS, remove it for macOS.
If you share the same code you between apps you can also conditionally exclude some of it for macOS.
#if os(iOS)
// iOS only code
#endif
However, just importing the framework results in the following warning email after I upload to App Store Connect:
The problem probably isn't importing, but (as the message you got indicates), linking to AVFAudio, that's the problem. So solve that, you should select your app target in the Xcode project and go to the Build Phases tab. Look at the Link Binary with Libraries line and hit the disclosure button at the beginning of the line to reveal all the libraries that are linked into your app. Find AVFAudio and change the setting (there's a popup on the right side of the line) from Required to Optional. That'll let your app link to the framework if it's there, but still run if it's not.
But wait, you're not done yet... What do you think will happen if your app tries to actually use a framework that's not linked in (because it doesn't exist on the machine)? You'll get a crash, of course. To avoid that unhappy fate, you'll need to check for the existence of the framework before you use it. For example, you could do something like:
if NSClassFromString("AVAudioPlayer") != nil {
// do your AVFAudio stuff here
}
Further follow up from Apple support suggested the following:
Change back to import AVFoundation
Reduce the deployment targets from the latest and greatest back down to something less recent.
So I did both of these, changing the deployment targets from iOS 14.5 and macOS 11.3 to iOS 14.1 and macOS 11.0.
This has resolved (or worked around!) the issue.
I do want to deploy to the latest and greatest target for this particular app, so I don't consider it to be a complete solution as yet, but it will do as a work around for now. (I actually want to deploy to 15.0 when it's available to make use of the promised improvements to OSLogStore.)
So this sounds like a bug to me, and I have queried Apple for some further information on the issue, in particular, the ability to target more recent OS versions.

App rejected due to missing info.plist key

My app is getting rejected due to a missing info.plist key.
Missing Info.plist key - This app attempts to access privacy-sensitive
data without a usage description. The app's Info.plist must contain an
NSPhotoLibraryUsageDescription key with a string value explaining to
the user how the app uses this data.
I know how to "fix" it. It's just as simple as it sounds, just add NSPhotoLibraryUsageDescription to my info.plist with a description of what it's used for.
The problem is that I'm not using anything that should trigger this requirement. I do not want to add this description without knowing what it's for.
The only thing I can think of that could cause this problem right now is that one of the external frameworks I'm using via CocoaPods has something to do with it.
This is my podfile:
def myPods
pod 'HockeySDK', '4.1.2'
pod 'ReactiveCocoa', '2.4.7'
pod 'TTTAttributedLabel', '2.0.0'
pod 'GoogleMaps', '2.1.0'
pod 'GoogleAnalytics', '3.17.0'
end
target 'MainApp' do
myPods
end
target 'BetaApp' do
myPods
pod 'Instabug', '7.0.5'
end
I know for a fact that Instabug requires this key (along with the key for Microphone usage), but I'm not always including Instabug, as you can see.
Let's say I have two targets; MainApp and BetaApp. They each have its own info.plist. In BetaApp's info.plist, I have included the keys required. In MainApp I have not included them, because Instabug is not used in MainApp.
When I now try to upload the MainApp to AppStore I get this rejection.
I have also tried removing the Instabug-pod completely (even though it's just present in the BetaApp), and it still happens in MainApp.
I have never had this rejection in MainApp before (it's not a new app, just an update).
I think I have updated GoogleMaps since last release, and maybe some of the others as well, but I have no idea how to find out why Apple thinks I have to implement NSPhotoLibraryUsageDescription.
Is there a way to find out what part of my app is triggering this requirement?
I assume that if I implement the keys, they will never actually be triggered, and the user would never be prompted to allow access to the photos library (because I have no code that attempts to access the user's photos library), but I'd like to know why this is happening, and I'm reluctant to add it before I know..
I'd suggest you to follow instructions found in this answer
I understand that this might sound dumb to add NSPhotoLibraryUsageDescription key for no reason, however binary validation on the Apple's side is the process you don't have control over so it's simpler just to add this key.
As for the background reason, I believe, Apple validator looks for UIImagePickerController usage in binary, not only AssetsLibrary or Photos framework linkage. So if you'd like to get your app submitted & approved, you have either sanitize around this, or simply add required key.
If you think, you don't use it, take a look at ReactiveCocoa/UI/UIImagePickerController+RACSignalSupport.m, so, unless you are not ready to have a custom ReactiveCocoa or avoid it's usage, you'll have to deal with NSPhotoLibraryUsageDescription

Integrating Parse in App extension

I’m trying to implement parse functionality in a app extension. The main app uses Parse to push and retrieve data. The problem is I can't install the parse SDK to my app extension. Is this even possible? I've been on google for about three hours and I’m starting to think not. I've tried to init another pod file and I’ve tried the the abstract_target function. No matter what I do, I can't seem to import it. Has anyone achieved this before? Im using swift 2.0 if that helps.
If there is another way to carry out the following, please let me know:
(This happens in the share popup view)
1.Grab user input text
2.Push it to the parse backend
in order to use Parse ios SDK in your app extension you are require to do the following:
enable local data store (local data store is where your data is being saved locally on your device)
Enable app groups and keychain sharing in both of your targets (your main app and your extension) this allows you to share the data and the session between your app and your extension.
When i did it. I follow this guide which explain how to integrate apple watch and app extension with parse IOS SDK.
If you are using CocoaPods in your project please make sure that you load the Parse pod also to your extension..
so let's assume that the only pod that you have in your Podfile is pod 'Parse' you Podfile should look like the following
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
def my_pods
pod 'Parse'
end
# Change the MainAppTargetName to your main app target
target 'MainAppTargetName' do
my_pods
end
# change MyExtensionTargetName to your extension target name
target 'MyExtensionTargetName' do
my_pods
end

Keychain Sharing with watchOS 2 - All about project settings?

I am using Xcode 7.0 (7A220), targeting iOS 9.0 and watchOS 2.0.
I haven't gotten keychain sharing to work in a watchOS 2 app of my own, but it works in this example project, which is part of my question.
There is a good talk from NatashaTheRobot (here) where she goes over keychain sharing with watchOS.(Working code from github here), see for yourself that her iOS app and watch app are able to share via keychain in the simulator.
Here's what I have done to her project and it still works:
Removed the access group string from the KeychainItemWrapper init method. This makes sense because the simulator isn't code signed and the access group gets deleted in KeychainItemWrapper initWithIdentifier: (checkout the comment in initWithIdentifier:)
Removed the identifier string from KeychainItemWrapper initWithIdentifier in both view controllers
Removed the keychain-access-groups key from both entitlements that specifies a keychain access group key
You can remove these three things and keychain sharing still works in the simulator for this project. Why? Shouldn't entitlements at least be necessary?
The thing that finally breaks this project is changing the development team/provisioning profile, which makes me think project settings are the real key to this issue.
In my own project I have added a watchOS 2 extension, added the keychain sharing capability to both targets, added appropriate access groups even with my bundle seed ID, I have tried creating separate provisioning profiles for the iOS app, watchkit app, and watchkit extension. I'm sure I am forgetting things I've already tried, I have been attempting to solve this for about a week to no avail. What am I missing?
Apple's docs on creating capabilities are not super specific on project settings. It says to click and turn on capabilities in the project. Done that.
Apple's other docs on generic keychain use didn't clear it up for me either. They have a project with 2 targets that share a keychain, but as far as I can tell my project settings and theirs aren't significantly different.
This answer goes over the useyourloaf article from 2010 on keychain sharing, but like I mentioned before, it seems like the simulator completely ignores those keychain access group identifiers.
I keep thinking there must be something obvious I have missed throughout all of this. Any pointers would be greatly appreciated.
Since watchOS 2.0 it is not possible to share a keychain item between the watch and its paired device.
https://forums.developer.apple.com/thread/5938

Resources