I have a iOS project with multiple targets. Each target has its own plist but builds the same code base to produce slightly different versions of the app.
This works fine but there are some minor issues.
Whenever I add a file (code file/resource), I have to remember to add to all targets.
When I resolve conflicts between branches, it is much more tedious since there are many conflicts in the project.pbxproj file since each codefile/resource is duplicated multiple times.
Is there a way such that I only add to 1 target and make the rest of the targets "inherit" from it. I looked at target dependencies but it doesn't seem to achieve what I want.
Related
I have over 100 projects in my XCode and when I add a new file or class I have to select each target one by one to add it to it. Is there a way to select multiple targets instead?
The usual way is to have targets that don't duplicate each others files. E.g. some targets are libraries that are used by some others, and eventually there's an app or a unit test target that uses them. In this case there's no need to have the same file in multiple targets.
So consider refactoring the common files to a common library target that you can reference from the other targets. In this case when you add a file, you can add it to just that library, and it will be automatically resolved (linked) in the other targets.
Note also that in this case the file you add is only compiled once, and the compilation result is reused in various dependant targets, as opposed to compiling a separate version of that file for each target.
If that's not an option for you, an alternative is to generate the Xcode project file using some tool like CMake, GN, or a custom script that can write xcodeproj files (there are libraries to do that in various languages).
I wanted to add a WatchKit Extension (with SwiftUI supported on iOS13+) to my existing app (target iOS12) while keeping both codebase separated (two repos).
How can I separate the WatchKit Extension code from the Mobile One?
Will my Watch App with SwiftUI only work for users with WatchOS 6 and iOS13 without affecting the existing users with iOS12?
How about the app binary size increase?
Thanks for reading!
I am not sure if there is a simpler solution, but this one should work:
Separation of both apps:
If you open in Xcode the Source Control navigator, you see that Branches, Tags and Remotes belong to a main entry in the Project navigator, i.e. to a Xcode project. So in order to have separate repos, you need separate Xcode projects to which you can assign separate repos.
You can however have multiple projects in one workspace, so that all files are available in this workspace.
To have one standalone app, and one app with a watch extension, just setup a workspace with your standalone app, and add another new project. This new project needs all files of the original app plus the watch extension.
Since you need files from one project also in the other, you could drag them from one project to the new one, but then they will be copied (a green + badge is shown during dragging). Usually this is not what you want, since you usually don’t want to maintain two copies separately. Instead, you can show such a file in the finder, and then drag it from the finder to the new project. In this case, you have the option only to copy the reference.
Independence of both apps:
Since you have two separate projects, you can set the deployment target in the target’s build settings as required.
Size:
Each project will get separate products, the standalone app only an xxx.app, and the new project xxx.app, Watch.app, and Watch Extension.appex. So there should be no overhead.
EDIT (due to the comment of Ouadie in his question):
I am not sure if I understand your problem:
With the procedure above, you get a single workspace with two separate projects that share part of the files.
The „mobile project“ is the same as you use right now. It has only a single target (despite of test targets) that is built exclusively with the sources required. It has thus the same size as now.
The „watch project“ is new. It has 3 targets, the „mobile“ target, the Watch target, and the Watch Extension target (despite of test targets). It is built with the shared sources, and the additional watch extension sources. Its size is thus larger, but the increase depends of course on your sources.
Since you have 2 repos, the projects are decoupled, but both repos share some files. If you want to decouple them completely, you could copy the files from your current project to your new project (instead of copying only references), but then you had to maintain 2 copies.
I hope this helps!
I haven’t tried this before but wanted to know how it happens. Suppose I have an Xcode file for my project called ‘Project A’. Now I want to make another project with the same features as that of ‘Project A’ for a project called ‘project B’. But for ‘project B’, I don’t want to make a different Xcode file but rather want to incorporate the changes in ‘project A’ itself so that when I run the same project, I’ll be able to run project A or project B as per my need. How can I achieve this…?
Click on your project, Goto General > Targets.
Right click on your project Target and select Duplicate.
You will get to choose between iPad and continue to duplicate for iPhone.
Going ahead in each new/existing file, you can choose which target it belongs to and keep doing your development. If you exclude the file from an target, it will not contribute to that app's size.
You can also keep your future files in both Targets depending on your needs.
We are at 400+ targets in xcode. It still works fine but there has to be a better way to set this up by keeping the same code base but not having all those targets which could slow down xcode.
Android Studio lets you update the appname, which loads that folder from disk so only that project is loaded to run and program against. In XCode that is not the case, all targets are available.
It's been years but is there a better way now, with hundreds of targets that doesnt involve Git or Branching? The questions in regards to this are old and only for a few projects, we are talking hundreds here.
Your question lacks enough context to make a specific recommendation but in general...
Use Frameworks
If you can, combine sensible things into a single (or multiple) framework target. Frameworks can be more than fancy wrappers around a dynamic library, they can contain helper tools and such as well.
Use Workspaces
If there is a logical grouping to your existing targets you can separate them out into their own Xcode projects. Once you have them in their own projects you can create a workspace that references those individual projects. Even if the combined workspace loads in everything upfront (I don't think it does tho) you can still open and use the separate projects for a fast and fluid experience when working on the components.
Use static libraries
If you have a ton of targets such that one requires A, B, and C, but another needs B, C, D then you can actually put A, B, C, and D together in a static library and rely on the linker to strip out unused code from each individual target. This obviously does not reduce the number of targets you have, but you can make the static library its own project and include it in a common workspace. This will also speed up compilation as the files only need be compiled once.
Parameterize Targets or Use Schemes
If your targets are simply wrapping some external build tool/script with hardcoded parameters (I've actually seen this) you can actually pass a ton of existing variables from xcode to these external tools and eliminate "duplicate" targets. Similarly you can add new schemes if some of your targets are simply permutations of each other. A good example I've seen of this are people that have a separate target for "sanitized" (address sanitizer, etc) builds you can instead create a sanitization scheme instead of a target.
Use "Script" Build Phases
If some of your targets are doing something such as linting then you can instead employ a script build phase to call the linter instead of having a separate target to do it.
Offload Targets to an External build System
Xcode can have targets that simply call out to an external tool/script using the Script build phase (and using variable parameters as mentioned above). This can make sense to do if you already use another build system (make, cmake, etc) for another platform. Use Xcode only for the Mac/iOS specific targets and offload everything else to a cross platform build system.
If the build system outputs errors in a format Xcode understands it will even show file and line errors the same as native Xcode targets. I've seen people write thin wrappers around external tools to catch parse and reprint errors into such a format.
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)