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

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.

Related

Can iOS 12 app extension write to Healthkit

When first released, docs stated that Healthkit could not be accessed from app extensions:
For example, in iOS 8.0, the HealthKit framework and EventKit UI
framework are unavailable to app extensions.
WatchOS 1 also could not access Healthkit, but that changed with WatchOS 2
Does anyone know if that restriction is still present in current versions of iOS? The name of one API call and one SO post give me hope, but still unclear if that only applies to WatchOS extensions.
Can't find any clear statement, specifically looking for use in intents/Siri Shortcut functionality. Only looking to write data, not read.
Extensions have been able to use HealthKit since at least iOS 10.0 and watchOS 3.0.
I have a similar situation. I have my app with a widget. I tried to use 'import EventKitUI' in one of my swift file in the main app. Now, if I check mark the target membership to include my widget, it won't work. I would get error "Could not build Objective-C module 'EventKitUI'" Once I removed the check mark, everything works just fine.
Don't know the reason behind this but it is just I found out.

dyld`__abort_with_payload: Without an error message

When I start my app with Xcode, I have a crash, but without an error.
The app is just stopping on this thread:
What can I do to have more information about the issue?
If you are using custom frameworks, you need to put it inside the "Embedded Binaries" section located in the Xcode project under the tab Target / General.
For me a simple Clean and Rebuild sorted it out.
This problem appeared after a system update up to macOS 10.15.2 beta (Catalina). Disabling "Thread Sanitizer" solved the issue (Xcode 11.2). Now I can't use Thread Sanitizer and have to wait for the next OS update.
Adding the framework to the embedded binary asset list fixed this. Here is what the setup of a foreign framework looks like in final form in the Xcode GUI as an Embedded Framework (Xcode 9.2, personally I like a visual breadcrumb trail better ;-) ):
Did Apple intentionally crash the runtime to somehow tell the developer about the problem that you cannot use non-Apple frameworks as simply linked frameworks in iOS development? It would be better to have it come up as a build error I would think... with a button that said "move it!"
The use of Embedded Binaries keeps the end user from having to add the Framework independently of your app (or have you do with an installer). In the case of the iPhone (iOS), that is impossible, but on macOS, it is possible, but it can get messy fast.
For the end user, it is much nicer to simply drag and drop an app to install it on macOS, which is where embedded becomes a benefit. Embedding also avoids the classic "DLL conflicts" of having external versions of your framework to manage. (Disk space is cheap, but my customer's time is precious.)
I fixed the error in my project just now!
If you are using the Swift framework in an Objective-C project, I advice you to change the build settings.
Set the Always Set Embed the Swift Standard Libraries option to Yes. Like this:
It was finally solved!
Making the framework "optional" instead of "required" worked for me.
To answer the original question "What can I do to have more informations about the issue?", this Apple forum thread provides a very simple tip: simply run your crashing app outside Xcode (i.e., stop it from Xcode, then run it manually on your device).
This will produce a crash log containing more details about what happened. You can then review this log from the Xcode Window menu → Devices and Simulators → View Device Logs.
In Xcode 11.1, turn off Do not Embed in Embed & Sign is a nice option.
Credit: mkonovalov's answer and William Cerniuk's answer
Unchecking "Guard Malloc" in diagnostics worked for me.
Continue the execution to see if any message shows up in debugger such as "MyFramework.framework" not found. If that is the case, follow this question: OS X Framework Library not loaded: 'Image not found'
For me Amos Joshua's answer worked.
Make sure you have added your binaries through "Embed Binaries" section.
Make sure you have enabled signing of frameworks in build phase section.
Make sure the embedded frameworks are not symlinks.
You can make the linked frameworks optional instead of required in "Link binary with libraries" phase. This will tell iOS to not look for these frameworks during launch. But anyway you need to fix the errors to use those frameworks!
Check if all the info.plist entries are good. In my case, I was using a Mac info.plist file for iOS. It was looking for some xib file which was not present in the iOS project.
Do a clean and build after any such change. This is required because Xcode does not copy/change these files if they already exist.
Remove the app from iPad and then install. Same reason as 7.
I had just missed applying the "Privacy - Camera Usage Description" in the info.plist file.
I faced the same issue with Xcode 11.3 and macOS v10.15.2 (Catalina) . The app was running well on the device, but not in the simulator. It seems there is an issue with the simulator and the workaround is to disable Thread Sanitizer.
Refer to Xcode 11.3 simulator SIGABRT on launch.
I encountered an error with the same signature (my project was in Objective-C) and discovered I had forgotten to link with the appropriate framework. The error message in the debug log that led to finding the error was:
dyld: Symbol not found: OBJC_CLASS$_SFSafariViewController
For my specific error, adding SafariServices.framework in the Targets → Build Phases → "Link Binary With Libraries" resolved the issue. While you probably don't have the same specific error and resolution, checking the debug log for clues is useful.
Sometimes it happens when you use system frameworks that are accessible only from a later iOS version than your target version. It might be fixed by marking this linked framework as optional.
For example, a project targeted on iOS 11 and being using AuthenticationServices for the iOS 12 AutoFill feature will crash on iOS 11 in the described way.
I had a similar issue that was resolved by a missing permission specification in plist (as weird as it is...).
I've tried to use AVCaptureDevice and it just crashed at starting (my app was very minimal).
Adding Privacy - Camera Usage Description to the info.plist file solved it for me.
I've had this situation after updating Xcode to v10.2.1 and Swift to v5.0.
If you are using Carthage + RxSwift, the new RxSwift uses RxRelay.framework. You should go to your /Carthage/Build directory find that framework and drag it to your project. Don't forget also add it to your carthage copy-frameworks script:
$(SRCROOT)/Carthage/Build/iOS/RxRelay.framework
It was resolved thanks to fred's answer.
I had this issue and didn't have success with the answers.
I was using a custom framework that would connect with Bluetooth devices. So the crash was happening because I had missed applying the "Privacy - Bluetooth Always Usage Description" in the info.plist file.
Check all your permissions fields are set up in the p-list file.
I was facing the same issue. Setting 'Always Embed Swift Standard Libraries' to Yes in Build Settings of my target worked for me.
If you use the Carthage build framework, after dragging the framework to your project, you should add it to General/Embedded Binaries.
I found the right way to resolve it.
Make sure the AppleWWDRCA.cer is set to the system default mode, and then it will work:
If you're using a framework written in Swift in an Objective-C application, you need to include the Swift toolchain in the app that consumes the framework.
The way I've found to do this is to create a dummy Swift file in the app, so that Xcode recognizes Swift and appropriately adds it to the project. You can then delete the dummy file.
Also if you are using custom frameworks, make sure you set the Mach-O type to static library. I read somewhere that iOS doesn't allow dylib. Anyway, this worked for me.
To add to the long list of encounters with this error, it occurs when I am on Xcode 12.2 Beta 2 deploying to my Mac running macOS v10.15.5 (Catalina) with the deployment target set to macOS v11.0 (Big Sur).
This situation happened because I was trying out the Mac Catalyst Tutorial app on adding a SideBar. Switching the target to macOS v10.15.5 eliminated the error and launched the app properly.
I faced this issue on iOS 14.5 when playing/implementing ATT (App Tracking Transparency) and have yet to add a usage description in file info.plist on why user tracking is needed.
The app crashes whenever the settings "Allow Apps to Request to Track" was enabled (when disabled, everything worked well).
The crash in Xcode provided no clues, except
libsystem_kernel.dylib`__abort_with_payload: (SIGABRT)
CoreSimulator 757.5 - Device: iPhone 11 (29AD27B2-6EC0-4B9C-8C8C-C5450695A19C) - Runtime: iOS 14.5 (18E182) - DeviceType: iPhone 11
Using the answer from fred's answer and getting the crash log from the actual device yielded this clue which was extremely helpful.
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: TCC, This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSUserTrackingUsageDescription key with a string value explaining to the user how the app uses this data.
Triggered by Thread: 1
I fixed it by changing "Embed & Sign" to "Embed without Signing" under General > Frameworks, Libraries and Embedded Content.
I didn't think this applied to me because I wasn't using the camera, but it did.
Many answers reference adding a Usage Description to Info.plist. I didn't know there are many more cases where a usage description is necessary (besides just the camera), see this link.
The link lists these services as needing a usage description or will cause this error:
Calendar, Contact, Reminder, Photo, Bluetooth Sharing, Microphone, Camera, Location, Heath, HomeKit, Media Library, Motion, CallKit, Speech Recognition, SiriKit, and TV Provider.
Add an entry to Info.plist, start typing "Privacy" as the key, and you will see all the available options pop up.
I've just had the same issue and the reason why was due to the fact that I've revoked my Developer Certificates and created new ones with Xcode 10, after a fresh macOS v10.14 (Mojave) update (for some reason, it deleted all login credentials and outdated some keychain certificates).
So, all I had to do was to remove the installed apps from my device and run them through Xcode again, in order for it to install the right new Provisioning Profile in my device :)
Actually, I had the issue with Xcode 11.3.1 and Thread Sanitizer was already turned off as mentioned in previous answers.
In my case, the issue was I used to have different Xcode versions in my Application folder like this:
/Applications/xcode11.3.1/Xcode.app
/Applications/xcode11.3/Xcode.app
/Applications/xcode10.1/Xcode.app
and
/Applications/Xcode.app - was 11.2
The build system looks on the /Applications/Xcode.app file by default. So bringing Xcode 11.3.1 to the /Applications/Xcode.app finally resolve the problem.
The same issue happened with me. I had iOS 14 Beta and the problem was fixed when I updated it to the official version.
I have fixed my error in my project.
I checked the other threads when the error happened. I found my error is about the camera.
Add the Camera privacy in the Info.plist file.
Open the info.plist file.
Add a new key called "Privacy - Camera Usage Description" and enter a string that describes why the app need camera. The describes will display when your app need to use the privacy.

