Use Cocoa Touch Framework in iOS and WatchKit - ios

I have a Cocoa Touch Framework that I developed for using in both my iOS app and my WatchKit app on iOS 8. I have no problems with iOS 8, however when I move the project to iOS 9 and update the WatchKit app to run natively I get the following error:
ParkFinderKit was rejected as an implicit dependency for 'ParkFinderKit.framework' because it doesn't contain platform 'watchsimulator' in its SUPPORTED_PLATFORMS 'iphonesimulator, iphoneos'
I attempted to manually add watchossimulator and watchos to the list of supported platforms:
However this produces another error:
ParkFinderKit was rejected as an implicit dependency for 'ParkFinderKit.framework' because its SDK is platform 'com.apple.platform.iphonesimulator' and it needs to match platform 'com.apple.platform.watchsimulator'
Any ideas as to how to solve my issue?

Okay, it looks like you cannot use a Cocoa Touch Framework inside of a WatchKit app. I was able to get around this by creating a new Watch Framework target and then assigning each file from the original framework to the new framework in the Target Membership options.
This accomplishes my goal of sharing code between iOS and WatchKit without having duplicate code.

Related

Xcode 11 Beta won't build because of WatchKit?

Worked on Xcode 10. Now in the beta I can't build I keep getting this error:
a "WatchKit" is not available when building for iOS Simulator.
Consider using #if !os(iOS) to conditionally import this framework.
I had the same issue for one swift file in the WatchKit Extension. It turned out that it was a member of both the iOS app and the WatchKit Extension. I unticked the iOS app in the target membership section for the file so that it only belongs to the WatchKit Extension target. Now the project builds successfully.
Some of the functionality to communicate between the Apple watch with the iPhone/iPad used to be implemented within the WatchKit framework. But at some point it got moved into the WatchKitConnectivity framework.
If you look in your Target's "Build Phase" -> "Link Binary With Libraries" section, you will see the "WatchKit.framework" with "Optional" status. iOS13+ has become more "strict" so it won't build unless I completely remove the "WatchKit.framework", and instead add "WatchConnectivity.framework".
Also make sure your iPhone/iPad code refers use "import WatchConnectivity" instead of "import WatchKit".
We need to use "Conditional Imports" to resolve the issue.
Replace the import WatchKit header with the below code :
#if !os(iOS)
import WatchKit
#endif
This resolved my issue and build successfully in iOS 13.
Xcode 11 removes WatchKit from the iOS SDK. From release notes:
The WatchKit framework is no longer included in the iOS SDK. If you’re using WatchKit APIs from iOS, you need to remove this use. The WatchKit framework remains available on watchOS. If you’re using WatchKit APIs from iOS to infer availability of features on the paired Apple Watch, include information about your use case when you submit feedback to Feedback Assistant. (49707950)
This includes Cordova plugins that reference WatchKit in plugin.xml:
<framework src="WatchKit.framework" />
The above line will add WatchKit as a framework for the iOS app target. You'll need to remove this and add WatchKit only to Watch target of your app.

Building an embedded framework for WatchOS and iOS in Xcode 8 with Swift 3

I am in the process of porting an all iOS + WatchOS 1 app written originally in Swift 1, to the latest Xcode 8, WatchOS 3, Swift 3.
My app has an embedded framework with some common functionality that used to compile and run file for both the watchkit extension target and the ios app target.
With Xcode 8 I can no longer seem to get this to work. When I try to import the framework in the watchkit extension code, I get the module not found error.
Is it still possible to compile and use one single embedded framework package on both the target iOS and WatchKit extension targets? In my framework I have the target platforms set to watchos, watchsimulator, iphoneos, iphonesimulator.
My gut says it's not possible anymore. Where originally all the code really ran on the phone itself, not that codes runs on the actual watch and the phone, you'd need to compile an embedded framework specifically for each.
Short version: You can't. Create a duplicate target and set it to use the watch SDK.
Longer version from Apple's docs: https://developer.apple.com/library/content/documentation/General/Conceptual/WatchKitProgrammingGuide/iOSSupport.html#//apple_ref/doc/uid/TP40014969-CH21-SW1
including:
NOTE
After you create a separate framework target for your WatchKit
extension, you must manage the contents of that framework separately
for both iOS and watchOS. If you add files to the iOS version of the
framework, remember to add them to the watchOS version.
Since Xcode 11 you can use Swift Package Manager to do this without duplicate targets. Have tested in Xcode 12 beta6 at least and it is another option to look at that didn't exist when the question was asked or I initially answered (and it doesn't meet the detailed requirements of the question as it needs newer Xcode).

Adding tvOS Parse SDK to existing iOS project

Has anyone successfully added the Parse tvOS SDK to an existing iOS project with a separate tvOS target?
The iOS app already uses the Parse SDK.
I added a tvOS target to my project, added the Bolts, Parse, SystemConfiguration, and libsqlite3.tbd (got Parse & Bolts here: https://github.com/parseplatform/parse-sdk-ios-osx/releases/tag/1.11.0)
I can compile and run that target on the AppleTV simulator, but I get tons of warnings like this:
URGENT: building for tvOS simulator, but linking in object file
(<path>Parse.framework/Parse(PFObject.o)) built for iOS.
Note: This will be an error in the future
Also, calling PFUser.logInWithUsernameInBackground just hangs.
Not sure if what I'm trying to do just isn't possible of if I'm doing something stupid. Would be great to get this to work as there's lots of sharable code between the projects.
Figured it out. I removed the iOS framework's path from the tvOS target's Framework Search Paths in build settings. The location of the iOS framework appeared first in the list of paths, which I guess hijacked the framework since the iOS/tvOS frameworks have the same name.
Sometimes you just have to take a break and then double check your assumptions.

AFNetworking does not appear to be compatible with WatchKit

I have an existing iOS app which uses a framework which uses some CocoaPods. I added a WatchKit App target then added the framework to "Embedded Binaries". At this point, everything still compiles and runs. As soon as I import anything from the framework into the WatchKit extension though, I get an error that says
Could not build module 'FrameworkName'.
When I build, another error comes up inside one of the framework files:
'AFNetworking/AFNetworking.h' file not found.
Versions of AFNetworking prior to v2.6 would not support WatchOS without modification—see the AFNetworking requirements. As v2.6 was released after this question was posted, this seems certain to be the cause of the issues you were experiencing.
pod init again so that CocoaPods generates new targets for your Podfile.
Add your dependencies to both your main app and to your extension in the Podfile.

Using embedded framework in extension's containing app with deployment target iOS 7.0 and earlier

I'm developing Today Widget Extension for an app with deployment target earlier than iOS 8.0.
In apple Extension Programming Guide they recommended to use embedded framework to share code between app extension and its containing app.
You can create an embedded framework to share code between your app
extension and its containing app.
In the end of this guide they explain how to deploy a containing app to older versions of iOS 8.0 by using dlopen command.
After I have added the framework target the project doesn't build successfully.
It's always failed with the following errors :
Lipo Error : /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: can't open input file: PATH_TO_BUILD/armv7/APP_NAME (No such file or directory)
Apple Mach-O Linker Error : ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (#rpath/FRAMEWORK_NAME) for architecture armv7
(Error 2 repeats with arm64 architecture)
What I'm doing wrong ?
Is there another way to share code between app extension and its containing app ?
If someone know about the dlopen solution, please input with a "How to" tutorial (examples are welcome).
You can't use embedded frameworks on iOS 7, even with dlopen.
What they're explaining on that page (and not very clearly) is that if your app uses an embedded framework on iOS 8 and you want to deploy the app on iOS 7, you can't have the framework load automatically on iOS 8. Instead you copy the framework into the app bundle as part of the build process and then, on iOS 8 only use dlopen to load the framework from code.
On iOS 7, the framework will exist in the app bundle, but iOS 7 does not support loading it into the app by any means, including dlopen
If you want to share code between an app and an extension and deploy on iOS 7, you cannot use a framework to share the code. You need to include all of the shared code in both the app target and the extension target.

Resources