Swift: how can I create external interface for static library (public headers analog in Objective-C .h) - swift

I need to create a static library with Swift,
and I need to know how can I implement interface for the library.
In Objective-C I can mark needed headers as public in build phases,
but there is not any headers and any interfaces in Swift.
What should I do with Swift?

Simply put: you don't.
Swift is not a language that separates headers and implementations. When you create a library or framework based on Swift and only for consumption by Swift, the Xcode default build setting of DEFINES_MODULE already does the job for you. This will create a .swiftmodule file, which will be used by import in other Swift projects.
If you want your code to be importable from Objective-C though, you might want to check if the SWIFT_INSTALL_OBJC_HEADER build setting is also enabled (which it is by default for frameworks as far as I know). Then the Swift compiler will generate a <ProductName>-Swift.h file for you, which you can import in Objective-C code to access your Swift classes and functions.

If you want your Swift framework to expose certain classes to the interface, simply mark the 'entities' (functions, variables etc.) public:
public class Class {}
public var variable: Int
public func function() { }
By default, all entities have internal access.
public entities are intended for use as API, and can be accessed by any file that imports the module, e.g. as a framework used in several of your projects.
internal entities are available to the entire module that includes the definition (e.g. an app or framework target).
private entities are available only from within the source file where they are defined.
Source: the official Swift blog.

Related

multiple project with one workspace xcode [duplicate]