WatchOS 2 App fails to launch on device with dyld_fatal_error for my Framework Library not loaded: Image not found

I've just followed the apple transition guide to upgrade my ObjectiveC app to WatchOS 2
https://developer.apple.com/library/watchos/documentation/General/Conceptual/AppleWatch2TransitionGuide/ConfiguretheXcodeProject.html
With the section "Sharing Code Between an iOS App and a watchOS App" describing how to duplicate an existing iOS framework into a WatchOS framework target for use by WatchOS as follows.
"If you already have a watchOS 1 app that shares a framework with your iOS app, duplicate your iOS framework target and modify it to support watchOS 2.
To duplicate and configure your framework target for watchOS 2
Open the project editor pane of Xcode. (The pane is normally closed.)
Control-click the target to display a context menu with a Duplicate command.
Change the name of the target so that you can identify it easily later.
In Build settings, change the following values:
Change the Supported Platforms setting to watchOS.
Change the Base SDK setting to the latest watchOS.
Change the Product Name setting so that it matches the name of your iOS framework. You want both frameworks to be built with the same name.
Add the framework to your WatchKit extension’s list of linked frameworks."
I've followed these steps to clone my framework which with the iOS framework was called MyFramework, and now the new WatchOS framework is called MyFrameworkWatch. But as described above the Product Name is set to MyFramework instead of MyFrameworkWatch. I presume this naming shift is so that I can include from my framework using
#import <MyFramework/SharedUtils.h>
instead of presumably having to change it to
#import <MyFrameworkWatch/SharedUtils.h>
I wouldn't mind the latter but I'll admit its nicer keeping the framework name the same.
After a bit more work beyond the initial automatic transition I managed to get my app working perfectly well on the simulator, but now switching to device i just can't get it to launch.
Launching my app on the device causes it to spin for a few seconds and then just crash. Launching the glance just causes it to spin indefinitely. Trying to run it from Xcode and running the app causes the app to eventually launch and spin, the spinning can last indefinitely sometimes, but eventually it gets through and i get the actual error reported as follows
dyld_fatal_error - dyld: Library not loaded: #rpath/MyFramework.framework/MyFramework referenced from WatchKit Extension Reason: image not found
So this is my Watch App Extension trying to link to the Watch framework, and doing so looking for the MyFramework name, not the MyFrameworkWatch name. I wonder if this name clashing has caused it to get confused?
When I try to find the frameworks referenced under the Products folder in Xcode I can see two frameworks
MyFramework
MyFramework
they're both reference the same path
/Users/jim/Library/Developer/Xcode/DerivedData/MyApp-byegspjumgwlfpahhwjgzpmfkcdx/Build/Products/Debug-iphoneos/MyFramework.framework
though you can see the target membership is separating the two frameworks, the top MyFramework is associated with the main app, today widget and framework tests project. The lower MyFramework is just associated with my Watch extension. It doesn't feel right that these are referencing the exact same path surely?
Finally when googling for this issue I've found reference of CocoaPods having similar problems though according to their site here
https://github.com/CocoaPods/CocoaPods/issues/4180
It's been fixed since September in version 0.39.0, which is the version that pod --version reports. So I presume I have their fix. I'm tempted to remove the cocoa pods from my framework to see if it helps.
Has anyone else followed the transition guide suggestions for creating a duplicate framework and then managed to get the app and framework actually installing on their watch ok?
Is there any way to analyse the build that is done to try and see if i can see problems with the built files so i don't have to wait for the watch to fail to launch the app to debug it.
Any help is really appreciated as always! Cheers!
Edit: I think I've managed to remove cocoa pods from the offending MyFrameworkWatch target by commenting out the target section in my pod file and running pod update/pod install... it didn't seem to clean up the target very well so i had to manually remove the cocoa pod steps in the post build step. Maybe i've not removed it properly, i find it a little confusing to know what is going on under the hood with cocoa pods. Regardless the same error occurred, so either i didn't remove it properly or it has no effect on this particular problem
Ok, this was caused by the apple documentation for transitioning being wrong, or me interpreting it wrong. It says
Add the framework to your WatchKit extension’s list of linked frameworks.
Where as actually the correct fix was to add the framework to the embedded binaries section (which automatically adds an entry to the linked frameworks anyways) and correctly places the framework within the watch extension under a Frameworks directory. Which the app then loads fine! So much frustration, I lost hours to this across a few days!!

