How to add a playground on XCode iOS Swift project? [duplicate] - ios

I'm new to iOS development and using Xcode and I'm having trouble getting Alamofire to work within a Playground. There's some functionality I'd like to test out for proof of concept but the library is not linked to the Playground and I've tried getting it to play nicely. I have Alamofire set up to work within an iOS (not in a Playground) project before the installation instructions in the Github Alamofire repo were recently updated.
Any suggestions on how to get Alamofire to import properly in the Playground?

Apple provides excellent step-by-step instruction to do so here: Importing Custom Frameworks Into a Playground

Here is what I consider to be the simplest straight line path:
Download and build Alamofire:
brew install carthage
echo "github \"Alamofire/Alamofire\"" > Cartfile
carthage update
Configure the workspace with a playground file and Alamofire.
From the Carthage/Build/{iOS / OSX} directory, drag the Alamofire.framework file into your link library list: {Project Name} -> {Target Name} -> Build Phases -> Link Binary With Libraries
Command-N (create file) -> {Platform} -> Source -> Playground
If not already in a Workspace file, File -> Save as Workspace. To be paranoid, I close the project / workspace and (re)open the workspace.
Click on the playground file created in #2, and add the import import Alamofire

You can try moving library to
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/System/Library/Frameworks/
Then you can import and use it right in your playground

You can create a playground within the project also like in this tutorial
Steps
If the project is not in a workspace, save as workspace
Create new Playground, by adding to workspace level in the project pane
Ensure your project has a framework target. If it doesn't Edit the scheme to add a new Cocoa Touch Framework target (it doesn't need to have unit tests)
Add the files that you want to use in the playground, to the new framework target
Build the Framework by selecting the target in the build box at the top
In the playground, import the Framework. If the classes you want to use are not public, you need to import like so: #testable import ModuleFramework

Related

How to import Swift Package in App already added to Workspace of App

I am using Xcode 12.4, I created an app "App".
After that, I created a Swift Package "MyLibrary" via File > New ... > Swift Package ..., and chose the option to immediately add it to the workspace "App":
I want "App" to be an example app of how to use the Swift Package, so it seems nice that I can develop the package + example app in the same window and things are grouped together:
The problem seems to be that I can't import "MyLibrary" for example in the ViewController.swift:
import MyLibrary // no such module "MyLibrary"
Question: How can the app import the swift package?
After you have added the package to your project you need to add the library to your "App" build target.
Select the project in your project navigator then under General
Select the "App" target
Check if MyLibrary is listed under "Frameworks, Libraries and Embedded Content". If not then add it using the "+" button – Joakim Danielson 25 mins ago
See also Apples documentation

Build TensorFlowLite Swift Custom Framework

I need to build TensorFlowLite Swift Framework/cocoapod from the sources and then use it instead of the original framework in one of the Swift projects.
Downloaded the code and followed the instructions in few scenarios but without success:
1) https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/experimental/swift
a) python configure.py
b) CocoaPods developers isn't applicable as it doesn't take the source from the local TensofFlow folder (or I am mistaken?)
c) Bazel developers I do:
bazel build tensorflow/lite/experimental/swift:TensorFlowLite
bazel test tensorflow/lite/experimental/swift:Tests --swiftcopt=-enable-testing
and eventually
generate_xcodeproj.sh --genconfig tensorflow/lite/experimental/swift/TensorFlowLite.tulsiproj:TensorFlowLite --outputfolder ~/path/to/generated/TensorFlowLite.xcodeproj
as a result I get a project with a libtensorflow-lite-experimental-swift-TensorFlowLite.a and few idx files. It compiles and I see the .a file (but both the app and tests don't compile for various reasons) and I don't quite understand how I can use that .a lib with Swift files as there are no module/headers etc. files.
After all these exercises there is TensorFlowLiteSwift.podspec in the root of TensorFlow and in the experimental/Swift folders. It still depends on the TensorFlowLiteC and if I refer to this podspec in another project via path param I can do import TensorFlowLiteC but not import TensorFlowLiteSwift / import TensorFlowLite and I believe the TensorFlowLiteC is still taken from the Internet, not locally.
2) Custom framework path from here:
https://firebase.google.com/docs/ml-kit/ios/use-custom-tflite
Here are few problems:
a) if I try to just use a project with tensorflow_lite.framework added internally then I can't reference TensorFlowLite / TensorFlowLiteC etc. in the Swift file.
b) if I try to follow a route of creating the local pod and reference the pod project then pod install doesn't work because mandatory parameters are not set (used provided example).
I expect to get a Xcode project or workspace which is built from the local TensorFlowFiles and which I can reference from other projects like 'import TensorFlowLiteSwift' or 'import TensorFlowLite'
The problem is that I don't understand even what's the correct route to make it happen.
Thanks.
All right, I figured out the answer here:
build TensorFlowLiteC framework from the root tensorflow folder:
bazel build --config=ios_fat -c opt //tensorflow/lite/experimental/ios:TensorFlowLiteC_framework
The result can be found here: bazel-bin/tensorflow/lite/experimental/ios/TensorFlowLiteC_framework.zip
Unzip the file and add the contents to the new XCode project (in my case it was Swift Single Window App). If you do it via drag'n'drop then XCode will automatically change the Frameworks, libraries and embedded content section, also will modify the Framework paths
Change this setting Build Settings\Linking\Other Linker Flags to -lc++
Done. You can do
import TensorFlowLiteC
and use the source files from the swift folder.