Note: I know How to call Objective-C code from Swift, but I don't know below,
I want to use this EsptouchForIOS's Demo in my project. The demo is write in OC, it has a storyboard and controller. I want to know how to integrate the demo in my swift project, and use that storyboard and it's controller in my swift project.
I'll start writing from the very beginning. Suppose you have a project in Objective-C and now you want to continue your project's development in Swift. Follow the below guidelines: (This intends to your specific needs)
First choose to add a new file from File->New->File. In this process select your language as Swift. In the final step here, you will be prompted to Create Bridging Header. Select that:
Now build your project once (⌘+B). You may get an error like this:
Change your target's minimum deployment to the version that Swift supports. (Example in the below screenshot)
To use Objective-C resources in Swift files:
Now that you've got one ProjectName-Bridging-Header.h file in your project. If you want to use any Objective-C class in your Swift files, you just include the header file of that class in this bridging header file. Like in this project, you have ESP_NetUtil and ESPViewController class and their header files too. You want to expose them to Swift and use them later in Swift code. So import them in this bridging header file:
Build once again. Now you can go to your Swift file. And use the Objective-C classes as like you use any resource in swift. See:
N.B: You must expose all the class headers (that you're intending to use later in Swift) in that bridging header file
To use Swift resources in Objective-C files:
Now you may wonder, I've successfully used Objective-C resources in Swift. What about the opposite? Yes! You can do the opposite too. Find your Target->Build Settings->Swift Compiler - General->Objective-C Generated Interface Header Name. This is the header file you will be using inside your Objective-C classes for any Swift to Objective-C interoperability. To know more check here.
Now inside any of your Objective-C class, import that interface header and use Swift resources in Objective-C code:
You will get more understanding from the official apple documentation.
You can checkout the worked out version of your linked project here with Objective-C-Swift interoperability.
So according to your question, you have added an objective C bridge in your swift project using How to call Objective-C code from Swift.
Now, import all headers (.h) files of your objective-c source code (demo project) that you want to direct use in swift file.
For example, your demo project has EsptouchForIOS following header (file with extension .h) files in project source code.
ESPAppDelegate.h, ESPDataCode.h, ESPTouchDelegate.h
import a header file in your bridge, which you want to use in your swift code. Suppose in your swift code you want touch delegate ESPTouchDelegate then write,
#import "ESPTouchDelegate.h"
Here is snapshot of your demo integration in my Test Swift project with bridge
and import statements.
Now, there is function/method in an objective C file getValue
which is used/accessed in swift project/file.
Similarly, you can import as many files (source headers) as you want in bridge and use the same files (source code) in swift.
I have never tried to use objective-c from swift project. But I normally used swift classes from my objective-c project. I usually follow this instructions https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html from apple developer website.

Have hidden implementation of functions in Swift like in the documentation?

I am building a rather large library and I think it would be a lot cleaner if I could have the implementation for my methods and such hidden. For example, when you view the in-code documentation for standard Swift types, such as UInt64, you see things like:
With the actual implementation of the methods hidden, and only the declarations and headers shown. How can I do this with my own library?
You need to distribute your library as a precompiled binary, in which case only the public headers + documentation will be visible for consumers of your library.
For more information, you can watch the WWDC2019 video of about Binary frameworks in Swift.
There is a shortcut in Xcode to show only the interface: Control+Command+Up Arrow, but it is a little slow and doesn't hide the internal methods that not useful for the usage of the code (since only public and open interface in Swift Package can be used by outside module).

How do you create public extensions, in a shared framework, for XCTest?

For example, I never use the description of XCTestCase.expectation, so I'd like to use a function to provide a default for it, and make it clear via naming that I'm initializing the expectation, as you can't really use an initializer for XCTestExpectation. But if the extension is not in a test target, then it can't compile:
Cannot load underlying module for 'XCTest'
import XCTest
public extension XCTestCase {
func makeExpectation() -> XCTestExpectation {
return expectation(withDescription: "")
}
}
I've created an xcworkspace here (https://github.com/dtweston/TestFrameworkSample) that demonstrates a solution to your issue. There are two projects in this workspace:
SampleApp project with an iOS app target and a unit test target.
SharedTestFramework project that imports XCTest and declares the single extension you put in your question.
The SampleAppTests target links to the SharedTestFramework to be able to use the extension it defines. The single test file imports the SharedTestFramework.
With those steps, I also encounter the Cannot load underlying module for 'XCTest' when building the SharedTestFramework.
The fix for that is to update the Framework Search Paths to include "$(PLATFORM_DIR)/Developer/Library/Frameworks". Now the SharedTestFramework compiles correctly, and as you can see in the workspace I uploaded, the SampleAppTests target is able to use it successfully.
Old and busted answer
Are you building a separate framework that is designed to be imported into test targets? If that's the case then I think you just need to reference XCTest.framework from this custom framework you're building.
On the other hand, if you're trying to add this extension to a framework that is used by your app target, that seems like a bad idea, because it would mean linking XCTest.framework to the binary that goes to the store and runs on people's devices.
I'm not sure if that's possible. I'm more confident that it's not a scenario Apple expects or supports.

How do I add a swift class to my framework header?

In Xcode 6 (beta 4 6A267n), I added a Framework (selecting Swift as the language) and the framework header has this comment:
// In this header, you should import all the public headers of your framework using statements like #import
Through SO I found that you have to append "-Swift" to your header file name, however I was not able to get this to work.
I've also added $(SRCROOT) to my header search path.
It sounds like you are trying to create your own Swift library? In which case, you do not need to create an external interface as described here:
Swift: how can I create external interface for static library (public headers analog in Objective-C .h)
With Swift you identify your public interface by marking classes and methods as public.
The header that has the -Swift suffix is a bridging header and is what you use to bridge Objective-C code so that it can be used in your Swift application.

How do I create an importable module in Swift?

I have read through Apple's documentation for Swift and can find nothing about how to create modules or how to define class or stucture members as private or public.
There are references to the import statement in the syntax but I can find no information on what it does or how to use it.
Does anyone know where I can find this?
In Swift, "Modules" refers to Frameworks. Xcode now has a template for creating a framework project for both iOS and OS X.
There is currently no way to declare methods or properties public / protected. If you would like to see this added as a feature, you can make a feature request on Apple's bug reporter. It should also be noted that Apple has stated that the language could change with each release of Xcode, so it is possible that member access levels could be added before the public release.
Also, there is a way to make a module by yourself, but it's a bit harder way.
If you'll look at xcrun swift -help you may see a few options, and there are -emit-module, -emit-library and -emit-object which might be useful, but, probably, you should prefer official way and distribute modules via Frameworks.
If you still want to make module on your own, you can read this guide with some explanation
Apple mentioned that private methods don't exist yet but they are in the process of being implemented. Remember that this is a newborn language and it is still being build up.
Update
You can modularize a swift project using frameworks.
We modularize by creating separate framework projects for each module and link them via Xcode workspace. It looks more natural when we separate the components into different projects & it also makes sure that there is only a one-way communication between modules. Developers can work/test on isolation without thinking much about other modules.
By default classes/structs/etc created within a framework will have an internal access control type so it is only visible within the modules. In order to make it visible outside the module, you can make it public.
More info on access controll level here
The latest Xcode 6 beta update (beta 4) bring access control to swift
Swift Enables Access Control
Swift access control has three access levels:
private entities can only be accessed from within the source file where they are defined.
internal entities can be accessed anywhere within the target where they are defined.!
public entities can be accessed from anywhere within the target and from any other context that imports the current target’s module.
Swift 4.0
Description from the chapter "Access Control" in the Apple book "The Swift Programming Language (Swift 4 Edition)"
Swift provides five different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.
open access and public access enable entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use open or public access when specifying the public interface to a framework. The difference between open and from another module that imports the defining module. You typically use open or public access when specifying the public interface to a framework.
internal access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure.
fileprivate access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.”