40

Sharing class between iOS app and extension app

I want to use a custom class in both my app and the extension app. If I just have the class in the main app folder, the extension doesn't pick up on it. I tried making a copy of it and putting it into the extension folder, but I of course get a invalid redeclaration of [my class] error. What's the best solution for this? It's just one class, not multiple resources.

0

4 Answers 4

57

Nothing should be copied. Just add required files to compile sources for your extension:

enter image description here

6
  • 2
    Thank you! This looks great! How does this compare to creating a Framework? Commented Mar 1, 2015 at 18:40
  • 2
    @RubenMartinezJr. Creating a framework will not build your class for each target separately. but will do it once and link to each target. Commented Mar 1, 2015 at 18:41
  • 1
    @RubenMartinezJr. In no way. You will just share the code between app and extension. They will be compiled separately. So for example you can use #ifdef SOME_EXTENSION_FLAG ... #endif to disable some parts of code during compilation for App or for extension.
    – Avt
    Commented Mar 1, 2015 at 18:45
  • 3
    The downside between this solution and a framework is that effectively the compiled class will be in both the app and the appex extension, thus increasing the overall size of the IPA file since there is duplication. With a dynamic framework you won't be able to support iOS7 but if you are building a product against iOS8 only, it is a better approach since both the app and the extension will communicate with the same framework.
    – Edgar
    Commented Apr 10, 2015 at 8:30
  • 2
    It seems to be that if I include ClassA.m in Compile Sources and ClassA has dependencies to ClassB and ClassC, I need to include ClassB.m and ClassC.m as well. This can go pretty crazy, if ClassB and ClassC in return has dependencies and so on. Anyone who has a solution to this problem or who can tell me if I'm missing something? Thanks! Commented Jul 21, 2015 at 13:12
30

Just make sure that the files you want to share gets a tick in the section Target Membership.

Select your file, open the utility panel on the right and tick the appropriate target under Target Membership.

enter image description here

3
  • 7
    Just for giving a bit more insight, doing it in this way also adds the class automatically to Compile Sources under Build Phases.
    – Burak
    Commented Jul 28, 2016 at 7:15
  • that's what I was missing, its really simple. Commented Nov 1, 2016 at 12:12
  • Yeah but it is more straight forward in comparison to adding to CompileSources Commented Mar 20, 2018 at 14:21
6

Embedded frameworks are a great way to reuse code between your application and your extension. Having moved some of the code to embedded frameworks will provide us with a great opportunity to write some unit tests around it.

See section Using an Embedded Framework to Share Code https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1

3

App Extension(e.g Widget aka Today, Photo Editing...)

  • Containing App - app which contains an extension or super app
  • Host App - app which calls App Extension and starts extension's lifecycle

For example systems Photos app can be Host App for Photo Editing Extension like Photoshop Extension which is a part of Photoshop App(Containing App)

App Extension - available from iOS v8 - it is a packaged bundle which uses different process than Containing App and can communicate with Containing App through App Groups and with Host App through IPC. It has .appex file extension and is located in PlugIns folder. Something similar to CXTests[About]

Application packaged bundle

SpeedWidgetExtension.appex - Application Extension packaged bundle

Communication of App Extension and Containing App

  • Share data - use App Group[About]
  • Share code
    • Target Membership - the simplest way or for pre iOS v8 which allows you to add files into every target. It increases a footprint of package because this file will be duplicated for every target

    • Framework - module for grouping/reusing code

      • Embedded framework aka Dynamic framework - the most appropriate way to share common code base. Please turn on APPLICATION_EXTENSION_API_ONLY[About] for the framework. Please note that for using Embedded framework you should embed it only in Containing App (and don't add this framework in App Extension. If you include this framework additionally to App Extension it will have the same framework inside App Extension bundle(additionally to Containing App) - framework will be duplicated). It is possible to use single framework for both Containing App and App Extension because of @prath[About]
      //App Extension
      LD_RUNPATH_SEARCH_PATHS = @executable_path/../../Frameworks
      //It means that App Extension can uses Dynamic framework from Containing app
      
      • Static Framework - link the code to executable binary. You can link library only for Containing App

Limitations:

  • Widget Extension UI should be written on pure SwiftUI
  • Widget Extension not easy to debug on a real device
  • Widget Extension is updated when it is possible(not exactly when you specify it)

[iOS Extension Widget(Today) gray background]
[iOS extensions]
[iOS App Group]
[Vocabulary]

Not the answer you're looking for? Browse other questions tagged or ask your own question.