Will Parse working correctly if I set StoreKit's status to optional in Build Phases

I would like to use the Appirater library in my project, but after reading its install tutorial one thing is not clear.
Be sure to change Required to Optional for StoreKit in your target's
Build Phases » Link Binary with Libraries section.
If I set the status of the StoreKit framework to Optional from Required, will this affect anything that is related to my Parse implementations? Because the Parse iOS SDK also requires StoreKit. Or switching to Optional means the framework will be loaded when it's needed only and don't have any side effects so Parse will also work properly? Am I right or it's not easy like that?
I would really appreciate if somebody could give me some guidance, thanks.
tl;dr It doesn't matter. Optional or Required are effectively the same for StoreKit in 2015.
Setting a framework to be Optional is essentially telling the system "Don't crash this app if you can't find this framework on the iOS device you are running on". StoreKit was introduced a long time ago in iOS so it's very unlikely that there are still devices with iOS versions before 3 (when StoreKit was introduced).
The only reason the Appirater instructions say to set it to Optional is because at the time those instructions were written, there were still a lot of iOS devices out there with versions of iOS that didn't have StoreKit, and Appirater could run without it, so there was no reason to crash the app over it. Thus, the instructions say to make it Optional.
That said, I should just simplify the Appirater setup and #import StoreKit in Appirater.h so nobody has to deal with that anymore.

