diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.pbxproj b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.pbxproj index a07e1fd..33aedb7 100644 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.pbxproj @@ -11,13 +11,13 @@ 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; }; 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; }; 66CD08F82A6A5C0E00D66EFD /* FunctionWithDefaultArgumentsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD08F72A6A5C0E00D66EFD /* FunctionWithDefaultArgumentsExample.swift */; }; - 66CD08FF2A71559000D66EFD /* JavaDocComments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD08FE2A71559000D66EFD /* JavaDocComments.swift */; }; - 66CD090A2A78109A00D66EFD /* DataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD09092A78109A00D66EFD /* DataClass.swift */; }; 66CD090E2A79052C00D66EFD /* EnumClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD090D2A79052C00D66EFD /* EnumClass.swift */; }; 66CD09142A790FF300D66EFD /* SealedClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66CD09132A790FF300D66EFD /* SealedClass.swift */; }; 66D4CCF32AD6EDA000552E0E /* SuspendFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CCF22AD6EDA000552E0E /* SuspendFunction.swift */; }; - 66D4CD0A2AD919DF00552E0E /* ConstructorWithDefaultArgumentsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CD092AD919DF00552E0E /* ConstructorWithDefaultArgumentsExample.swift */; }; 66D4CD462ADD754E00552E0E /* FlowExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D4CD452ADD754E00552E0E /* FlowExample.swift */; }; + 66F10C7D2B19FD1300FFB2C8 /* InteropSamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F10C7C2B19FD1300FFB2C8 /* InteropSamples.swift */; }; + 66F10C7F2B19FD2E00FFB2C8 /* ResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F10C7E2B19FD2E00FFB2C8 /* ResultView.swift */; }; + 66F10C812B19FDA400FFB2C8 /* SealedInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F10C802B19FDA400FFB2C8 /* SealedInterface.swift */; }; 7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; }; /* End PBXBuildFile section */ @@ -39,13 +39,13 @@ 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = ""; }; 66CD08F72A6A5C0E00D66EFD /* FunctionWithDefaultArgumentsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionWithDefaultArgumentsExample.swift; sourceTree = ""; }; - 66CD08FE2A71559000D66EFD /* JavaDocComments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaDocComments.swift; sourceTree = ""; }; - 66CD09092A78109A00D66EFD /* DataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataClass.swift; sourceTree = ""; }; 66CD090D2A79052C00D66EFD /* EnumClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnumClass.swift; sourceTree = ""; }; 66CD09132A790FF300D66EFD /* SealedClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SealedClass.swift; sourceTree = ""; }; 66D4CCF22AD6EDA000552E0E /* SuspendFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendFunction.swift; sourceTree = ""; }; - 66D4CD092AD919DF00552E0E /* ConstructorWithDefaultArgumentsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstructorWithDefaultArgumentsExample.swift; sourceTree = ""; }; 66D4CD452ADD754E00552E0E /* FlowExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowExample.swift; sourceTree = ""; }; + 66F10C7C2B19FD1300FFB2C8 /* InteropSamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteropSamples.swift; sourceTree = ""; }; + 66F10C7E2B19FD2E00FFB2C8 /* ResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultView.swift; sourceTree = ""; }; + 66F10C802B19FDA400FFB2C8 /* SealedInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SealedInterface.swift; sourceTree = ""; }; 7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -70,38 +70,22 @@ path = "Preview Content"; sourceTree = ""; }; - 66CD08FD2A71556800D66EFD /* Common */ = { + 66CD09062A780AF800D66EFD /* ClassesAndInterfaces */ = { isa = PBXGroup; children = ( - 66CD08FE2A71559000D66EFD /* JavaDocComments.swift */, - ); - path = Common; - sourceTree = ""; - }; - 66CD09002A715BA500D66EFD /* DataTypes */ = { - isa = PBXGroup; - children = ( - ); - path = DataTypes; - sourceTree = ""; - }; - 66CD09062A780AF800D66EFD /* Classes */ = { - isa = PBXGroup; - children = ( - 66CD09092A78109A00D66EFD /* DataClass.swift */, 66CD090D2A79052C00D66EFD /* EnumClass.swift */, 66CD09132A790FF300D66EFD /* SealedClass.swift */, + 66F10C802B19FDA400FFB2C8 /* SealedInterface.swift */, ); - path = Classes; + path = ClassesAndInterfaces; sourceTree = ""; }; - 66CD090B2A78FD7800D66EFD /* UsualWorkflow */ = { + 66CD090B2A78FD7800D66EFD /* MoreAboutFunctions */ = { isa = PBXGroup; children = ( 66CD08F72A6A5C0E00D66EFD /* FunctionWithDefaultArgumentsExample.swift */, - 66D4CD092AD919DF00552E0E /* ConstructorWithDefaultArgumentsExample.swift */, ); - path = UsualWorkflow; + path = MoreAboutFunctions; sourceTree = ""; }; 66D4CD422ADD6EDE00552E0E /* Coroutines */ = { @@ -134,15 +118,15 @@ isa = PBXGroup; children = ( 66D4CD422ADD6EDE00552E0E /* Coroutines */, - 66CD090B2A78FD7800D66EFD /* UsualWorkflow */, - 66CD09062A780AF800D66EFD /* Classes */, - 66CD09002A715BA500D66EFD /* DataTypes */, - 66CD08FD2A71556800D66EFD /* Common */, + 66CD090B2A78FD7800D66EFD /* MoreAboutFunctions */, + 66CD09062A780AF800D66EFD /* ClassesAndInterfaces */, 058557BA273AAA24004C7B11 /* Assets.xcassets */, 7555FF82242A565900829871 /* ContentView.swift */, 7555FF8C242A565B00829871 /* Info.plist */, 2152FB032600AC8F00CF470E /* iOSApp.swift */, 058557D7273AAEEB004C7B11 /* Preview Content */, + 66F10C7C2B19FD1300FFB2C8 /* InteropSamples.swift */, + 66F10C7E2B19FD2E00FFB2C8 /* ResultView.swift */, ); path = iosApp; sourceTree = ""; @@ -249,13 +233,13 @@ 66D4CCF32AD6EDA000552E0E /* SuspendFunction.swift in Sources */, 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */, 66CD090E2A79052C00D66EFD /* EnumClass.swift in Sources */, - 66CD090A2A78109A00D66EFD /* DataClass.swift in Sources */, + 66F10C7D2B19FD1300FFB2C8 /* InteropSamples.swift in Sources */, + 66F10C7F2B19FD2E00FFB2C8 /* ResultView.swift in Sources */, 66D4CD462ADD754E00552E0E /* FlowExample.swift in Sources */, 66CD08F82A6A5C0E00D66EFD /* FunctionWithDefaultArgumentsExample.swift in Sources */, 66CD09142A790FF300D66EFD /* SealedClass.swift in Sources */, - 66D4CD0A2AD919DF00552E0E /* ConstructorWithDefaultArgumentsExample.swift in Sources */, - 66CD08FF2A71559000D66EFD /* JavaDocComments.swift in Sources */, 7555FF83242A565900829871 /* ContentView.swift in Sources */, + 66F10C812B19FDA400FFB2C8 /* SealedInterface.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -390,6 +374,7 @@ "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", ); INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -418,6 +403,7 @@ "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", ); INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate index acfbf3f..b366e84 100644 Binary files a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate and b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/DataClass.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/DataClass.swift deleted file mode 100644 index 1912c0f..0000000 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/DataClass.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Foundation -//import shared -// -//class DataClassExample { -// -// let data = DataClass(param1: "abc", param2: 123, param3: true) -// let data2 = DataClass(param1: "def", param2: 456, param3: false) -// -// func copy(){ -// let dataCopy = data.doCopy(param1: "def") -// print(dataCopy) -// } -// -// func equals(){ -// print(data.isEqual(data)) -// print(data.isEqual(data2)) -// } -// -// func toString(){ -// print("data = \(data)") -// } -// -//} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/EnumClass.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/EnumClass.swift deleted file mode 100644 index e2db5ad..0000000 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/EnumClass.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Foundation -import shared - -class EnumClassExample{ - func useEnumClass() { - let e1 = EnumClass.entryOne - let _ = EnumClass.entryTwo - - let _ = EnumClass.entryOne.name - let _ = EnumClass.entryOne.type - - let _ = EnumClass.companion.findByType(type: "entry_two") - let _ = EnumClass.companion.findByType(type: "entry_two_trheee") - - switchEnumClass(enumClassExample: e1) - } - - private func switchEnumClass(enumClassExample: EnumClass) { - switch enumClassExample { - case .entryOne: print("entryOne") - case .entryTwo: print("entryTwo") - } - } -} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/SealedClass.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/SealedClass.swift deleted file mode 100644 index b99478b..0000000 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Classes/SealedClass.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation -import shared - -class SealedClassExample { - func example(s: SealedClass) { - switch onEnum(of: s) { - case .object: print("object") - case .simple(let simple): print("simple \(simple.param1)") - case .data(let data): print("data \(data.param1) \(data.param2)") - } - } -} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/EnumClass.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/EnumClass.swift new file mode 100644 index 0000000..e6d504b --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/EnumClass.swift @@ -0,0 +1,24 @@ +import Foundation +import shared + + +func useEnumClass() { + let e1 = EnumClass.entryOne + let _ = EnumClass.entryTwo + + let _ = EnumClass.entryOne.name + let _ = EnumClass.entryOne.type + + let _ = EnumClass.companion.findByType(type: "entry_two") + let _ = EnumClass.companion.findByType(type: "entry_two_trheee") + + switchEnumClass(enumClassExample: e1) +} + +private func switchEnumClass(enumClassExample: EnumClass) { + switch (enumClassExample) { + case .entryOne: print("entryOne") + case .entryTwo: print("entryTwo") + } +} + diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedClass.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedClass.swift new file mode 100644 index 0000000..d79e79c --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedClass.swift @@ -0,0 +1,16 @@ +import Foundation +import shared + +func sealedClassExample(){ + printSealedClassType(s: SealedClass.Object()) + printSealedClassType(s: SealedClass.Simple(param1: "123")) + printSealedClassType(s: SealedClass.Data(param1: "123", param2: true)) +} + +private func printSealedClassType(s: SealedClass) { + switch onEnum(of: s) { + case .object: print("object") + case .simple(let simple): print("simple \(simple.param1)") + case .data(let data): print("data \(data.param1) \(data.param2)") + } +} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedInterface.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedInterface.swift new file mode 100644 index 0000000..641d3a1 --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ClassesAndInterfaces/SealedInterface.swift @@ -0,0 +1,26 @@ +import Foundation +import shared + +func sealedInterfaceExample(){ + switchOnSealedInterfaces(sealedInterfaces: SealedInterfacesFirstImpl()) + switchOnSealedInterfaces(sealedInterfaces: SealedInterfacesSecondImpl()) +} + +private func switchOnSealedInterfaces(sealedInterfaces: SealedInterfaces){ + switch(onEnum(of: sealedInterfaces)){ + case .first: print((sealedInterfaces as! any SealedInterfacesFirst as SealedInterfacesFirst).firstFunctionExample()) + case .second: print((sealedInterfaces as! any SealedInterfacesSecond as SealedInterfacesSecond).secondFunctionExample()) + } +} + +class SealedInterfacesFirstImpl : SealedInterfacesFirst { + func firstFunctionExample() -> String { + return "first" + } +} + +class SealedInterfacesSecondImpl : SealedInterfacesSecond { + func secondFunctionExample() -> String { + return "second" + } +} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Common/JavaDocComments.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Common/JavaDocComments.swift deleted file mode 100644 index 1a8391a..0000000 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Common/JavaDocComments.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation -import shared - -// Problem statement -func testJavaDocComments(){ - let javaDocComments = JavaDocComments() - javaDocComments.commentProperty - javaDocComments.commentFunction(arg1: 3) -} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ContentView.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ContentView.swift index c2db060..a5a2af9 100644 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ContentView.swift +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ContentView.swift @@ -2,59 +2,32 @@ import SwiftUI import shared struct ContentView: View { - var body: some View { - VStack { - Text("Swift Interop Playground") - Button("Go", action: { - //testClasses() - - //testCoroutines() - - //testUsualWorkflow() - }) + var body: some View { + let sections = sections() + NavigationView { + VStack { + List { + ForEach(sections) { section in + Section(section.title) { + ForEach(section.samples) { sample in + NavigationLink(destination: ResultView(sample: sample)) { + Text(sample.title) + } + } + } + } + } + .listStyle(.sidebar) + } + .navigationTitle("Kotlin/Swift Interop Playground (SKIE)") + .navigationBarTitleDisplayMode(.inline) } - } - - func testClasses(){ - //Data classes - //If default argument interop is enabled, it's not necessary to specify all arguments. - //DataClassExample().copy() - - //Enum classes - //SKIE creates real Swift enums, and automatically converts them from Kotlin enums. Enums are exhaustive. - //EnumClassExample().useEnumClass() - - //SealedClassExample().example(s: SealedClass.Object()) - //SealedClassExample().example(s: SealedClass.Simple(param1: "param1")) - //SealedClassExample().example(s: SealedClass.Data(param1: "param1", param2: true)) - } - - @MainActor func testCoroutines(){ - //Suspend functions - //Translated into callback, experimentally - into async / await. Libraries like SKIE and KMP-NativeCoroutines can be used to improve the interop. - //SuspendFunctionExample().example() - - //Flows - //Translated into callback, experimentally - into async / await. Generic type arguments are lost. Libraries like SKIE and KMP-NativeCoroutines can be used to improve the interop and provide cancellation support. - //FlowExample().example() - - //SuspendFunctionExample().exampleWithCancellation() - //FlowExample().exampleWithCancellation() - } - - func testUsualWorkflow(){ - //Constructor with default arguments - //If default argument interop is enabled, it's notnecessary to specify all arguments. - //ConstructorWithDefaultArgumentsExample().example() - - //Function with default arguments - //If annotated, it's not necessary to specify all the arguments. - //FunctionWithDefaultArgumentsExample().example() } } + struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } + static var previews: some View { + ContentView() + } } diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/FlowExample.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/FlowExample.swift index c0d8287..7cc101a 100644 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/FlowExample.swift +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/FlowExample.swift @@ -1,21 +1,22 @@ import Foundation import shared + + @MainActor -class FlowExample{ - func example(){ - Task { - for await it in NumberFlowRepository().getNumbers() { - print("Got number: \(it)") - } +func flowExample(){ + Task { + for await it in NumberFlowRepository().getNumbers() { + print("Got number: \(it)") } } +} - func exampleWithCancellation(){ - Task { - for await it in NumberFlowRepository().getNumbers() { - print("Got number: \(it)") - } - }.cancel() - } +func flowWithCancellationExample(){ + Task { + for await it in NumberFlowRepository().getNumbers() { + print("Got number: \(it)") + } + }.cancel() } + diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/SuspendFunction.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/SuspendFunction.swift index d3ce31a..f54155d 100644 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/SuspendFunction.swift +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/Coroutines/SuspendFunction.swift @@ -1,20 +1,19 @@ import Foundation import shared -class SuspendFunctionExample{ - @MainActor - func example(){ - Task { - let result = try await ThingRepository().getThing(succeed: true) - print("Got result: \(result)") - } +@MainActor +func suspendFunctionExample(){ + Task { + let result = try await ThingRepository().getThing(succeed: true) + print("Got result: \(result)") } +} - @MainActor - func exampleWithCancellation() { - Task { - let result = try await ThingRepository().getThing(succeed: true) - print("Got result: \(result)") - }.cancel() - } +@MainActor +func suspendFunctionWithCancellationExample() { + Task { + let result = try await ThingRepository().getThing(succeed: true) + print("Got result: \(result)") + }.cancel() } + diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/InteropSamples.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/InteropSamples.swift new file mode 100644 index 0000000..d65d9a2 --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/InteropSamples.swift @@ -0,0 +1,91 @@ +import Foundation +import shared + +struct InteropSection: Identifiable { + let id = UUID() + let title: String + let samples: [InteropSample] +} + +struct InteropSample: Identifiable { + let id = UUID() + let title: String + var description: String = "" + let action: @MainActor () -> () +} + +let outputMarker = "Sample output: " +let printedToConsoleNote = "Sample output is printed to the console." + +func sections() -> [InteropSection] { + [moreAboutFunctionsSection(), + classesAndInterfacesSection(), + coroutinesSection()] +} + +func classesAndInterfacesSection() -> InteropSection { + InteropSection(title: "Classes and interfaces", samples: [ + InteropSample( + title: "Enum classes", + description: "No equivalent enum is generated on the Swift side, and default case must be specified in a switch expression. Instead an object with static elements is generated. Improved interop available with SKIE." + ) { + useEnumClass() + }, + InteropSample( + title: "Sealed classes", + description: "A class with heirs is generated. Passing to a switch statement requires a default case. Improved interop available with SKIE." + ) { + sealedClassExample() + }, + InteropSample( + title: "Sealed Interfaces", + description: "Separate protocols were generated that were not related to each other." + ) { + sealedInterfaceExample() + } + ]) +} + +func moreAboutFunctionsSection() -> InteropSection { + InteropSection(title: "More about Functions", samples: [ + InteropSample(title: "Functions with default arguments", + description: "You always have to specify all the function arguments. Improved interop available with SKIE.") { + FunctionWithDefaultArgumentsExample().example() + } + ]) +} + +func coroutinesSection() -> InteropSection { + InteropSection(title: "Coroutines", samples: [ + InteropSample( + title: "Suspend functions", + description: + """ + Translated into callback, experimentally - into async / await. Libraries like SKIE and KMP-NativeCoroutines can be used to improve the interop and provide cancellation support. + """) { + suspendFunctionExample() + }, + InteropSample( + title: "Cancellation of suspend functions", + description: "Task cancellation is stubbed. Suspend function returns value, no CancellationError." + ) { + suspendFunctionWithCancellationExample() + }, + + InteropSample( + title: "Flows", + description: + """ + Translated into callback, experimentally - into async / await. Generic type arguments are lost. Libraries like SKIE and KMP-NativeCoroutines can be used to improve the interop and provide cancellation support. + """ + ) { + flowExample() + }, + InteropSample( + title: "Cancellations of Flows", + description: "Task cancellation is stubbed. Flow continues emitting values." + ) { + flowWithCancellationExample() + } + ]) +} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/UsualWorkflow/FunctionWithDefaultArgumentsExample.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/MoreAboutFunctions/FunctionWithDefaultArgumentsExample.swift similarity index 100% rename from kotlin-swift-interopedia-samples-skie/iosApp/iosApp/UsualWorkflow/FunctionWithDefaultArgumentsExample.swift rename to kotlin-swift-interopedia-samples-skie/iosApp/iosApp/MoreAboutFunctions/FunctionWithDefaultArgumentsExample.swift diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ResultView.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ResultView.swift new file mode 100644 index 0000000..8afd453 --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/ResultView.swift @@ -0,0 +1,39 @@ +import SwiftUI +import Foundation + +struct ResultView: View { + let sample: InteropSample + + var body: some View { + List { + Section(header: Text(sample.title)) { + Text(sample.description) + } + .headerProminence(.increased) + .onAppear { runSample(sample: sample) } + } + } +} + +@MainActor +func runSample(sample: InteropSample) { + print("-------------------------") + print("-------------------------") + print(sample.title) + print("-------------------------") + print("Sample output:") + print("-------------------------") + sample.action() +} + +struct ResultView_Previews: PreviewProvider { + static var previews: some View { + ResultView( + sample: InteropSample( + title: "Title", + description: "Description", + action: {} + ) + ) + } +} diff --git a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/UsualWorkflow/ConstructorWithDefaultArgumentsExample.swift b/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/UsualWorkflow/ConstructorWithDefaultArgumentsExample.swift deleted file mode 100644 index 8d94a35..0000000 --- a/kotlin-swift-interopedia-samples-skie/iosApp/iosApp/UsualWorkflow/ConstructorWithDefaultArgumentsExample.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation -import shared - -class ConstructorWithDefaultArgumentsExample { - func example() { - let result = ConstructorWithDefaultArgumentsClass(param1: "234") - print("result \(result.param1) \(result.param2) \(result.param3)") - } -} diff --git a/kotlin-swift-interopedia-samples-skie/shared/build.gradle.kts b/kotlin-swift-interopedia-samples-skie/shared/build.gradle.kts index 1566fc7..428ce4f 100644 --- a/kotlin-swift-interopedia-samples-skie/shared/build.gradle.kts +++ b/kotlin-swift-interopedia-samples-skie/shared/build.gradle.kts @@ -3,7 +3,7 @@ import co.touchlab.skie.configuration.DefaultArgumentInterop plugins { kotlin("multiplatform") id("com.android.library") - id("co.touchlab.skie") version ("0.5.0") + id("co.touchlab.skie") version ("0.5.6") } @OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) @@ -36,7 +36,7 @@ kotlin { val commonMain by getting { dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") - implementation("co.touchlab.skie:configuration-annotations:0.5.0") + implementation("co.touchlab.skie:configuration-annotations:0.5.6") } } val commonTest by getting { @@ -53,12 +53,4 @@ android { defaultConfig { minSdk = 21 } -} - -skie { - features { - group { - DefaultArgumentInterop.Enabled(true) - } - } } \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/DataClass.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/DataClass.kt deleted file mode 100644 index 6626135..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/DataClass.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.jetbrains.swiftinteropplayground.classes - -data class DataClass( - val param1: String, - val param2: Int, - val param3: Boolean -) \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/SealedInterfaces.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/SealedInterfaces.kt new file mode 100644 index 0000000..ed2f404 --- /dev/null +++ b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/classes/SealedInterfaces.kt @@ -0,0 +1,23 @@ +package com.jetbrains.swiftinteropplayground.classesandinterfaces + +sealed interface SealedInterfaces { + + interface First : SealedInterfaces { + fun firstFunctionExample(): String + } + + interface Second : SealedInterfaces { + fun secondFunctionExample(): String + } +} + +fun sealedInterfaceExample(sie: SealedInterfaces) { + when (sie) { + is SealedInterfaces.First -> { + sie.firstFunctionExample() + } + is SealedInterfaces.Second -> { + sie.secondFunctionExample() + } + } +} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/common/JavaDocComments.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/common/JavaDocComments.kt deleted file mode 100644 index 08fc7ee..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/common/JavaDocComments.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.jetbrains.swiftinteropplayground.common - -/** - * A class commented with documentation. - */ -class JavaDocComments { - - /** - * A property commented with documentation. - */ - val commentProperty: Int = 0 - - /** - * A function commented with documentation. - * @param arg1 Documentation for argument - * @return Documentation for return value - */ - fun commentFunction(arg1: Int): Int { - return 0 - } -} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/datatypes/Primitives.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/datatypes/Primitives.kt deleted file mode 100644 index 9ad6a48..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/datatypes/Primitives.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.jetbrains.swiftinteropplayground.datatypes - -class Primitives { - fun byteType(b: Byte): Byte { - return b - } - - fun shortType(s: Short): Short { - return s - } - - fun intType(i: Int): Int { - return i - } - - fun longType(l: Long): Long { - return l - } - - fun floatType(f: Float): Float { - return f - } - - fun doubleType(d: Double): Double { - return d - } - - fun stringType(s: String): String { - return s - } - - fun charType(c: Char): Char { - return c - } - - fun booleanType(b: Boolean): Boolean { - return b - } -} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/functions/DSL.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/functions/DSL.kt deleted file mode 100644 index c17441a..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/functions/DSL.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.jetbrains.swiftinteropplayground.functions - -@DslMarker -annotation class DslMarkerExample - -data class Experiment(val key: String, val description: String) - -@DslMarkerExample -data class ExperimentsDsl(val list: MutableList = mutableListOf()) { - fun enable(experiment: Experiment) { - list += experiment - } - -} - -@DslMarkerExample -data class Dsl(val experiments: ExperimentsDsl = ExperimentsDsl()) { - fun experiments(block: ExperimentsDsl.() -> Unit = {}) { - experiments.block() - } -} - -fun example() { - val dsl = Dsl().apply { - experiments { - enable(Experiment(key = "key1", description = "desc1")) - } - } - println(dsl) -} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/FunctionWithDefaultArgumentsClass.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/moreaboutfunctions/FunctionWithDefaultArgumentsClass.kt similarity index 80% rename from kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/FunctionWithDefaultArgumentsClass.kt rename to kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/moreaboutfunctions/FunctionWithDefaultArgumentsClass.kt index c3b590d..725203d 100644 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/FunctionWithDefaultArgumentsClass.kt +++ b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/moreaboutfunctions/FunctionWithDefaultArgumentsClass.kt @@ -1,4 +1,4 @@ -package com.jetbrains.swiftinteropplayground.usualworkflow +package com.jetbrains.swiftinteropplayground.moreaboutfunctions import co.touchlab.skie.configuration.annotations.DefaultArgumentInterop diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/ConstructorWithDefaultArguments.kt b/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/ConstructorWithDefaultArguments.kt deleted file mode 100644 index fd1dac1..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/commonMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/ConstructorWithDefaultArguments.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.jetbrains.swiftinteropplayground.usualworkflow - -class ConstructorWithDefaultArgumentsClass( - val param1: String, - val param2: Int = 300, - val param3: Boolean = false -) \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples-skie/shared/src/iosMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/DefaultArgumentsBridge.kt b/kotlin-swift-interopedia-samples-skie/shared/src/iosMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/DefaultArgumentsBridge.kt deleted file mode 100644 index 17f8a5b..0000000 --- a/kotlin-swift-interopedia-samples-skie/shared/src/iosMain/kotlin/com/jetbrains/swiftinteropplayground/usualworkflow/DefaultArgumentsBridge.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jetbrains.swiftinteropplayground.usualworkflow - -fun createDefaultArguments(): FunctionWithDefaultArgumentsClass { - return FunctionWithDefaultArgumentsClass() -} - -fun functionWithDefaultArgument(defaultArguments: FunctionWithDefaultArgumentsClass){ - defaultArguments.functionWithDefaultArgument() -} \ No newline at end of file diff --git a/kotlin-swift-interopedia-samples/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate b/kotlin-swift-interopedia-samples/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate index 0234105..e0f2918 100644 Binary files a/kotlin-swift-interopedia-samples/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate and b/kotlin-swift-interopedia-samples/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/pamelahill.xcuserdatad/UserInterfaceState.xcuserstate differ