I have an Xcode swift app that uses "import CoreBluetooth" to access a wearable.
Now, my teammate wants to use my functionality, and thus wants a lib (.a) that he can incorporate into his xcode GUI app.
Can I refactor my app into a lib for him to add to his GUI app?
Or, is the only way to create a new xcode lib project?
Short answer is yes, you can use the same project. You need to separate 2 things:
Project is a design-time / code organization entity. One project can contain framework, app, tests, etc - all at the same time
What actually dictates what is going to be built are Targets. Some targets will build an app, some will build the library etc. Each target may contain any subset of files from your project (as long as they compile).
So that's one way to go about it: create a second target for Framework, add relevant files to Build Phases > Compile Sources and voila.
The advantage is simplicity. The disadvantages are many: how do you know you didn't break compatibility with wearable? how do you know which file belongs to app, and which belongs to app and framework (sure, you can see when you click on file, or folder structure can help, but it's not going to stop the mistake from happening)? or what if compatibility your iOS app needs is different with what wearable app needs? how do you maintain versions of such framework? etc etc
So a much better cleaner way is to create a separate repo for your framework, and maintain it as an internal product you are sharing between various components. That way you can maintain clear versioning, compatibility, and address bugs without the fear of breaking either app or wearable. And you can include that framework in both projects using (like suggested above) Swift Package Manager, or CocoaPods, or even manually.
Related
What is the proper way to link a dynamic framework which lives in the same workspace like the app?
I have a problem when adding the framework from the products folder to the App's "Embedded Binaries" section - because the added framework may be built for simulator and the app builds against iphoneos. I can not add both, can I?
I want to achieve that when my app builds, the framework is built too and I can work the changes immediately instead of doing some cumbersome update via Carthage or something link that.
EDIT: http://netsplit.com/xcode-two-apps-with-a-shared-private-framework-in-a-workspace This blog post describes exactly what i want to do - but this does not work since i want to develop on simulator and iphone (it would require a fat framework). Or did I miss something.
Although is possible to develop main app and framework and doing integration test in the same time from many workspaces, at same point becomes a slow-ish and not scalable development process.
So I suggest you to make a sample app in the workspace of your framework and develop and test your features directly from there. Once your framework is quite stable you release it and you integrate it with your main app.
During my work with development of iOS applications, i noticed that almost every application has some parts that are repeated. For example every application has user management logic, Login, Sign Up, Forgot password.
And every time, i find my self trying to manually import already developed logic (View controllers, nibs, storyboards).
My question is how can i implement these common features in separate component, so i can simply reuse them every time i start new project. Also notice that there should be possibility for small customisations, for example all apps have login screen, but UI design varies for every app.
Long story short, what i need is:
How to encapsulate commonly repeated features in separate component.
How to inject the component in the newly started project.
How to make customizations at the component, without changing the component core.
I guess that here should be made some combination of Framework (Or static library) and cocoa pods, but i wanted to hear if somebody have already developed some concept about this.
Yes, exactly as you supposed, the way I opted for to reuse components is through a static library or sometimes a framework of reusable components, implementing common logic or well structured classes to inherit from in the new projects, which I make available to the new projects as a CocoaPods development pod sitting on my development machine or in a shared git repository. This way should answer your questions 1 and 2. For your question 3, you can either opt to perform customisations to the core dismissing pod updates, or to adapt the core methods to a possible override in the destination project. Hope it helps.
How to encapsulate commonly repeated features in separate component.
Whatever you choose you are going to have to factor out the code your separate component requires from your code base. This is the first step in the entire process - so think long and hard about if it makes sense to turn it into a separate component.
So now you have some code you would like to reuse...
There are a number of ways of doing this, such as Xcode's workspaces, stand alone source files, static libraries and frameworks. Cocoa pods is a package manager and will help you maintain your framework - not write it :(
Xcode's workspaces
A workspace is an Xcode document that groups projects and other
documents so you can work on them together. A workspace can contain
any number of Xcode projects, plus any other files you want to
include. In addition to organizing all the files in each Xcode
project, a workspace provides implicit and explicit relationships
among the included projects and their targets.
Static Libraries
Introduction to Using Static Libraries in iOS
Static libraries provide a convenient mechanism for sharing code among
multiple applications. On iOS, static libraries are the only supported
library type. This document explains how to extract code from your
application into a new static library and how to use that static
library in multiple applications.
Frameworks
In OS X, shared resources are packaged using standard frameworks and
umbrella frameworks. Both types of framework feature the same basic
structure and can contain resources such as a shared library, nib
files, image files, strings files, information property lists,
documentation, header files, and so on. Umbrella frameworks add minor
refinements to the standard framework structure, such as the ability
to encompass other frameworks.
Frameworks are packaged in a bundle structure. The framework bundle
directory ends with the .framework extension, and unlike most other
bundle types, a framework bundle is presented to the user as a
directory and not as a file. This openness makes it easy for
developers to browse any header files and documentation included with
the framework.
Source Files
These are the classes you have factored out of your code base. You could just include them in each project you use them - for instance a separate repo, that contains all of your shared/common code that you add to your Xcode project's workspace. Very simple, not the best to maintain.
How to inject the component in the newly started project.
Depending on how you choose to implement your common code will effect this step. For source files you just need add them to the project and set the target. For frameworks or static libraries you will have to embed them in your project
For workspaces you will add the projects containing the shared code to the main projects workspace.
How to make customizations at the component, without changing the component core.
Again you may find yourself refactoring code so that you expose the UI controls or logic functions that you want to be able to customize. As a general rule the more you expose the more complex the code gets.
We have 3 apps that we maintain, that all use the same menu controller and Core Data model. In addition, one of the apps uses several views and controllers from one of the apps. It's getting to the point that we need to find some way to separate into different projects to prevent painful Xcode project merges. Right now all the code is mixed in together and each app has its own target in one Xcode project.
Is there any way we can separate the project easily into different projects that have AppA, AppB, and AppC where AppB and AppC depend on AppA?
Depending on how each app is different, you can create different targets in your Xcode.
Here's a docs on how you create Xcode targets.
If that does not suit your need, you can create multiple projects and reference files from other projects. I really can't tell what you'd need without more information.
Maybe use cocoapods.
You can make your own (private) pods for the various files that your projects rely on and then keep them updated in their own repository, and then the projects can include the pod and update it when needed. You can also point specific projects to specific branches of the pod repo etc.
(Not sure whether Core Data is supported in pods yet though, might be)
I have created a dynamic framework for one of my apps as I was using a lot of the same code for the main app and the extensions. This works well and has reduced the amount of duplicate code in the project.
I am now looking at creating a second app and it would save me a huge amount of time if I could use the framework from the first app.
How would I go about doing this?
My initial thought is to break the framework out into it's own project and include that project in the app projects by using a workspace.
Another thought was to have both apps in the same project, but as different targets.
I also use git, so it would be beneficial to have the framework separate from the apps.
First of all I'd like to say that I'm pretty new to this topic so I'm a bit confused on some general aspects of how it works.
Basically I'm working on an iOS project which has two targets, one is the app itself which I'm developing and it is a front-end iOS client, one is a static library which the former developer used to define classes belonging to a back-end framework.
Both the files of the app itself (the client I'm working on) and the static library (the back-end framework) are in the same xcode project bundle.
Even If I've never done the "setup procedure" of the static library anything seems to be working just fine on compilation.
Now the question is: I'm setting up unit tests because I'd like to start developing new features adopting a Test Driven Development approach, so one of the things I was struggling on was if I had to generate or not two separate test targets, one for the iOS app and one for the static library (since they're two separate targets), ore use one single test target for both the static library and the iOS App.
So, reading on the internet to find a solution I discovered that, as even Apple suggests here , a common approach is to add the static library as a "sub-project" of the app project.
I'm just asking myself why and what is the difference with my current situation (one project, to targets, one of it is the static library). Are there any drawbacks? Should I reorganize the whole project?
My experience agrees with Apple and the common approach. I'd suggest making the framework a subproject. (I've had some issues finding headers, but that's my lack of mastery over Xcode, not a flaw in the process.)
Set up unit tests on each project, independently. This way, your tests are true to your objective with a framework: You've successfully decoupled the framework from the parent project entirely.
If you write the all of the unit tests in the parent project, what happens when the framework is needed in another project? You've got two choices. You can not test the framework, or string along the original parent. Do the right thing and split up your tests.
I've got an open source framework that I built, called SpiffyKit, that has a parent project called SpiffyTester. (I admittedly didn't unit test much, because it's all UI and no logic.) It may serve as a good example of a starting point.
Depending on your needs you can use Pods, static or adding it to the project. If you add a library as a "subproject" is useful when you are working on the 2 projects at once. For example if you add something new to the library you just compile the library and voila you have access to the new library in your project. However if you just link the static library you will have to open the project for the library then build then replace it in the library and add the new headers witch is a lot of setup work.