With the new Swift 5.3 package manager, it's possible for a Swift package to vend out images from an Asset catalog. Let's say I have a package called "ImageLibrary" which has image assets I wish to share between many projects.
Now I have my main app project and I import the Swift package. In my storyboard, XCode lets me select images from the asset catalog in my library "ImageLibrary". However, at runtime the images cannot be found, because they exist in a different bundle to the storyboard.
The only solution I can find is to drag the Image asset library from the "ImageLibrary" Swift package into my "Copy Bundle Resources" list. And this does works. The images end up in the app's bundle and appear at runtime.
The problem is that if my Swift package is referred to with a remote repository link, XCode will check the code out and compile it deep inside the Derived Data folders. And the "Copy Bundle Resources" link will point to that folder. And now the XCode project file has a link with information specific to my hard-disk buried in it. With a large team that won't work of course.
I could possibly use a local Swift package to deal with this, but I anticipate similar problems with continuous integration tools and so on. I suspect this is just something that was not intended to be done with Swift packages, and that I'm out of luck.
Thanks for any ideas,
Simon.
One approach you can take is to declare public UIImages initialized with your graphics from the asset catalog all within the Swift package. Then the UIImage will be available to your main app project. This approach will work remote Swift packages as well as local Swift packages, so long as you are able to edit the Swift package source code yourself to update it.
Related
I must have read over a dozen posts on possible techniques to link a local library into my Swift Package. Specifically, my package depends on libturbojpeg.a, which most users won't have installed anywhere. Even if they did install it (there is a DMG), I'd have to go through hoops to make sure I was linking in the correct version. I finally found a post in the Swift Forums that basically says you can't do it now.
It appears that the only way to link it now is using .linkerSettings(LinkerSetting.unsafeFlags(..., but if you use that your package can't be managed by Xcode (see above link, and I even tried it and verified it cannot be used).
Is there some kind of workaround that allows me to distribute my Swift Package with the library?
In my Package, I created a directory "Libraries" and added my library there.
I discovered that Xcode 11 places included Swift Packages in a specific location in the Derived Folders directory. This means that it is possible to tell Xcode where to find it during the link phase.
My Package has these instructions in it for users:
1) Add the Package using Xcode->File->Packages with the URL of https://github.com/dhoerl/
2) Open the app's Project Build Phases, and from the Package shown in the left file pane, drag the Libraries/.a file into the link phase. It will appear just above the that should already be there
3) In Application Build settings, under library search paths, add:
"$(BUILD_DIR)/../../SourcePackages/checkouts//Libraries"
Build and run! Voíla - works like a charm!
Note: obviously this is somewhat fragile, Xcode 12 could change how packages are managed, but its possible by then that the Swift Package Manager will support linking of local libraries (its mentioned in the above link.)
I'm trying to load a custom .dylib library via the dlopen() function (in a Swift iOS app). It requires a path to the library.
Where to put the library in the project structure?
What will be the library's path on the iOS device?
Also, a tangential question, it seems more usual to include the library's sources directly into the project and let Xcode build it. Is that a preferable approach for some reason?
1 )
If you include the .dylib library in with your list of files and resources in your project, you can use the "Copy Files" build phase to copy the dylib into your shipping app.
A tutorial can be seen here.
2 )
For dlopen, try using just the .dylib name before you try to use relative paths including the "#executable_path" or "#rpath" run time variables. An example can be seen here in this related question.
As for why some developers prefer to include the library source code in a project, I believe it's mostly just a preference by folks who aren't comfortable with the "Copy Files" build phase or in using dlopen.
This (pre iOS 8) tutorial on creating frameworks for iOS mentions packaging assets (images, etc) as a bundle that lives outside of the framework product. The .framework and bundle are two separate items...
This is not ideal because, to use the framework you must drag two items into your Xcode project: both the framework package AND the bundle. Dragging an extra item is too much work and I don't want my users to suffer such a fate...
I want my framework package to CONTAIN my assets bundle so anyone who uses the framework only has to drag-drop a single item (the .framework file).
Is this possible?
That's one of the great benefits of using the new dynamic frameworks, you can most certainly include any assets your framework may need and this includes:
Images
Configuration files.. plists, .txt, etc.
Audio
Xibs
There was an Apple WWDC 2014 Session that covered this.
ASCII version here.
However, while dynamic frameworks like these have been supported for a while in OSX, it has only been available for iOS since iOS 8.
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.
I used to copy/paste my IOS plugin files inside Plugins/IOS folder on my Unity project, but it doesn't work for bundles (as it has directory structure).
I can't beleave there is no way to generate xcode project from unity with .bundle inside?
Any help appreciated
Unity3D will not contains folders in the Plugins/iOS to Xcode project. In fact Unity3D will only auto merge source file and .a library for you, as described by Unity3D's doc:
Automated plugin integration Unity iOS supports automated plugin
integration in a limited way. All files with extensions
.a,.m,.mm,.c,.cpp located in the Assets/Plugins/iOS folder will be
merged into the generated Xcode project automatically. However,
merging is done by symlinking files from Assets/Plugins/iOS to the
final destination, which might affect some workflows. The .h files are
not included in the Xcode project tree, but they appear on the
destination file system, thus allowing compilation of .m/.mm/.c/.cpp
files.
Note: subfolders are currently not supported.
But you can use the PostprocessBuildPlayer attribute to implement this yourself. I made a tool for this purpose called XUPorter, which can make exporting and libraries setting easier from Unity3D to Xcode. You may want to see it on GitHub. There is a demo in the package and you may set your bundle under the 'folders' tag.