Shared internal framework not found after renaming project - ios

I have a swift Xcode project say named Motorcycle and it has an internal framework shared among targets called MotorcycleKit. After I rename my project to Rollerblades I see in the project overview I now have a RollerbladesKit instead of MotorcycleKit. After doing a find and replace on import MotorcycleKit to import RollerbladesKit and running the app I get a module not found error on my import RollerbladesKit. How do I fix this error?

The Xcode rename function has a bug where it renames shared internal framework's Project Name to the exact literal of the new project name if the shared internal framework's name has the name of the original project in it. So from the question. MotorcycleKit has Motorcycle in its name and it gets replaced with Rollerblades instead of RollerbladesKit. You can fix this by going to your framework's Build Settings > Packaging > Product Name and correcting the name there, in this case by appending it with 'Kit'.

Related

Cannot find 'ConfigurationIntent' in scope error

Adding a Widget Extension target to a new or existing iOS project leads to a bogus error when building the project: Cannot find 'ConfigurationIntent' in scope. Cleaning DerivedData / project does not help.
It turns out that if you have a Class Prefix assigned to your xcode project document settings, xcode will silently add the prefix to the auto-built configuration intent class but this isn't obvious because the configuration itself does not contain a prefix.
In my case I had a prefix TDD. I spotted the file TDDConfigurationIntent.swift in the build folder. The solution is to either rename the configuration intent manually OR remove the class prefix in project document settings.

Xcode change dynamic framework Product Module Name

I’m trying to change the product module name of a dynamic framework.
The main reason I’m doing this is that my framework is customised for each client, so I have different targets with different names and output files that I want to keep different as they are, but I would like the framework to be imported for all the targets with the product name.
The framework is in objective C and consumed by a swift application.
In the Xcode build settings the DefinesModule is set to YES.
Let’s say the product name is CustomerSDK and I want it to be imported as ProductSDK.
For example: The framework file will be CustomerSDK.framework and the import statement import ProductSDK.
If I use the $(PRODUCT_NAME:c99extidentifier) as the module name (the default option in Xcode) by calling import CustomerSDK it works, but when I try to change the Product Module Name field in build settings to another one the code completion of Xcode in the host application project doesn’t find the module name and even if I write it I get the “No such module ProductSDK” error. Looking inside the resulting product framework I can see that no modulemap file is generated.
I tried also to create a custom module.modulemap file, in this case the code completion of Xcode in the host application project proposes the new name, but when I try to compile I still get the “No such module ProductSDK” error.
framework module ProductSDK {
umbrella header "CustomerSDK.h"
export *
module * { export * }
}

Swift: import framework but can't find class in a workspace

Similar to 'Swift: import framework but can't find class in it' but different.
I have a Xcode workspace using CocoaPods for some libs. I did create my own framework and drop it to the workspace like I did for a Xcode project. In both the import statement finds the framework but in the workspace the classes are not found. The Xcode project does not have any problems.
If I open the project instead of the workspace Xcode will find the classes in the framework.
Whats might be wrong?
My package would not see some objects without any hint of why not. The tests in the package worked and the SwiftUI previews worked in the imported packages.
It turned out that my package contained both extensions and classes that had not been marked public and they could not be seen in the imported package.
I marked the extensions with the public keyword and marked both the classes and their init() with the public keyword.
I found this comment above, which solved my issue:
"Hard to say without seeing the project, but the most probable case is that you haven't marked your classes in the framework as public – lobstah" Thanks lobstah!

Umbrella Header Not Found When Changing Target Name or Product Name of Framework

