What is the @exported attribute in Swift
This attribute officially does not exist. Unofficially, however, it is a way of opening a sub-framework's symbols into your own framework's scope and exporting them as though they were yours. For example, a testing framework might wish to declare an @exported XCTest
somewhere so all it takes to use the framework is just import TestFramework
.
Be warned, though the attribute is compatible with most swift versions and should compile fine, it will break code completion in creative ways on each individual build of Xcode - probably a big reason why it is not an official feature yet.
What is import func, struct, class, and @_exported in Swift?
You can import only a specific part of a module, not a whole module:
Providing more detail limits which symbols are imported—you can specify a specific submodule or a specific declaration within a module or submodule. When this detailed form is used, only the imported symbol (and not the module that declares it) is made available in the current scope.
From Import Declaration
For example import func POSIX.isatty
will import function isatty
from module POSIX
instead of importing the whole module POSIX
(which is BIG).
The @_exported
attribute starts with an underscore. That means it's a private Swift attribute. Not a feature, an implementation detail.
In short, this attribute lets you export a symbol from another module as if it were from your module.
exported: true' has no effect in '_specialize' attribute in Xcode 12.5
I have resolved the issue with running pod update
instead of pointing to a specific version in my Podfile
Otherwise, you could also follow what @coryhowell pointed out,
removed the pod and added it as a Swift Package (Version 1.4.0)
Podfile
platform :ios, '11.4'
use_frameworks!
inhibit_all_warnings!
target 'myAppp' do
pod 'Alamofire', '~> 4.8.1'
pod 'CryptoSwift'
end
Podfile.lock - auto-created, then pointed to latest version of the CryptoSwift
PODS:
- Alamofire (4.8.2)
- Countly (20.11.1):
- Countly/Core (= 20.11.1)
- Countly/Core (20.11.1)
- Crashlytics (3.12.0):
- Fabric (~> 1.9.0)
- CryptoSwift (1.4.0)
- Device (3.1.2)
- Fabric (1.9.0)
..
...
not showing all lines
....
......
Should an IBOutlet property be marked nullable or nonnull?
If your class is written in Swift, you can't use a non optional property because otherwise the compiler is going to complain that the property is never initialized. That's why Apple recommends to declare it as an implicitly unwrapped optional, because once your object has been initialized, you know for sure that the property contains a value (unless you have a dangling outlet, which can happen by the way...)
When exporting from Objective-C, you can mark it as nonnull
and it will appear in Swift as a non optional property which is fine in that case. Note that you can't use both nonnull
and weak
.
So you can either do :
@property (nonatomic, strong, nonnull) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet var subview: UIView
or
@property (nonatomic, weak, nullable) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet weak var subview: UIView?
If for some reason you still want the property to be exported to Swift as an implicitly unwrapped optional, you can mark the property as null_resettable
or null_unspecified
. That's not really what they are meant for but it will still produce the desired result. See this blog post for more on these annotations.
@property (nonatomic, weak, null_unspecified) IBOutlet UIView *subview;
// Exported to Swift as @IBOutlet weak var subview: UIView!
How to make a Swift String enum available in Objective-C?
From the Xcode 6.3 release notes (emphasis added):
Swift Language Enhancements
...
Swift enums can now be exported to Objective-C using the @objc
attribute. @objc enums must declare an integer raw type, and cannot be
generic or use associated values. Because Objective-C enums are not
namespaced, enum cases are imported into Objective-C as the
concatenation of the enum name and case name.
Access control in swift 4
My original answer (shown below) is now mostly outdated – the beginnings of the resilience model are to be implemented in Swift 4.2 with the introduction of the @inlinable
and @usableFromInline
attributes, corresponding to the old @_inlineable
and @_versioned
attributes.
In addition, and more importantly, the rule for what default arguments of publically accessible functions can reference has changed again. To recap the previous rules:
In Swift 3 there was no enforcement of what access level such default argument expressions could reference (allowing your first example where
defaultValue
isinternal
).In Swift 4, such a default argument could only refer to declarations exposed as a part of the module's interface, including those that aren't otherwise directly visible to users in another module (i.e
@_versioned internal
).
However in Swift 4.2, with the implementation of SE-0193, the rule is now that the default argument expression of a publicly accessible function can only refer to publicly accessible declarations (not even @inlinable internal
or @usableFromInline internal
).
I believe this is paving the way for the displaying of default argument expressions in a module's generated interface file. Currently Swift just shows an unhelpful = default
, but I believe this will change to actually show the default argument. This can only realistically happen with this new access-control restriction in place (Edit: This is now happening).
Old answer (Swift 4)
This change is due to the work towards a resilience model that is already available via underscored attributes (@_inlineable
, @_versioned
, @_fixed_layout
), but is yet to be officially finalised (so you probably shouldn't be using these attributes yourself yet). You can read about the full proposed details of the resilience model here, as well as the the Swift evolution discussion on it here.
In short, an inlineable function is one whose implementation, as well as declaration, is exposed as a part of a module's interface and can therefore be inlined when called from another module. An inlineable function must therefore also be publically accessible to begin with (i.e public
or higher).
What you're running into is a change that makes default argument expressions for publically accessible functions inlineable, meaning that they must be available to be evaluated directly in the calling module's binary. This reduces the overhead of calling a function with default parameter values from another module, as the compiler no longer needs to do a function call for each default argument; it already knows the implementation.
I don't believe this change is officially documented in the release of Swift 4 itself, but it is confirmed by Swift compiler engineer Slava Pestov, who says:
Swift 3.1 added resilience diagnostics for inlineable code, which is not an officially supported feature, but in Swift 4 we switched these checks on for default argument expressions as well.
So if you have a publically accessible function with a default argument expression (such as MyClass.defaultValue
in your case), that expression can now only refer to things that are also a part of that module's interface. So you need to make defaultValue
publically accessible.
Unfortunately, there's currently no way to make a private
function's declaration part of a module's interface (which would allow for your usage of it in a default argument expression). The attribute that would facilitate this is @_versioned
, but it is forbidden with (file)private
due to the following reasons given by Slava Pestov:
It would be a trivial change to allow
@_versioned
onprivate
and
fileprivate
declarations, but there are two pitfalls to keep in mind:
Private symbols are mangled with a ‘discriminator’ which is basically a hash of the file name. So now it would be part of the ABI,
which seems fragile — you can’t move the private function to another
source file, or rename the source file.Similarly, right now a
@_versioned
function becoming public is an ABI compatible change. This would no longer work if you could have
private @_versioned
functions, because the symbol name would change if
it becamepublic
.
For these reasons we decided against “
private versioned
” as a concept.
I feel likeinternal
is enough here.
You could achieve this with a @_versioned var defaultValue
though:
open class MyClass {
private let value: Int
@_versioned static var defaultValue: Int {
return 10
}
public init(value: Int = MyClass.defaultValue) {
self.value = value
}
}
The declaration of MyClass.defaultValue
is now exported as a part of the module's interface, but still cannot be directly called from another module's code (as it's internal
). However, the compiler of that module can now call it when evaluating the default argument expression. But, as said earlier, you probably shouldn't be using an underscored attribute here; you should wait until the resilience model has been finalised.
Swift to Objective-C header does not contain Swift classes
Here's how I have gotten it to work. You can see a more large-scale answer here.
Change this:
class HelloWorld {
func hello() {
println("hello world")
}
}
To:
@objc class HelloWorld {
class func newInstance() -> HelloWorld {
return HelloWorld()
}
func hello() {
println("hello world")
}
}
Then, In your ObjC file:
#import "TestApp-Swift.h"
And call like this:
HelloWorld * helloWorld = [HelloWorld newInstance];
[helloWorld hello];
Related Topics
How to Get Data from Observedobject with Onreceive in Swiftui
Strange Error Nw_Protocol_Get_Quic_Image_Block_Invoke Dlopen Libquic Failed
How to Use .Svg Images in Swiftui
Spawning a Spritekit Node at a Random Time
How to Succinctly Get the First 5 Characters of a String in Swift
Adding a View to the Window Hierarchy
How to Apply Borders and Corner Radius to Uibarbuttonitem
How to Integrate Latest Sdwebimage API in My Swift Based Project
In Swift, How to Remove a Uiview from Memory Completely
Property Observers for Uiview Bounds and Frame React Differently
Changing Color of Button Text and State
How to Convert a Swift String to Cfstring
Open a Viewcontroller from Remote Notification
How to Use Dispatch Groups to Wait to Call Multiple Functions That Depend on Different Data
Swift: Loop Over Array Elements and Access Previous and Next Elements
Avspeechutterance - Swift - Initializing with a Phrase