How do you create a basic TemplateInfo.plist file with Ancestors and specific frameworks? - xcode

Whenever I create a new project I add my own class files -often the same ones. It has become tedious to manually create these over and over. I want an automatic way to do this. I discovered custom Project Templates and I'm not sure if they are well documented by Apple.
I can create a cocos2D project with my custom classes and it works wonders. The problem is when I create a basic empty application with my custom classes.
Basically okay I'll give a little context. See my TemplateInfo.plist: This works. Note the "Ancestors" part. Here's how I interpret it: this inherits from cocos2d templates and does things like:
add necessary frameworks
adds cocos2D things like the splash image
other project-specific things
Now I don't know where these ancestor templates are or what format they are in, so I can't yet break down the individual things and say "OK I want the frameworks they include but not the launch image," but that's essentially what I want to do. I want to start with the most basic template and build from there manually.
I discovered that I can add specific frameworks in the "Targets" area. But before tackling that, I have a question: What Ancestors do I use, so that it does not use the Cocos2D base templates? I want the most basic thing.
1) Try removing all Ancestors and create a new Project and Xcode won't let you name the project and it crashes.
2) Try including only the Ancestors for the Default Empty Application: com.apple.dt.unit.cocoaTouchApplication
And it adds the correct frameworks:
Foundation
CoreGraphics
UIKit
XCTest
which is cool. However I noticed it overrides my Prefix.pch with a [Project-Name]-Prefix.pch and my project does not compile because I include a Debug Logger statement in my custom Prefix.ch like this:
#ifdef DEBUG
#define DLog(...) NSLog(__VA_ARGS__)
I figure this is the "com.apple.dt.unit.cocoaTouchApplication" ancestor doing its thing, and I want custom behavior that's different.
Is there a list of Ancestors somewhere that I can look at? Or is there a way I can look at the specific settings defined in "com.apple.dt.unit.cocoaTouchApplication" (if that even makes sense)?
Has anyone else run into this? What techniques do you use? Does anyone wish for an easier way to do this? Or is it better to create files manually every time?
I'm spinning wheels and any insight would be helpful. Thanks.

I figured it out. Searching through Xcode's default templates, I found one that uses basic ancestors. I used the following two:
And in Targets you can easily add the frameworks you want to include:
There are many little quirks like how to include an Info.plist file and Prefix.pch file and how to get it to rename properly (and replace the default one placed by the template). I am creating a video tutorial to show all these things in detail.
Creating your own custom templates is quite satisfying. Saves a lot of time and hassle when beginning new projects.

Related

Xcode create shared framework across lots of targets

I'm making stuff for IOS, Mac, and WatchOS - I have certain common functionality that is more about me and the way I program than about whatever it is I'm programming - helper methods etc
What I'd like is to have a "Common" framework or library in my app which is included into every other library. I understand I need a separate target for each of ios, macos, watchos, but I can't figure out how to set it up.
I can create a framework - and it comes with a target - I can duplicate that target and change stuff, but I don't seem to be able to change it from IOS to macos for instance. I can create a separate macos target, but then I can't seem to be able to change where it gets the code from.
Essentially in my source tree I want a single directory:
Common
and then have target frameworks CommonIOS, CommonMacOs, CommonWatchOS - that all just compile "Common". How do I achieve that?
You're misusing the word "framework". All you want is to keep some source code as a library that all your projects and targets, no matter what system they'll be compiled for, can use. You are describing a Swift package.

Why Are My Dependent Frameworks Being Pulled In Twice?

[Note: This question is, I think, dealing with the consequences of what prompted this never answered question]
I have a workspace that includes both a framework target and an application target. When I run the application many messages of the following form come to the console: Class "C" is implemented in both "Binary1" and "Binary2". One of the two will be used. Which one is undefined.
Here is a sampling of those messages:
objc[65093]: Class FIRAIdentifiers is implemented in both /Users/Robert/Library/Developer/Xcode/DerivedData/GenerationOfNow-bmsridmvnbtgfiduzqqomicqvsns/Build/Products/Debug-iphonesimulator/VerticonsToolbox.framework/VerticonsToolbox (0x10804bd20) and /Users/Robert/Library/Developer/CoreSimulator/Devices/33628599-9570-4784-B324-DAC383435F75/data/Containers/Bundle/Application/26411B80-FB71-44E9-AA64-05FEF20B9F08/GenerationOfNow.app/GenerationOfNow (0x10674a150). One of the two will be used. Which one is undefined.
objc[65093]: Class FIRASearchAdReporter is implemented in both /Users/Robert/Library/Developer/Xcode/DerivedData/GenerationOfNow-bmsridmvnbtgfiduzqqomicqvsns/Build/Products/Debug-iphonesimulator/VerticonsToolbox.framework/VerticonsToolbox (0x10804bd70) and /Users/Robert/Library/Developer/CoreSimulator/Devices/33628599-9570-4784-B324-DAC383435F75/data/Containers/Bundle/Application/26411B80-FB71-44E9-AA64-05FEF20B9F08/GenerationOfNow.app/GenerationOfNow (0x10674a1a0). One of the two will be used. Which one is undefined.
objc[65093]: Class FIRAZeroingWeakContainer is implemented in both /Users/Robert/Library/Developer/Xcode/DerivedData/GenerationOfNow-bmsridmvnbtgfiduzqqomicqvsns/Build/Products/Debug-iphonesimulator/VerticonsToolbox.framework/VerticonsToolbox (0x10804bde8) and /Users/Robert/Library/Developer/CoreSimulator/Devices/33628599-9570-4784-B324-DAC383435F75/data/Containers/Bundle/Application/26411B80-FB71-44E9-AA64-05FEF20B9F08/GenerationOfNow.app/GenerationOfNow (0x10674a218). One of the two will be used. Which one is undefined.
All of the duplicated class definitions come from Firebase frameworks which were installed into my workspace via the Pod file demonstrated in this question. Here is a screen shot of my workspace's Navigator:
Notice that both the framework target (VerticonsToolbox) and the application target (GenerationOfNow) are referencing the pods.
It seems to me that the proper way for a framework to be built is that it should not embed whatever frameworks it is linked against. It should be the responsibility of whatever application uses that framework to pull in the other dependencies. And indeed, when I examine the build phases for the framework VerticonsToolbox there is no option for specifying embedded binaries whereas there is for the application GenerationOfNow.
So, I am at a lose as to how to proceed. I suspect that what is happening is a result of the things that are put in place when pod install is executed. Can anyone advise me?
BTW: Can anyone point me to a good write up on how Xcode builds, what the various settings are, what tools there are for examining the binaries, etc? With Xcode everything is fine until it isn't and then there is this big, mysterious soup of stuff. Jeez!