How to reuse Swift code in other projects?

I wrote a class in Swift. I want to use this code in two separate iOS app projects that I wrote. Both the shared code and the apps are written in Swift. What is the best way of doing that?
I tried to create both a framework and a library in Swift and then add it as a sub-project to my app. In both cases I could not make the app see the module. I tried to add the shared module to "Target Dependencies" and "Link Binary With Libraries" of the main app's target. No luck - the app still can not see the classes of the shared module.
Using Xcode6 Beta6 at the moment.
Solution
As Konstantin Koval and Heliem pointed out, all I needed is to use public in my class and method declarations, in the shared module. Now all works, both if I use workspace and if I add the module as a subproject.
Update
I just found an excellent easy solution for reusing code between projects in Swift. It is called Carthage (https://github.com/Carthage/Carthage). This is not a plug as I am not affiliated with it in any way, I just really like it. It works in iOS 8+.
Create a new project (iOS Cocoa Touch Framework) for your reusable code
Move your classes to that Framework project
Mark your methods and classes, that should be visible to others as public
Create Workspace.
You can create a workspace on step 1. When you create new Framework project, Xcode will ask you if you want to create new workspace and add that project to workspace. This is the best approach
Add both your project and Framework to the workspace
Select you project target -> General tab. Add Framework and Libraries (add your library here)
When you want to use code from your Library in swift file, import it using import 'LibTargetName'
You can take a more programatic approach by using SWM (Swift Modules): https://github.com/jankuca/swm
It is very similar to npm (node.js package manager) or bower (client-side module manager); you declare your dependencies in a swiftmodule.json file like below. It does not have a central module registry like the two mentioned JS solutions, it only accepts git URLs.
{
"name": "ProjectName",
"dependencies": {
"Dependency": "git://github.com/…/….git"
}
}
…run swm install and have the Dependency module (compiled into a *.swiftmodule binary) ready for import in the .modules/ directory.
import Dependency
And if you prefer to skip Xcode for app development, you can also build your whole app using swm build (more info in the project's readme).
The project is still in early stages but it makes itself useful a lot for me at least. It provides the most clean (and clear) way of creating importable modules.
Here is a video which is very straightforward: http://eonil-observatory.tumblr.com/post/117205738262/a-proper-way-to-add-a-subproject-to-another-xcode
The video is for OS X instead of iOS. But you will get it and figure out the process for iOS.
Let's assume that AppA needs to reused code from SharedProject.
The following process works for me in Xcode 7 Beta:
Create SharedProject. Project type must be Framework instead of Application. You write common code in this project and mark the code as public.
Open AppA in Xcode, open the folder which contains SharedProject in Finder. Drag the .xcodeproj file of SharedProject from Finder and drop it into the root folder of AppA in Xcode Project Navigator.
AppA --> Build Phases --> Link Binary with Libraries. Add SharedProject.
import SharedProject and reuse code from SharedProject!
Edit:
Nowadays I suggest you use Carthage. It's better than the home made solution above.

How to I import 3rd party frameworks into Xcode Playground?

How do I import 3rd part frameworks into Xcode Playground?
Swift Playground obviously has a framework import mechanism because we can import Cocoa, SpriteKit, and in an OSX Playground, XCPlayground (XCPlayground seems missing from iOS, oddly)
What I'd really like to do is hide code from my playground and be able to show a minimal example. Any thoughts on how to load a Framework into Swift playground?
See also:
How to import own classes from your own project into a Playground
Is it possible to import third-party Objective-C code into a Swift playground?
(This question is different because the request is to use a framework in Playground rather than simply regular swift files)
There is currently no supported way to import your own framework or app code into a playground, short of pasting it into the playground editor. We're aware that this is very desirable functionality, but as always we encourage people to "vote with bugreporter" at bugreport.apple.com
Right now, if you're just trying to hide code for showing in an example, code folding in the editor might do the trick.
It is now possible to import your own frameworks into a playground. This provides a way to share code between your applications and playgrounds, which can both import your frameworks. To do this, your playground must be in the same workspace as the project that produces your framework. You must have already built your framework. If it is an iOS framework, it must be built for a 64-bit run destination (e.g. iPhone 5s). You must have an active scheme which builds at least one target (that target's build location will be used in the framework search path for the playground). Your "Build Location" preference (in advanced "Locations" settings) should not be set to "Legacy". If your framework is not a Swift framework the "Defines Module" build setting must be set to "Yes". Once all these conditions are fulfilled, importing your framework will work in a playground.
Edited: As of Beta5 this is now supported when the playground is part of the workspace that builds the framework as a target. There are more details on the Apple dev forums site, but hopefully #Rick Ballard will add them to his answer here and that should becoke the definitive answer for this question.
Don't do the below anymore!
For the short term, while there's no supported solution, if you're producing a Module/Framework you can copy it into the SDKs System/Library/Frameworks directory and then just import <#Module#> the same way as you import system Frameworks.
For an OS X Playground: /Applications/Xcode6-Beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks
And for iOS: /Applications/Xcode6-Beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/System/Library/Frameworks/
But before you do that... go file a radar as #Rick says in his answer.
I've written a tutorial covering import of custom frameworks in Beta 6
In short, if you've got your playground and framework either in the same project or workspace, and your framework is built for 64 bits (even for iOS), they play very well together.
source: http://qiita.com/ryokosuge/items/2551cd4faa9dca324342
If there is anyone who still had difficulty understanding how to go about it after reading the accepted answer, this may help.
It's not in English though so I will explain here:
Using Carthage:
1: Setup your Cartfile in the root of the project, add your libraries and run:
carthage update --platform iOS --use-submodules
2: Make sure your project is saved as a Workspace. From the Xcode menu bar: File > Save As Workspace. Shutdown Xcode and reopen from the new .xcworkspace file.
3: Add your library's .xcodeproj file in your workspace: File > Add files to "your_workspace_name". Then find it in: ${SRCROOT}/Carthage/Checkouts/your_library_name/your_library_name.xcodeproj
4: Find the Embedded Binaries and Linked Frameworks and Libraries section in your project's general settings. Add your library's .framework file to both.
5: Clean(⇧+⌘+K) and build(⌘+B).
6: Import your library in the playground.
I solved it by copying the built frameworks to the Built Products Directory, where Playgrounds in the workspace also searches for frameworks. Note: you also need to run lipo and strip away unused architectures from the FAT binaries.
The steps needed (in a nutshell):
Create an aggregate target
Add a script phase to copy the frameworks
from Carthage/Build/iOS/ to BUILT_PRODUCTS_DIR (I use a swift script
in the example below, but you can use also use bash, ruby python
etc.)
Run aggregate target Now you can import the framework(s) in a
Playground
Additionally you can leverage the aggregate target in your app:
Embed frameworks from BUILT_PRODUCTS_DIR, not Carthage/Build/iOS/
Add aggregate target to app scheme to re-establish frameworks after a clean.
Here is an example project setup as above: https://github.com/richardnees/CarthagePlaygrounds
Like using Objective-C classes in Swift code, you can import 3rd-party library/classes into your project and Xcode will ask you if you wanna create a <#YourProjectName>-Bridging-Header header file. Choose yes and import all header files you need in that file. After that, in your playground, you can simply do import <#YourProjectName>-Bridging-Header after import UIKit and you will be able to use the classes you imported to your project.
Update: this is actually incorrect. Please see my comment below. Sorry for any confusion...

How to import own classes from your own project into a Playground

Assume a setup like this:
You have an Xcode 6 project, where you've implemented your own classes (say MyView and MyViewController) with both Objective-C and Swift
You have added a Playground into your project
In the Playground, it's possible to import modules (frameworks) like UIKit with the import keyword. How do you enable access to the project's other classes from the Playground?
Just trying to access project classes directly results with an error message:
Use of unresolved identifier 'MyView'
As of Xcode 6.0 Beta 5, it is now possible to import your own frameworks into a playground. This provides a way to share code between your applications and playgrounds, which can both import your frameworks. To do this:
Your playground must be in the same workspace as the project that produces your framework. Your workspace must contain a target that produces the framework, instead of using a pre-built framework.
You must have already built your framework. If it is an iOS framework, it must be built for a 64-bit run destination (e.g. iPhone 5s), and must be built for the Simulator.
You must have an active scheme which builds at least one target (that target's build location will be used in the framework search path for the playground).
Your "Build Location" preference (in advanced "Locations" settings of Xcode) should not be set to "Legacy".
If your framework is not a Swift framework the "Defines Module" build setting must be set to "Yes".
You must add an import statement to your playground for the framework.
Once all these conditions are fulfilled, importing your framework will work in a playground.
In Xcode 7 we introduced another mechanism that you can use to import your own classes as source, instead of importing a framework; you can read about this "Auxiliary Sources" support at http://help.apple.com/xcode/mac/8.0/#/devfa5bea3af
I actually managed to refer to other Swift files in the current project by doing this:
Create an empty Playground and place is somewhere under your project.
Open the YourPlayground.playground bundle (yes, it's a bundle = directory) in Terminal.
Edit contents.xcplayground for example with vi and add another section like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='3.0' sdk='iphonesimulator'>
<sections>
<code source-file-name='section-1.swift'/>
<code source-file-name='section-2.swift'/>
</sections>
<timeline fileName='timeline.xctimeline'/>
</playground>
Rename section-1.swift to section-2.swift (if you created the Playground from scratch, there should be an example section-1.swift in your bundle)
Add a hard link (symbolic link doesn't seem to work) named section-1.swift which will point outside the bundle to your Swift class file like:
ln ../../Classes/MyView.swift section-1.swift
Close Xcode and open the Playground again.
Now there should be two sections, one with the contents of your Swift class file and the other one with the example content you got from creating the Playground from scratch.
This way I can actually run code lying outside the Playground, but Xcode seems to crash more often when doing it like this.
Edit:
As of Xcode 6 beta 5 you're now able to refer to project files, as Rick Ballard instructs in his answer.
Since Beta 5 of Xcode 6 it is possible to import your code if it is in a framework. What you need to do is create a framework target, add the Swift files there and in your playground do
import ModuleName
You can look up the module name in the build settings. It's usually the same as the target name.
Remember to make the code you want to see public. You'll need to build the project before changes are available in the playground. (You'll also need to edit the playground to trigger re-execution.)
Important
Do not give the playground file the same name as the target! If you do, importing seems to work but you'll get the following error when the playground tries to execute:
Playground execution failed: error: Couldn't lookup symbols:
I wasted an hour on figuring that out. :)
I wasn't able to get it working using any of the answers here, so I started playing around and found a simple way that worked for me to import a swift class into a playground.
Just create a playground in your project, theres a directory inside it called 'sources', just drag a copy of the swift class into that folder and the playground then will have access to it.
For example:
I just put links to all my swift files in the Sources folder:
cd /path/to/project/MyPlayground.playground/Sources
ln -s ../../*.swift .
This way changes in your source file will take effect in your playground immediately. Worked very nicely.
Xcode 8.2, Swift 3.0.1, macOS Sierra
All you have to do - is write in the beginning:
import ModuleName
(assuming your playground placed in the same workspace as framework/project)
If it's doesn't work:
Rebuild your project
Recreate playground and copy all from old playground there
It solves a lot of strange errors with failed init's and imports of whatever!

Resources