Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8de82aa

Browse files
committed
Add annotations for interop sections
1 parent 3f47f14 commit 8de82aa

File tree

13 files changed

+232
-0
lines changed

13 files changed

+232
-0
lines changed

‎README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ You can edit the code, rerun the app, and see how the output has changed.
3737
<tr><td><a href="/docs/overview/Top-level%20functions.md">Top-level functions</a></td><td>You can access a top-level function via the wrapper class: TopLevelFunctionKt.topLevelFunction().</td></tr>
3838
<tr><td><a href="/docs/overview/Exceptions.md">Exceptions</a></td><td>If you invoke a Kotlin function that throws an exception and doesn't declare it with `@Throws`, that crashes the app. Declared exceptions are converted to NSError and must be handled.</td></tr>
3939
<tr><td><a href="/docs/overview/PublicAPI.md">Public API</a></td><td>Public classes, functions, and properties are visible from Swift. Marking classes, functions, and properties internal will exclude them from the public API of the shared code, and they will not be visible in Swift.</td></tr>
40+
<tr><td><a hred="/docs/overview/ObjCName.md">Interop annotation - @ObjCName</a><td><td>Gives better Objective-C/Swift names to Kotlin constructs like classes, functions and so on, without actually renaming the Kotlin constructs. Experimental.</td></tr>
41+
<tr><td><a hred="/docs/overview/HiddenFromObj.md">Interop annotations - @HiddenFromObj</a><td><td>Hides a Kotlin declaration from Objective-C/Swift. Experimental.</td></tr>
42+
<tr><td><a hred="/docs/overview/ShouldRefineInSwift.md">Interop annotations - @ShouldRefineInSwift</a><td><td>Helps to replace a Kotlin declaration with a wrapper written in Swift. Experimental.</td></tr>
4043
<tr><td><a href="/docs/overview/KDocComments.md">KDoc comments</a></td><td>You can see certain KDoc comments at development time. In Xcode, use Option+Double left click to see the docs. Note that many KDocs features don't work in Xcode, like properties on constructors (@property) aren't visible. In Fleet, use the 'Show Documentation' action.</td></tr>
4144
</table>
4245