Dividing a Swift application's components into Swift modules

I'm writing an iOS application in Swift, and I'm trying to figure out how to organize the project into separate modules. I'm using an MVVM architecture, and I want to make the Model, ViewModel, and View components separate Swift modules that make only subsets of themselves accessible to the modules that import them. The files in the View would import the ViewModel, and files in the ViewModel would import the Model. How can I accomplish this? Note that I'm not trying to create libraries that multiple applications can share. I'm just trying to enforce separation of components using modules.
EDIT: Maybe the question is, "What mechanism should I use to create modules aside from the one that comes with the initial iOS application project?"
One of the answers in "How do you use Namespaces in Swift?" https://stackoverflow.com/a/24032860/215400 says, "classes (etc) are implicitly scoped by the module (Xcode target) they are in." From that, one might conclude that targets correspond to modules and that the answer is to create separate targets within an Xcode project, but I tried that earlier, and tskulbru is saying that I need multiple Xcode projects.
Regarding multiple Xcode projects, the File > New > Project > iOS Framework & Library > Cocoa Touch Framework option didn't look right because it's supposed to be for things that use UIKit, and two of the modules I want to create shouldn't depend on UIKit. The other "Framework & Library" option, Cocoa Touch static library, isn't an option with Swift.
Another StackOverflow post mentioned using private Pods. After spending an hour working on that, I concluded that it wasn't the right solution because I shouldn't have to edit these modules in different workspaces.
This isn't possible without creating separate projects for the modules you want to create. This is because the way Swift handles namespacing.
Eonil answered this better than me: https://stackoverflow.com/a/24032860/215400
(Copy below)
Answered by SevenTenEleven in the Apple dev forum:
Namespaces are not per-file; they're per-target (based on the
"Product Module Name" build setting). So you'd end up with something
like this:
import FrameworkA
import FrameworkB
FrameworkA.foo()
All Swift declarations are considered to be part of
some module, so even when you say "NSLog" (yes, it still exists)
you're getting what Swift thinks of as "Foundation.NSLog".
Also Chris Lattner tweeted about namespacing.
Namespacing is implicit in swift, all classes (etc) are implicitly
scoped by the module (Xcode target) they are in. no class prefixes
needed
From my perspective if you want to encapsulate your components, probably you have two solutions:
Framework
Internal cocoapods
Both solutions will give you fully encapsulated modules, where you can define API that will be available in project through public keyword.
All other things will be not visible in your core project.
Managing your project will cost you a lot more time, but if you write this using SOLID principles, probably you will get more reusable code and those frameworks could be imported to other project just using import definition.

Create XCode 4 lib out of an project

I have a project with several classes. Now I want two libraries, one exactly for one class and one containing two classes.
Therefore i added two new products "libA.a" and "libB.a"
At the class-m-files i chose as targets "libA.a" or "libB.a"
It tells me, it puts the libs in a folder. But this folder is empty.
Can anyone tell me a step by step explanation, how this is possible.
(I also tried to crate a new product for static libraries, only added this one class and it compiles, but I can nowhere find this lib-File).
So the basic question: Where can I find a Tutorial, how to create a lib (only for IPhone, not for a simulator or universal or so...). URL, ... any help is appreciated.
Or can anyone tell me my missing step(s), do I need to do anything else?
Well, the solution was sooo simple ...
When starting the compilation, it is possible to choose the target next to the play-stop-buttons. The toolbar looks like this.
PLAY STOP TARGET DEVIVE
Click on the Target, chhose LibA, press "Play" (=Compile) and it works. Same for LibB.

Is there an easier way to add properties to a class in XCode?

I'm getting a bit more seasoned with my iPhone development but I still don't know everything. One thing that bugs the hell out of me is having to add properties to a class, because there are four steps involved:
Add a class member to the Header file
Add the property definition to the Header file
Add a synthesize declaration to the implementation file
Add a release statement to the dealloc method in the implementation file
Is there any easier way to do it? A hidden feature of XCode I don't know about? A tool of some kind maybe?
Accessorizer might be what you're looking for. I've never used it personally but many Mac Developer podcasts give it rave reviews.

Resources