Using external libraries in Swift 4 playground - xcode

I've been trying to learn Swift 4, and therefore needed to use Xcode9 Beta as the IDE. I would like to load a large CSV data file to do some data analysis using a playground. The library I'm trying to use is CSVImporter, installed using Carthage, as recommended by the developer.
I've spent a week on this issue, trying to follow guides I've found online, such as here - Stackoverflow, here - Medium, but they all refer to previous versions of Swift and Xcode, and none seem to work.
In general their approach seems to be incorporating the playground into workspace with a project that uses the imported resource. I usually get the "No such module 'CSVImporter'".
My specific question is: How do I set up a Swift 4 Playground so that I can import CSVImporter with Xcode 9 Beta?
While I have this specific task, I think this would be of general interest to the community. I suspect that someone with a far clearer idea than I of how Xcode executes builds and resolves build dependencies would be able to address this fairly easily! Many thanks.

Basically, you have it right. Approach is:
Create new XCode project for Cocoa Framework under MacOS
Create Cartfile with your dependencies
Build dependencies (e.g. carthage update --platform macOS)
Import the .framework files that were built (from Carthage/Build/Mac)
Create extra build phases step that will run script /usr/local/bin/carthage copy-frameworks and copy imported frameworks (just follow Carthage's guidelines, it's all the same so far)
Create some .swift file (e.g. main.swift) that will just import frameworks that you have imported via Carthage
Save XCode project as a workspace file
Create new playground (also MacOS) and save it under the projects root folder of your "fake" framework
Add the playground into workspace (as of XCode 9 it's not possible to create playgrounds directly in the projects/workspaces, so you need to do this trick with adding an existing file to the workspace)
Build your project
In the playground file, import your "fake" framework (see step 1), and only after import your carthage dependency framework.
Profit

If your external libraries are SPM packages you can create a playground with Arena:
arena https://github.com/finestructure/Gala
🔧 resolving package dependencies
📔 libraries found: Gala
✅ created project in folder 'SPM-Playground'

Related

How do I add a framework dependency to a test target?

I have created a framework that contains code useful for testing (a bunch of convenience initializers, for example). Now I would like to import that framework in a test target but there doesn't seem to be a way to do this in Xcode. Just importing it with import Dependency gives me the "Module not found" error when building.
The General tab of the test target does not have any settings for that (or any settings):
The Build Phase tab has a Dependencies section, but the framework I want to add does not show up in the list when I press the + button:
There's also a Link Binary with Libraries section, but when I try to select the framework there Xcode says that file is already being linked (where?):
I can import and use the framework if I add it in the Frameworks, Libraries and Embedded Content section of the main target, but I don't want to do this since the framework is meant to be used only in the test code. I don't see the reason to pollute the namespace with all the extra initializers. I could probably try to check if no XCTest classes are available at runtime and crash, but that seems like a workaround rather than a solution.
Any advice?
P.S. I'm using the latest version of Xcode (11.3.1).
If you have a source code you are able to use Explicit dependency[About] with cross-project reference
drag and drop dependency project inside a test target
Build Phases -> Dependencies -> Plus(If you didn't include dependency into test target on previous step)
Import
[Mixing Objective-C and Swift]
Xcode 12
Drag and drop the framework into folder where tests are located.
Go to YourAppTests target settings: Build phases -> Link Binary With Libraries – here your framework should be listed, if not tap on + button -> Add other (on the bottom) and choose your framework from project's test folder
Done!
PS: most likely works for Xcode 11 as well

How to Import Swift Source Code into a XCode Swift Project

I've written a working swift prototype. It contains a parent class and some subclasses. I want to be able to import the parent class into another project where I will create sub classes for it.
I created a new XCode project for a dynamic library, added the parent class to it and ran build. I've seen where you can't use static for Swift code.
I also created a different directory and set up a swift package. The build on it ran successfully.
When I add an import statement to the project where I want to use it, it says it can't find it. The statement is: "import RailsData", the name of the parent class.
I've tried adding the dynamic library project to "Linked Frameworks and Libraries". I also tried adding the swift file directly. XCode flags the import as not found.
The swift package manager example is all command line based so I'm not sure if will work with XCode projects. I would eventually like to make a package out of it.
Xcode 8.2, Swift 3.0. I'm pretty sure I'm missing something fundamental.
Update
I found a related question. It says to
Put your package manifest file into the same directory as the Xcode project, and then invoke swift package generate-xcodeproj
With a search I found this page that says:
Instructions for how to build a package are provided by the Package.swift manifest file.
So I copied the file to the root of my project and ran the command above. It created a new .xcodeproj. When I opened it, I saw my original files, but not anything from the package. That's not surprising as there is no reference to it's location in the file system. Also a mystery is what happens when you want additional packages. Do you keep generating new projects?
It seems like the missing link is the following command
swift package generate-xcodeproj
Actually Adding Swift 3 packages to Xcode 8 using the Swift package manager should answer your question.

How to conditionally compile version-specific Swift (1.2 vs 2.0) code in the same source file?

I have a Swift demo project that comes bundled with my framework. I want to ensure that the Swift code in the demo compiles successfully with both Xcode 6 (Swift 1.2) and Xcode 7 (Swift 2.0) without user intervention.
Since there's only marginal preprocessor support in Swift, how can I determine at compile-time which version of Swift or Xcode is being used to compile the code?
Now, here's the important detail:
It has to work automatically!
Open the project in Xcode 6 -> compiles
the Swift 1.2 code.
Open the project in Xcode 7 -> compiles the Swift
2.0 code.
No build settings or other means that require the user to specify, one way or another, which Swift/Xcode version she is using.
I keep thinking: this is such a trivial task, how could that not be possible with Swift?
As a framework developer this is driving me nuts since a successful compile of a Swift project now entirely depends upon the user's version of Xcode, and I can't ask them all to "update to Xcode 6.4" and at a later point having to ask them all over again to "update to Xcode 7.1". This is insane!
The alternative would of course be to have separate demo projects, managing different code bases, one for each version of Swift. And hoping the user will know what project will work with her version of Xcode. Not a real alternative.
The other alternative, to simply not use any of Swift 2.0's enhancement, is unfortunately not possible either. There is syntax, classes and methods that won't work in one or the other Swift version, if only due to the compiler being more picky in newer Xcode versions.
You can accomplish this using some of Xcode's advanced build settings, in particular:
XCODE_VERSION_MAJOR: Which encodes the Xcode major version as a string like "0700".
EXCLUDED_SOURCE_FILE_NAMES: A "fnmatch"-style pattern of source files to exclude by default.
INCLUDED_SOURCE_FILE_NAMES: A "fnmatch"-style pattern of source files to include.
I would not generally recommend doing this, as it will make your project hard to understand for most Xcode users, but if you absolutely want to make it work you can use this technique.
The way you accomplish it is as follows:
For any source files which need to be versioned, name them something like "Thing-Versioned-0600.swift" and "Thing-Versioned-0700.swift". Make sure both files are in the sources build phase.
Use the excluded mechanism to prevent any versioned files from being compiled by default, by adding a project-level build setting: EXCLUDED_SOURCE_FILE_NAMES = *-Versioned-*.swift.
Use the included mechanism to only add back in files that match the current Xcode major version, by adding another project-level build setting: INCLUDED_SOURCE_FILE_NAMES = *-Versioned-$(XCODE_VERSION_MAJOR).swift.
Having 2 versions of the code inside your project won't work since the code would not compile. There is no compiler directive for conditional compiling based on a version.
There is one workaround that could work (did not test it)
First create 3 files named version_current.swift, version_1_2.swift and version_2.swift. Make sure that only version_current.swift is part of your build target.
Then create a new build script phase and place it right above the 'compile sources' phase. In that script you will copy over the content of either the 1_2 or the 2 version over the current.
My scripting knowledge is not so good, so I can't give you much help doing this. You can get the version with code like:
$ xcrun swift -version
And then just execute a copy statement.
But then this will only work for the default Xcode version on your system. When you want to use a different version, you also have to change the default version.

Importing 3rd party framework in a Playground's "SupportCode.swift"

Is there a way to include a (non-Apple) framework in the "SupportCode.swift" file, in the Sources directory of a Playground?
While the framework is successfully imported when the import directive is placed in the Playground itself, I get a "No such module" error popping up when trying to import the same framework in SupportCode.swift.
I have my playground embedded in a workplace with the required frameworks added to it as well.
It is a hack. if you have file like "Parse.framework", just copy it to Xcode's system frameworks folder at "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks"
Now you can import this framework in playground just like any other system framework.
This didn't work until recently.
In order to import an external framework, you have to have the playground and your framework's target/project in an Xcode Workspace. Once you have that and you build the framework, you can just import the framework with an import.
If the playground is already in a project that is not a workspace file, you can convert the project to a workspace by choosing File > Save As Workspace then add the playground to that workspace.
You can also drag the framework project in the Finder to the project navigator in the workspace.
Open the playground file in the editor, and add import the custom framework using an import statement.
NOTE: These are the conditions.
The framework is in the same workspace as the playground.
The framework has already been built.
If it is an iOS framework, it is built for a 64-bit run-time
destination.
The workspace contains at least one active scheme that builds a
target.
If it is an Objective-C framework, it sets the Defines Module build
setting to Yes.
I have found this tutorial exactly how I was doing in my project.
https://m.pardel.net/using-3rd-party-frameworks-in-swift-playgrounds-fd415f6dba10
Please don't miss to add empty .swift file in your project as describe in this answer https://stackoverflow.com/a/47922876/855261

Build static library

I am trying to build a .a static library for my iPhone project.
So, I have created a new project, and I used the template Cocoa Touch Static Library.
Then, in XCode 4.0, I add my .m and .h files.
i have successfully build the project, but no .a file is created In XCode, I see .a file in Products category but displayed in red; so it doesn't exist.
I don't understand why my build button don't create .a file, any help?
I see that you accepted the answer, but I thought I'd leave a note for future library developers. After upgrading an Xcode 3.x based static library project to 4.x, the library will not always upgrade and begin doing universal library builds. When this happens, the project build will be successful and apps linked against the target dependency will run fine, but you'll get red static library files showing in the projects you pull in. This is very annoying and the only fix I have found is to recreate the project files -- I tried auditing the build settings but was unable to figure out the confounding factors.
Hope this helps save somebody the 2 hours I just lost :-P

Resources