‎docs/overview/HiddenFromObjC.md‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## Interop annotation - @HiddenFromObjC
2+
3+
Hides a Kotlin declaration from Objective-C/Swift. Experimental.
4+
5+
### Explanations
6+
7+
In Kotlin:
8+
```kotlin
9+
@HiddenFromObjC
10+
fun myKotlinOnlyFunction(){
11+
println("Only Kotlin!")
12+
}
13+
```
14+
15+
In Swift:
16+
```swift
17+
func hiddenFromObjCExample(){
18+
//Uncommenting gives compilation error
19+
//myKotlinOnlyFunction()
20+
}
21+
```
22+
23+
Using the `@HiddenFromObjC` annotation, we can prevent the export of this function to Objective-C/Swift. This is different from using the `internal` keyword, because the construct can still be used from other Kotlin compilation units, just not from Objective-C/Swift.
24+
25+
#### Setup
26+
27+
Since the annotation is experimental, it is necessary to opt-in.
28+
29+
```kotlin
30+
sourceSets {
31+
all {
32+
languageSettings.optIn("kotlin.experimental.ExperimentalObjCRefinement")
33+
}
34+
}
35+
```
36+
37+
### Credits
38+
With thanks to [Rick Clephas](https://github.com/rickclephas) for the annotation contribution and example code.
39+
40+
---
41+
[Table of contents](/README.md)

‎docs/overview/ObjCName.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## Interop annotations - @ObjCName
2+
3+
Gives better Objective-C/Swift names to Kotlin constructs like classes, functions and so on, without actually renaming the Kotlin constructs. Experimental.
4+
5+
### Explanations
6+
7+
In Kotlin:
8+
```kotlin
9+
@ObjCName(swiftName = "MySwiftArray")
10+
class MyKotlinArray {
11+
@ObjCName("index")
12+
fun indexOf(@ObjCName("of") element: String): Int = 1
13+
}
14+
```
15+
16+
In Swift:
17+
```swift
18+
let array = MySwiftArray()
19+
let index = array.index(of: "element")
20+
```
21+
22+
Here we are renaming a class, function, and its parameter using the `@ObjCName` annotation so that we can use the alternative names from Objective-C/Swift. This is especially useful to change the Swift names of constructs to more idiomatic names without actually renaming them in Kotlin.
23+
24+
#### Setup
25+
26+
Since these annotations are experimental, it is necessary to opt into them in.
27+
```kotlin
28+
sourceSets {
29+
all {
30+
languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
31+
}
32+
}
33+
```
34+
35+
### Credits
36+
With thanks to [Rick Clephas](https://github.com/rickclephas) for the annotation contribution and example code.
37+
38+
---
39+
[Table of contents](/README.md)

‎docs/overview/ShouldRefineInSwift.md‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## Interop annotations - @ShouldRefineInSwift
2+
3+
Helps to replace a Kotlin declaration with a wrapper written in Swift. Experimental.
4+
5+
### Explanations
6+
7+
In Kotlin:
8+
```kotlin
9+
interface Person {
10+
@ShouldRefineInSwift
11+
val namePair: Pair<String, String>
12+
}
13+
14+
class RealPerson: Person {
15+
override val namePair = "First" to "Last"
16+
}
17+
```
18+
19+
In Swift:
20+
```swift
21+
extension Person {
22+
var name: (firstName: String, lastName: String) {
23+
let namePair = __namePair
24+
return (namePair.first! as String, namePair.second! as String)
25+
}
26+
}
27+
28+
func shouldRefineInSwiftExample(){
29+
let authorNames = RealPerson().name
30+
print("Author is: \(authorNames.firstName) \(authorNames.lastName)")
31+
}
32+
```
33+
34+
Using the `@ShouldRefineInSwift` annotation, we are indicating that we intend to refine the definition of `namePair` in Swift. The annotation marks the property as swift_private in the generated Objective-C API. Such declarations get a __ prefix, which makes them invisible from Xcode’s autocomplete.
35+
36+
37+
#### Setup
38+
39+
Since these annotations are experimental, it is necessary to opt into them in.
40+
```kotlin
41+
sourceSets {
42+
all {
43+
languageSettings.optIn("kotlin.experimental.ExperimentalObjCRefinement")
44+
}
45+
}
46+
```
47+
48+
### Credits
49+
With thanks to [Rick Clephas](https://github.com/rickclephas) for the annotation contribution and example code.
50+
51+
---
52+
[Table of contents](/README.md)

‎kotlin-swift-interopedia-samples/iosApp/iosApp.xcodeproj/project.pbxproj‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@
7575
66D4CD442ADD715400552E0E /* FlowKMPNativeCoroutinesExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CD432ADD715400552E0E /* FlowKMPNativeCoroutinesExample.swift */; };
7676
66D4CD482ADD784F00552E0E /* FlowExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CD472ADD784F00552E0E /* FlowExample.swift */; };
7777
66D4CD4C2ADEA4C000552E0E /* ExceptionsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CD4B2ADEA4C000552E0E /* ExceptionsExample.swift */; };
78+
66F10C792B19DC0700FFB2C8 /* HiddenFromSwiftExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F10C782B19DC0700FFB2C8 /* HiddenFromSwiftExample.swift */; };
7879
7535496A2AE116ED0016A54B /* ResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753549692AE116ED0016A54B /* ResultView.swift */; };
7980
7535496C2AE1376C0016A54B /* InteropSamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7535496B2AE1376C0016A54B /* InteropSamples.swift */; };
8081
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
82+
E59830997CE3DC9E31D1E9C1 /* ObjCNameExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5983E5A1B87DC036ABBEFAD /* ObjCNameExample.swift */; };
83+
E598319E705FEB827303DCB9 /* ShouldRefineInSwiftExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E59839FB583E1FD27DC551A2 /* ShouldRefineInSwiftExample.swift */; };
8184
/* End PBXBuildFile section */
8285

8386
/* Begin PBXCopyFilesBuildPhase section */
@@ -158,11 +161,14 @@
158161
66D4CD432ADD715400552E0E /* FlowKMPNativeCoroutinesExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowKMPNativeCoroutinesExample.swift; sourceTree = "<group>"; };
159162
66D4CD472ADD784F00552E0E /* FlowExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowExample.swift; sourceTree = "<group>"; };
160163
66D4CD4B2ADEA4C000552E0E /* ExceptionsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExceptionsExample.swift; sourceTree = "<group>"; };
164+
66F10C782B19DC0700FFB2C8 /* HiddenFromSwiftExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenFromSwiftExample.swift; sourceTree = "<group>"; };
161165
753549692AE116ED0016A54B /* ResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultView.swift; sourceTree = "<group>"; };
162166
7535496B2AE1376C0016A54B /* InteropSamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteropSamples.swift; sourceTree = "<group>"; };
163167
7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
164168
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
165169
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
170+
E59839FB583E1FD27DC551A2 /* ShouldRefineInSwiftExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShouldRefineInSwiftExample.swift; sourceTree = "<group>"; };
171+
E5983E5A1B87DC036ABBEFAD /* ObjCNameExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjCNameExample.swift; sourceTree = "<group>"; };
166172
/* End PBXFileReference section */
167173