Fails to distribute my app: "Your app contains non-public API usage."

After I fixed some bugs and refactored my project which has been release on App Store, it fails to distribute. The Xcode shows the following error message:
Your app contains non-public API usage. Please review the errors, correct them, and resubmit your application.
The app references non-public symbols in Payload/XXX.app/XXX: UICreateCGImageFromIOSurface
XXX is the app name.
I've search the entire project, and didn't find any this keyword (UICreateCGImageFromIOSurface). How can I fix this?
Remove Reveal.framework from your project. This should not be linked in release mode of your binary.
You app contains code not only from sources, but from all statically linked libraries. You have to check all of those for containing private call. Looks like at least Reveal library contains it.
Double check any third-party libraries you are using in your project
I was facing the issue and after checking my pods file, I found that Look Back - Framwork which is available for debug builds only as for as I know. So removing that fixed the issue. Successfully submitted app through Xcode 6.1 for Apple Testflight beta testing :)
Never ship an app linked against the Reveal library. Reveal exposes
your app to deep introspection and will likely cause your app to be
rejected by the Apple review team. Reveal is intended for internal
development and debugging purposes only.
The Reveal service will stop automatically while the iOS host app is
not the frontmost app. It will automatically start again when the app
is re-opened.
Reveal supports inspection of applications compiled against iOS 6 and
later. The iOS Deployment Target build setting must also be 'iOS 6.0'
or later. You may see link errors if this is not the case.
Reveal uses Bonjour to connect with the running iOS application. If
you are running the iOS application on a device, it will need to be
on the same network as the Reveal Mac app to be able to connect with
it. If you have any problems connecting to your application check
your firewall and proxy setting to ensure they are not blocking
communications.
Find out more...
cordova plugin rm cordova-plugin-ionic-webview
cordova plugin add cordova-plugin-ionic-webview#4.1.0

Resources