I have this code base that I decided to turn into a framework to reuse in my future apps.
So I went ahead and created an Xcode Project for Cocoa Touch Framework.
To keep things simple (and workspaces out of the picture, at least until I grasp the basics of frameworks), I created a "test-bed" iOS app that embeds/depends on/links to the framework as an additional target to the same project (not a separate project). The idea, of course, is to use this app to test my frameworks capabilities as I add or modify them.
So my project has two targets:
MyFramework
MyTestApp
...And of course, two schemes (one to build each):
I am also modifying the code so that it works both on iOS and macOS.
Warning: no umbrella header found for target 'MyFramework (macOS)', module map will not be generated.
So far, so good.
Additionally, I am also modifying the code so that it works both on iOS and macOS.
So I added two more targets:
MyFrameworkMac
MyTestMacApp
...aslo setup so that the app target-depends, links to, and embeds the framework.
Still, good.
Next, I decided to do some cleanup and file rearranging, to keep things tidy and making sense before the number of files starts to grow further.
Then, the trouble started.
After some trial and error, I discovered a few things:
1) If I change the target name for the iOS Framework and try to build the iOS app, I get the following warning:
/Users/Me/Projects/MyFramework/Code/MyFramework/:1:1:
Umbrella header for module 'MyFramework' does not include header
'PublicHeaderXX.h'
...for each of the public header that are included in my master header:
// In this header, you should import all the public headers of your framework
// using statements like #import <MyFramework/PublicHeader.h>
#import <MyFramework/PublicHeader01.h>
#import <MyFramework/PublicHeader02.h>
#import <MyFramework/PublicHeader03.h>
...
2) If I change the product name of the iOS framework in Build Settings, I get the error:
Lexical or Preprocessor Issue | 'MyFramework/MyFramework.h' file not found
...pointing at the location where I import it in the app source code:
#import <MyFramework/MyFramework.h>
for the Mac framework target, I can get away with changing the Target Name, but if I change the product name, I get the warning:
Warning: no umbrella header found for target 'MyFrameworkMacRenamed',
module map will not be generated
So I ask...
Is there a way to set the target names and product names I want for each framework target?
I'm sure there must be something somewhere that I should "modify to match" and eliminate some discrepancy, but I'm new to frameworks and can't figure it out ... (What is an 'umbrella header' anyway?)
It turns out the "umbrella header" is no other than the 'main' header for the framework that is created automatically by Xcode when you first create the project or framework target, and it must have the same name as the target (as explained, for example, here).
As to why both target and product must me named the same, I can only guess it has to do with keeping linking not too complicated (Apps are not 'linked against', so I guess there is no damage in the product name being anything you want).
I was trying to get away with a Single Header to Rule Them All (platforms), using TargetConditionals.h etc. to import either Cocoa.h or UIKit.h, which is impossible, because Xcode won't let you use the same name for both targets, and those have to match the name of their headers!
So, I settled for:
<MyFramework/MyFramework.h>: Classic. Accept No Substitutes. Exclusive for iOS, and
<MyFrameworkMac/MyFrameworkMac.h>: Now Available on the Mac too! - From the People Who Brought You MyFramework
I did a lot of reading and trying. My solution is combined:
Clean build
Close Xcode
Delete DerivedData everywhere - in project folder, user folder (~/Library/Developer/Xcode) and in root folder
/Library/Developer/...
Open Xcode and clean again
Delete app from test device
Now it works.

Swift: using private framework

I have built an iOS Swift framework with Xcode.
After writing the code I have build the project and took the .framework file inside the Products folder to test it.
To test the framework have open a new application and drag and drop the .framework file previously built and I added it into the embedded binaries list of my application project.
To import it into my ViewController.swift class I wrote:
import frameworkName
No problem until here, this means that the project sees the framework.
When I try to use a public class inside the framework with:
var x : className?
I get the following error:
'className' is unavailable: cannot find Swift declaration for this class
What does it mean? What is the problem?
When you're referencing a framework in the products directory from your workspace, ensure that the location is "Built Products" and the filename is just the framework name, without any additional path components.
If you're referencing a framework that isn't in your workspace, I would recommend using Carthage instead of copying it directly into your repository. This will make versioning much easier, and will ensure that it is built correctly for both simulator and device.
To actual a self defined framework, u really have to do a lot of things.
Firstly, make sure ur framework is used on right device. It's to say framework can only be used on corresponding device(either one of Simulator, Device and Mac). In other words, if framework A built on simulator, project import framework A can only pass compile and successfully built on simulator.
P.S. if universal version desired, -lipo command is what u need to further explore.
Secondly, during implementing ur framework , make sure all the classes, methods and variables u want use outside start with Public.
Thirdly, check ur project setting Embedded Binaries and linked Frameworks and Libraries do contain ur framework.

Resources