168174
/* Begin PBXFrameworksBuildPhase section */
@@ -208,6 +214,9 @@
208214
66D4CD1D2AD9587900552E0E /* TopLevelFunctionExample.swift */,
209215
66D4CD4B2ADEA4C000552E0E /* ExceptionsExample.swift */,
210216
669CC60F2AEA910800DC4B6E /* PublicApiExample.swift */,
217+
E5983E5A1B87DC036ABBEFAD /* ObjCNameExample.swift */,
218+
66F10C782B19DC0700FFB2C8 /* HiddenFromSwiftExample.swift */,
219+
E59839FB583E1FD27DC551A2 /* ShouldRefineInSwiftExample.swift */,
211220
);
212221
path = Overview;
213222
sourceTree = "<group>";
@@ -311,6 +320,7 @@
311320
7555FF7D242A565900829871 /* iosApp */,
312321
7555FF7C242A565900829871 /* Products */,
313322
7555FFB0242A642200829871 /* Frameworks */,
323+
E5983519E4CA8889A93ADA6B /* configuration */,
314324
);
315325
sourceTree = "<group>";
316326
};
@@ -351,6 +361,14 @@
351361
name = Frameworks;
352362
sourceTree = "<group>";
353363
};
364+
E5983519E4CA8889A93ADA6B /* configuration */ = {
365+
isa = PBXGroup;
366+
children = (
367+
);
368+
name = configuration;
369+
path = iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/configuration;
370+
sourceTree = "<group>";
371+
};
354372
/* End PBXGroup section */
355373

356374
/* Begin PBXNativeTarget section */
@@ -488,6 +506,7 @@
488506
66D4CD222AD95DC900552E0E /* TopLevelPropertyMutableExample.swift in Sources */,
489507
66D4CCE62AD6DDC400552E0E /* SuspendFunctionExample.swift in Sources */,
490508
669CC6122AEE9CC200DC4B6E /* SuspendFunctionKMPNativeCoroutinesWithCancellationExample.swift in Sources */,
509+
66F10C792B19DC0700FFB2C8 /* HiddenFromSwiftExample.swift in Sources */,
491510
66D4CD082AD9173F00552E0E /* ConstructorWithDefaultArgumentsExample.swift in Sources */,
492511
665A18952A9614E9000087BE /* FunctionReturnsLambda.swift in Sources */,
493512
66D4CCD82AD6835D00552E0E /* FunctionWithLambdaArgsExample.swift in Sources */,
@@ -517,6 +536,8 @@
517536
66D4CD042AD81B6F00552E0E /* StarProjectionExample.swift in Sources */,
518537
66D4CCFE2AD80F2B00552E0E /* GenericFunctionsExample.swift in Sources */,
519538
7555FF83242A565900829871 /* ContentView.swift in Sources */,
539+
E59830997CE3DC9E31D1E9C1 /* ObjCNameExample.swift in Sources */,
540+
E598319E705FEB827303DCB9 /* ShouldRefineInSwiftExample.swift in Sources */,
520541
);
521542
runOnlyForDeploymentPostprocessing = 0;
522543
};

‎kotlin-swift-interopedia-samples/iosApp/iosApp/InteropSamples.swift‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,23 @@ func overviewSection() -> InteropSection {
7575
protectedPropertyExample()
7676
protectedFunctionExample()
7777
},
78+
InteropSample(
79+
title: "@ObjCName",
80+
description: """
81+
Gives better Objective-C/Swift names to Kotlin constructs like classes, functions and so on, without actually renaming the Kotlin constructs.
82+
"""
83+
) {
84+
objCNameExample()
85+
},
86+
InteropSample(title: "@HiddenFromObjC",
87+
description: "Hides a Kotlin declaration from Objective-C/Swift.",
88+
action: {
89+
hiddenFromObjCExample()
90+
}),
91+
InteropSample(title: "@ShouldRefineInSwift",
92+
description: "Helps to replace a Kotlin declaration with a wrapper written in Swift.") {
93+
shouldRefineInSwiftExample()
94+
},
7895
InteropSample(
7996
title: "KDoc Comments",
8097
description:
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
import shared
3+
4+
func hiddenFromObjCExample(){
5+
//Uncomment to see error
6+
//myKotlinOnlyFunction()
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Foundation
2+
import shared
3+
4+
func objCNameExample(){
5+
let array = MySwiftArray()
6+
let index = array.index(of: "element")
7+
print(index)
8+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Foundation
2+
import shared
3+
4+
extension Person {
5+
var name: (firstName: String, lastName: String) {
6+
let namePair = __namePair
7+
return (namePair.first! as String, namePair.second! as String)
8+
}
9+
}
10+
11+
func shouldRefineInSwiftExample(){
12+
let authorNames = RealPerson().name
13+
print("Author is: \(authorNames.firstName)\(authorNames.lastName)")
14+
}

‎kotlin-swift-interopedia-samples/shared/build.gradle.kts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ kotlin {
3838
sourceSets {
3939
all {
4040
languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
41+
languageSettings.optIn("kotlin.experimental.ExperimentalObjCRefinement")
4142
}
4243

4344
val commonMain by getting {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /