Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

SwiftUI preview is not working when using the CocoaPods plugin #3059

Closed
Thomas-Vos opened this issue Jun 10, 2019 · 11 comments
Closed

SwiftUI preview is not working when using the CocoaPods plugin #3059

Thomas-Vos opened this issue Jun 10, 2019 · 11 comments

Comments

@Thomas-Vos
Copy link
Contributor

Thomas-Vos commented Jun 10, 2019

I cannot get Kotlin native working with the new SwiftUI preview. SwiftUI works fine in the simulator, but the Xcode preview shows this error:

Terminating app due to uncaught exception 'NSGenericException', reason: 'Only one Kotlin framework can be loaded currently'
terminating with uncaught exception of type NSException

I could only reproduce this with the CocoaPods plugin, so that seems related.

Here is a sample project. I added my changes as separate commits so you can see what I did.

Open the Xcode project in Xcode 11 on Mac OS Catalina beta. (you might need to follow this readme file to set it up). Navigate to the SwiftUIView.swift file and you will get this error in the preview:
Screenshot 2019-06-10 at 18 28 46

Here is the crash log the screenshot is referring to.

I originally reported this issue on Slack.

@SvyatoslavScherbina
Copy link
Contributor

Thanks, confirmed.

@SvyatoslavScherbina
Copy link
Contributor

After some investigation I consider this a bug in SwiftUI preview implementation.

This implementation internally produces *.preview-thunk.dylib files (under DerivedData). These dynamic libraries seem to contain (at least some of) the compiled application code and are dynamically loaded to the application binary built under ~/Library/Developer/Xcode/UserData/Previews. The .dylib also gets all the application dependencies linked. This obviously can't work properly with static dependencies, since it would make them contained twice in the binaries, which is somewhat incorrect at least for Objective-C code.

Xcode seems to apply some workaround for this by avoiding linking static dependencies. This workaround works in simple cases but doesn't work for CocoaPods dependencies. You can verify this by creating SwiftUI project with e.g. AFNetworking pod configured without use_frameworks and observing its classes twice (in *.preview-thunk.dylib and main binary).

Kotlin/Native produces static frameworks when imported via CocoaPods, so it is technically contained twice which results in the crash you reported.

@itstheceo
Copy link

Still experiencing this with Xcode 11.3 beta (11C24b). I thought the issue might be addressed by a fix introduced in 11.2 but it didn't seem to help.

Xcode Previews now passes BUILT_PRODUCTS_DIR correctly as a DYLD_FRAMEWORK_PATH when rendering previews to allow you to reference and resolve built frameworks and other products. (53967108) https://developer.apple.com/documentation/xcode_release_notes/xcode_11_2_release_notes

@GianfrancoMS
Copy link

Problem still persists in Xcode 11.3 (11C29)

@audkar
Copy link

audkar commented Jan 21, 2020

Do any workarounds exist? Solutions posted on Cocoapods issues tracker doesn't work in kotlin-native dependency case.

@SvyatoslavScherbina
Copy link
Contributor

Please try to make Kotlin framework dynamic. E.g. with Gradle Kotlin DSL:

kotlin {
    targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
        binaries.withType<org.jetbrains.kotlin.gradle.plugin.mpp.Framework> {
            isStatic = false
        }
    }
}

If you use a pod dependency in Gradle project, then ensure that your project's Podfile has use_frameworks!

@audkar
Copy link

audkar commented Jan 22, 2020

Notice: I am new to iOS development so I might misunderstand some basic concepts in iOS build toolchain or miss some obvious steps 😅

When I set framework to be compiled as dynamic I get this during build:

Gradle task error during xcode build

> Task :client-mobile:linkDebugFrameworkIos
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/konan/targets/ios_x64/native/debug.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/konan/targets/ios_x64/native/strict.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/common/stdlib/targets/ios_x64/native/runtime.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/platform/ios_x64/posix/targets/ios_x64/native/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /var/folders/ch/kkzfq3kx1kv62_plncvnx2h40000hc/T/native1156493527370136262/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /var/folders/ch/kkzfq3kx1kv62_plncvnx2h40000hc/T/native237765971876319384/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /var/folders/ch/kkzfq3kx1kv62_plncvnx2h40000hc/T/native2589246322831161163/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/platform/ios_x64/iconv/targets/ios_x64/native/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /var/folders/ch/kkzfq3kx1kv62_plncvnx2h40000hc/T/native7001350878957947942/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/platform/ios_x64/darwin/targets/ios_x64/native/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/platform/ios_x64/Foundation/targets/ios_x64/native/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
warning: linking module flags 'SDK Version': IDs have conflicting values ('[2 x i32] [i32 13, i32 0]' from /Users/user165606/.konan/kotlin-native-macos-1.3.61/klib/platform/ios_x64/CFNetwork/targets/ios_x64/native/cstubs.bc with '[2 x i32] [i32 13, i32 2]' from out)
Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_AFHTTPSessionManager", referenced from:
      objc-class-ref in result.o
  "_OBJC_CLASS_$_FIRAnalytics", referenced from:
      objc-class-ref in result.o
  "_OBJC_CLASS_$_FIRApp", referenced from:
      objc-class-ref in result.o
  "_OBJC_CLASS_$_FIRFirestore", referenced from:
      objc-class-ref in result.o
ld: symbol(s) not found for architecture x86_64
e: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors

> Task :client-mobile:linkDebugFrameworkIos FAILED

My gradle project structure:

mainModule (uses cocoapods plugin and has some cocopods dependencies)
    | - sharedModule1 (has some mpp deps)
    | - sharedModule2 (has some mpp deps)
    | - <...>

use_frameworks! is added to Podspec

When using static framework app works fine, just SwiftUI fails to show.

@itstheceo
Copy link

itstheceo commented Jan 26, 2020

Please try to make Kotlin framework dynamic. E.g. with Gradle Kotlin DSL:

kotlin {
    targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
        binaries.withType<org.jetbrains.kotlin.gradle.plugin.mpp.Framework> {
            isStatic = false
        }
    }
}

If you use a pod dependency in Gradle project, then ensure that your project's Podfile has use_frameworks!

I can confirm this works. I had some trouble initially but after ensuring the framework search paths for both my project and the pods project were set to $(inherited) and recursive, it started working.

Thanks!

Edit: I created a swift_ui branch for my template project, if anyone wants a working example

@SvyatoslavScherbina
Copy link
Contributor

@audkar CocoaPods plugin is not supposed to work flawlessly with dynamic Kotlin frameworks, so you need to add explicit linker options to link Kotlin framework with dependencies from CocoaPods.

@sherviiin
Copy link

sherviiin commented Mar 27, 2021

In case you are using the new template from Android Studio's KMP you will have packForXcode task in shared module's build file.
Just add :
framework.isStatic = false

@SvyatoslavScherbina
Copy link
Contributor

See KT-35723 for built-in support for dynamic frameworks in Kotlin CocoaPods Gradle plugin.
Not sure if there is anything else to do on Kotlin side, so I'm closing this issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants