How can I reference a Swift class in my WatchKit extension from the core iOS code? - ios

I am trying to make my iOS application send the WatchKit Extension a set of data each time that data is updated from the server.
This is what the code in my iOS app looks like (names changed)
[WatchKitDataModel loadDataFromSource: currentData]
However, the iOS application does not recognize the WatchKitDataModel.
The error is "use of undeclared modifier."
Please help me make my apps talk to one another!

Ensure that your offending class is added to both the App target and the WatchKit target in the Document panel
The picture shows a TodayExtension but the principle is the same.

To share code between your WatchKit Extension and its containing app, create an embedded Framework in your app. Frameworks are the recommended tool by Apple to share code, within an app, and between apps.
To create an embedded Framework in Xcode 6, select your project and go to File > New > Target... Then in the dialog that opens select iOS > Framework & Library > Cocoa Touch Framework. Click Next. Give it a name, SomethingKit, similar to what Apple uses, e.g. UIKit, HealthKit, WatchKit. Now create your new classes and other common code in files inside your new Framework. When you want to use it in any of your other targets, i.e. the WatchKit Extension or its containing app, don't forget to import SomethingKit.
Ah, and don't forget to give public access level to the public-facing classes and functions in your Framework.
For more information about Frameworks to share code, for example, what sort of things cannot be included in Frameworks, see Apple's article: Using an Embedded Framework to Share Code.
There is also an interesting WWDC 2014 session video about this: Building Modern Frameworks.

Related

Objective C generated interface header file Not found in WatchKit

I am currently working to add Apple Watch app in my current App. I added the required profiles and got it to working without any issues.
Now, I want to use some of the class files from iphone app in my apple watch app. I did add the .m file in the target membership to the watchkit extension target.
Since the file which I want to use is in Objective C class, I went ahead and created the bridging header file for apple watch extension target.
Each time when I run the application; I get $(SWIFT_MODULE_NAME)-Swift.h file not found. I did try to follow steps from this link but to no avail. I did clean build folder; removed the derived data but it still gives me the same error.
Am I missing anything in particular which others have tried and can share with me ?
I am using Xcode 8 and Swift 3.
So I figured out the answer and thought of posting it here.
There are couple of ways in which you can fix this but it depends on what you want to do.
1) Using #IF TARGET_OS_IOS will allow you to use the class from iphone to watch.
2) You can also use WatchConnectivity framework to send and/or receive messages, send data also. This is the new framework Apple has recommended to use for connectivity between the devices.
Hope this will help someone else trying to figure out this problem.

iOS Today Widget share source file with main application

I've added a Today Extention Widget Project in my Xcode workspace and I want to use some source file from the main app, so I've flagged the "target membership" on this files. The problem is that the Xcode linker fail with duplicate symbol error when compiling the main app. So what is the correct way to share source file between main app and widget?
You can use Frameworks to share code/files between your Host App and App Extension.
You can create an embedded framework to share code between your app
extension and its containing app. For example, if you develop an image
filter for use in your Photo Editing extension as well as in its
containing app, put the filter’s code in a framework and embed the
framework in both targets.
For more on sharing scenarios between Host App and App Extension refer to: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1

Framework CFBundleIdentifier Collision

I've made a custom SDK using Cocoa Touch Framework (followed these instructions to make it https://kodmunki.wordpress.com/2015/03/04/cocoa-touch-frameworks-for-ios8-remix/) .
One app, that is using this SDK is already uploaded to app store and is reviewed by apple and all is well.
Now I'm trying to submit second app to App store. All is well on the xCode, it shows that upload was completed successfully, but few minutes after uploading I get a letter that says:
CFBundleIdentifier Collision - The Info.plist CFBundleIdentifier value
'com.company.MySDK' of 'myApp.app/Frameworks/MySDK.framework' is
already in use by another application.
I don’t understand why apple even checks the app framework's bundleidentifier. Looks like there are lot of similar issues with using different bundles, but I haven not found a fix that would work for this issue.
Would be really thankful for help, thanks!
For me it was caused by framework's .plist keyword CFBundlePackageType that was using the default value APPL but had to be changed to FMWK (https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-111321).
if you are using Nested frameworks use "Do Not Embed" in the general tab-> framework and libraries
for example:
your project uses framework A and
and framework A uses frameworks B, C, ... Do not Embed these frameworks

Adding Framework and App Extension targets to IOS App project, am I doing it correctly?

I'm studying IOS/Swift development and I'd like to build an IOS app that in the future will have its own Today Extension. I've read that it is better to put the common logic (for example the logic that accesses Internet resources, performs some job on the result etc) between the App and its extension into a Custom Framework.. Since I think I'll need to change both Framework and App code during the development of the App, I'd like to avoid building the framework in a separate project, than use Show In Finder function to locate the framework bundle and then drag-and-dropping it within the App project.. So I'd like to know if this is the correct way to set up a Workspace with an App, the framework it uses and the Today Extension of the App:
Create a new Project with an IOS App target
Select the project in the Project Navigator and then Editor->Add Target... and specify a Cocoa Touch Framework
Editor->Add Target... and specify Today Extension
Add the framework in Linked Frameworks and Libraries
In this way I've seen that changes to the Framework sources do not need a Framework target recompilation, maybe because the project knows about the need to recompile framework sources even if I only build & run the IOS App target that uses that framework? Am I doing it right? I've seen that the Today Extension created in such way does not lists the framework in the Build Phases -> Target Dependencies while the IOS App does, but both of them correctly use the updated code of the Framework when I update it.
Then, I've noticed the following warning when I compile the project, but I don't know if it is related to the way I've setup the project:
ld: warning: linking against dylib not safe for use in application extensions: /Users/gianni/Library/Developer/Xcode/DerivedData/TestFrameworkApp-dshihhfiuepeqzddbnpgnfwilhem/Build/Products/Debug-iphonesimulator/TestFramework.framework/TestFramework
BTW is it normal that the entries within the Products folder are always red? Is it due to the fact that I build only for IOS Simulator since I don't have a Paid developer account that allows me to build for an IOS Device? Does this prevent me to build a framework that can be exported for some other Project since I can't find the Framework bundle with a right clicking on the framework product and selecting Show In Finder (and so I can't drag-and-drop it to another project)?
I hope I've been clear enough and that you'll point me in the right direction to understand what is the suggested way of starting my new project :)
It sounds to me like you're headed down the exact path I would take.
Regarding the warning you're seeing... I believe that checking the "Allow app extension API only" for your shared framework will supress that and cause build failures when you attempt to use a API that is not allowed in extensions.

How sharing the model of the main app with WatchOS2?

I need to share my entities (CoreData) of the main app with WatchOS2.
There are two ways to share code between targets - frameworks, and just including the .m or .swift file in multiple targets using Xcode's inspector.
WatchOS2 can create a dynamic framework and the main app too.
I have tried to create a dynamic framework in the main app and share code with WatchOS 2 : `Not such module TestFrameworkKit'.
Framework isn't going to work with a watchOS 2 extension because that extension runs on a completely different device.
Any idea ?
I just add the .swift and .m files to both targets and this works great. Since the iOS and watch app need to be in the same project anyways, this is a very appropriate solution. I would only look into adding frameworks if you need to share code between projects.

Resources