New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Friction adding swift plugin to objective-c project #16049

Open
xster opened this Issue Mar 29, 2018 · 20 comments

Comments

Projects
None yet
@xster
Contributor

xster commented Mar 29, 2018

flutter create a non-swift project

In pubspec.yaml, add a swift plugin such as flutter_iap.

  1. flutter run warns about use_frameworks! from pod install. Easy to resolve so far.
  2. Building gives The “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift. This setting can be set in the build settings editor. error.
    Seems like swift pod developers need to specify
    s.pod_target_xcconfig = { 'SWIFT_VERSION' => <a version above 2.3 for it to work with Xcode 9> }
    in their podspec. Added temporary hack in Podfile with
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '3.2'
    end
  end
end

and re-pod install
3.

#import "Headers/flutter_iap-umbrella.h"
            ^
   .../ios/Pods/Target Support Files/flutter_iap/flutter_iap-umbrella.h:13:9: error: include of non-modular header inside framework module 'flutter_iap': '.../.pub-cache/hosted/pub.dartlang.org/flutter_iap-1.0.1/ios/Classes/FlutterIapPlugin.h'

Add

pre_install do |installer|
  # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
  Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
end

and

post_install do |installer|
  installer.pods_project.targets.each do |target|
    # workaround for https://github.com/CocoaPods/CocoaPods/issues/7463
    target.headers_build_phase.files.each do |file|
      file.settings = { 'ATTRIBUTES' => ['Public'] }
    end
  end
end

to make it work.

Wonder if we can add some automatic handling of swift plugins in the default objective-c project's Podfile

@xster xster added the p: tooling label Mar 29, 2018

@xster

This comment has been minimized.

Contributor

xster commented Mar 29, 2018

@pinkfish

This comment has been minimized.

pinkfish commented Apr 19, 2018

I tried these work arounds and it is still failing to build with the same error. Do I need to make any specific changes to the podfile that is being included or something too? I just did these in my app podfiles...

:1:9: note: in file included from :1:
#import "Headers/flutter_places_dialog-umbrella.h"
^
/Users/ddb/git/mobile/flutter_fuse/ios/Pods/Target Support Files/flutter_places_dialog/flutter_places_dialog-umbrella.h:13:9: error: include of non-modular header inside framework module 'flutter_places_dialog': '/Users/ddb/git/flutter_places_dialog/ios/Classes/FlutterPlacesDialogPlugin.h'
#import "FlutterPlacesDialogPlugin.h"

@dlutton

This comment has been minimized.

dlutton commented Apr 19, 2018

@pinkfish
Are you using cocoapods 1.5.0?

If so, try downgrading to 1.4.0. That's the only way I've been able to get it to work.
sudo gem install cocoapods -v 1.4.0
delete your Podfile.lock and Podfile dir in /ios and do a pod install

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 19, 2018

@dlutton @pinkfish We have been unable to make Cocoapods 1.4.0 work all the way through to app store archives, and we'll be supporting only Cocoapods 1.5.0 or later going forward.

With Cocoapods 1.5.0 and newest Flutter tooling (on master), all you should have to do is patch your Podfile as follows:

target 'Runner' do
  use_frameworks! # <--- add this
  ...
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
      config.build_settings['SWIFT_VERSION'] = '3.2' # <--- add this
    end
  end
end

Then delete ios/Podfile.lock and execute flutter run.

Filing issue that changing ios/Podfile does not cause flutter run to redo pod install #16734

@dlutton

This comment has been minimized.

dlutton commented Apr 19, 2018

@mravn-google Tried cocoapods 1.5.0 and it's failing with:

Xcode's output:
↳
    === BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Debug ===
    ld: warning: Auto-Linking library not found for -lswiftSwiftOnoneSupport
    ld: warning: Auto-Linking library not found for -lswiftCoreAudio
    ld: warning: Auto-Linking library not found for -lswiftCore
    ld: warning: Auto-Linking library not found for -lswiftQuartzCore
    ld: warning: Auto-Linking library not found for -lswiftCoreImage
    ld: warning: Auto-Linking library not found for -lswiftCoreGraphics
    ld: warning: Auto-Linking library not found for -lswiftAVFoundation
    ld: warning: Auto-Linking library not found for -lswiftCoreMedia
    ld: warning: Auto-Linking library not found for -lswiftDispatch
    ld: warning: Auto-Linking library not found for -lswiftObjectiveC
    ld: warning: Auto-Linking library not found for -lswiftCoreFoundation
    ld: warning: Auto-Linking library not found for -lswiftUIKit
    ld: warning: Auto-Linking library not found for -lswiftDarwin
    ld: warning: Auto-Linking library not found for -lswiftMetal
    ld: warning: Auto-Linking library not found for -lswiftsimd
    ld: warning: Auto-Linking library not found for -lswiftFoundation
    Undefined symbols for architecture x86_64:
[✓] Flutter (Channel master, v0.3.1-pre.35, on Mac OS X 10.13.3 17D102, locale en-US)
    • Flutter version 0.3.1-pre.35 at /Users/dlutton/development/flutter
    • Framework revision 7b163c7c0b (4 hours ago), 2018-04-18 20:31:45 -0700
    • Engine revision 3cc8d82895
    • Dart version 2.0.0-dev.48.0.flutter-fe606f890b

[✓] iOS toolchain - develop for iOS devices (Xcode 9.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 9.3, Build version 9E145
    • ios-deploy 1.9.2
    • CocoaPods version 1.5.0
@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 19, 2018

@dlutton Would you be able to share your pubspec.yaml and ios/Podfile?

@dlutton

This comment has been minimized.

dlutton commented Apr 19, 2018

@mravn-google
Maybe it's my flutter_tts plugin I wrote in swift that's failing. It worked with cocoapods 1.4.

Podfile:

# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

def parse_KV_file(file, separator='=')
  file_abs_path = File.expand_path(file)
  if !File.exists? file_abs_path
    return [];
  end
  pods_ary = []
  skip_line_start_symbols = ["#", "/"]
  File.foreach(file_abs_path) { |line|
      next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
      plugin = line.split(pattern=separator)
      if plugin.length == 2
        podname = plugin[0].strip()
        path = plugin[1].strip()
        podpath = File.expand_path("#{path}", file_abs_path)
        pods_ary.push({:name => podname, :path => podpath});
      else
        puts "Invalid plugin specification: #{line}"
      end
  }
  return pods_ary
end

target 'Runner' do
  use_frameworks!

  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
  # referring to absolute paths on developers' machines.
  system('rm -rf Pods/.symlinks')
  system('mkdir -p Pods/.symlinks/plugins')

  # Flutter Pods
  generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
  if generated_xcode_build_settings.empty?
    puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
  end
  generated_xcode_build_settings.map { |p|
    if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
      symlink = File.join('Pods', '.symlinks', 'flutter')
      File.symlink(File.dirname(p[:path]), symlink)
      pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
    end
  }

  # Plugin Pods
  plugin_pods = parse_KV_file('../.flutter-plugins')
  plugin_pods.map { |p|
    symlink = File.join('Pods', '.symlinks', 'plugins', p[:name])
    File.symlink(p[:path], symlink)
    pod p[:name], :path => File.join(symlink, 'ios')
  }
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
      config.build_settings['SWIFT_VERSION'] = '3.2'
    end
  end
end

pubspec.yaml

name: fof
description: A new Flutter project.

dependencies:
  flutter:
    sdk: flutter
  connectivity:
  flutter_tts:
  share: "^0.3.1"

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter


# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  assets:
    - assets/failure.webp
    - assets/fortune.webp
    - assets/LaunchImage.png

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.io/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.io/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  fonts:
    - family: Lato
      fonts:
        - asset: fonts/Lato-Regular.ttf
          weight: 400
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies, 
  # see https://flutter.io/custom-fonts/#from-packages

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 19, 2018

The flutter_tts plugin works fine when included in a Flutter project created using -i swift.

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 19, 2018

Adding an empty Swift file to your Flutter iOS project in Xcode and accepting to add bridging header also works.

@dlutton

This comment has been minimized.

dlutton commented Apr 19, 2018

Okay I’ll try that out thank you

@dlutton

This comment has been minimized.

dlutton commented Apr 19, 2018

@mravn-google I confirmed it's working with cocoapods 1.5.0. Thank you sir

@goodis0

This comment has been minimized.

goodis0 commented Jul 12, 2018

@mravn-google can you explain how to

Adding an empty Swift file to your Flutter iOS project in Xcode and accepting to add bridging header also works.

Where am I creating this file and what is a bridging header?

@lukepighetti

This comment has been minimized.

lukepighetti commented Jul 25, 2018

@goodis0 Did you find an answer to this? Trying to add a pub package to a project I created with Flutter: New Project in Visual Studio Code and it's failing due to SWIFT_VERSION error being discussed.

@lukepighetti

This comment has been minimized.

lukepighetti commented Jul 25, 2018

Can confirm that @mravn-google provided a simple and effective fix #16049 (comment)

@efortuna

This comment has been minimized.

efortuna commented Sep 13, 2018

One of our customers tried @mravn-google's and @xster's workarounds and is still seeing errors:

/Users/xiao/projects/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-2.0.0/ios/Classes/strategies/AudioVideoPermissionStrategy.swift:14:80: error: type 'AVMediaType' (aka 'NSString') has no member 'video'
                return AudioVideoPermissionStrategy.getPermissionStatus(mediaType: AVMediaType.video)
                                                                                   ^~~~~~~~~~~ ~~~~~
    /Users/xiao/projects/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-2.0.0/ios/Classes/strategies/AudioVideoPermissionStrategy.swift:16:80: error: type 'AVMediaType' (aka 'NSString') has no member 'audio'
                return AudioVideoPermissionStrategy.getPermissionStatus(mediaType: AVMediaType.audio)

Any other suggestions for workarounds?
cc @hukid

@timsneath

This comment has been minimized.

Member

timsneath commented Sep 17, 2018

I also hit the same issue @efortuna mentioned after applying @mravn-google's workaround, but fixed it by choosing a later Swift version in the Podfile:

      config.build_settings['SWIFT_VERSION'] = '4.0' # <--- instead of 3.2

This enabled me to successfully add the geolocator package to an Objective-C project. Can you try this, @hukid?

@gunhansancar

This comment has been minimized.

gunhansancar commented Oct 14, 2018

@timsneath I've tried with config.build_settings['SWIFT_VERSION'] = '4.0' and it is still not working because I had to disable # use_frameworks!. It was needed to be disabled for firebase messaging library. It is a known issue #9694.

Btw to describe what is not working, I try to use a plugin written in swift, https://pub.dartlang.org/packages/permission_handler but when I include it to my pubspec file, it cannot run on ios because it couldn't find the header files.

Error launching application on iPhone.
    ** BUILD FAILED **
    
Xcode's output:
↳
    /Users/gunhansancar/development/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-2.1.0/ios/Classes/PermissionHandlerPlugin.m:2:9: fatal error: 'permission_handler/permission_handler-Swift.h' file not found
    #import <permission_handler/permission_handler-Swift.h>
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 error generated.
    /Users/gunhansancar/development/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-2.1.0/ios/Classes/PermissionHandlerPlugin.m:2:9: fatal error: 'permission_handler/permission_handler-Swift.h' file not found
    #import <permission_handler/permission_handler-Swift.h>
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 error generated.
@sjmcdowall

This comment has been minimized.

Contributor

sjmcdowall commented Nov 2, 2018

Any updates on this? I am having the same issues with including both a Swift plugin (get_version) and the Google Maps map_view plugin. I can get one of the other to work but not both ... Rather frustrating... On iOS of course.. seems fine on Android..

@gkd720

This comment has been minimized.

gkd720 commented Nov 2, 2018

I was also trying to get the 'geolocator' package to work in an Flutter iOS app. I did the @timsneath Podfile tweak above, but I figured why not go to the latest, 4.2? Well, that doesn't work, since some UIKit type is deprecated at 4.2, so I went back to 4.0, and everything works great. But does this mean use of this package will break as we use later Swift versions? I'm at Xcode 10.1, Build version 10B61, ios-deploy 1.9.2, CocoaPods version 1.5.3. Thanks @timsneath for the tweak.

@hyz1992

This comment has been minimized.

hyz1992 commented Nov 14, 2018

@dlutton @pinkfish We have been unable to make Cocoapods 1.4.0 work all the way through to app store archives, and we'll be supporting only Cocoapods 1.5.0 or later going forward.

With Cocoapods 1.5.0 and newest Flutter tooling (on master), all you should have to do is patch your Podfile as follows:

target 'Runner' do
  use_frameworks! # <--- add this
  ...
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
      config.build_settings['SWIFT_VERSION'] = '3.2' # <--- add this
    end
  end
end

Then delete ios/Podfile.lock and execute flutter run.

Filing issue that changing ios/Podfile does not cause flutter run to redo pod install #16734

This way is very effective,but it caused another problem in my project.
I have a local plugin and it import a local .framefork file,this is my plugin's podspec:
`
Pod::Spec.new do |s|

s.name             = 'tx_ugc'
s.version          = '0.0.1'
s.summary          = 'A new Flutter plugin.'
s.description      = <<-DESC
A new Flutter plugin.
DESC
s.homepage         = 'http://example.com'
s.license          = { :file => '../LICENSE' }
s.author           = { 'Your Company' => 'email@example.com' }
s.source           = { :path => '.' }
s.source_files = 'Classes/**/*.h','Classes/**/*.m','Third/AFNetworking/**/*','Third/MBProgressHUD/**/*','Third/Masonry/**/*'
s.public_header_files = 'Classes/**/*.h'#,'TXLiteAVSDK_UGC.framework/Headers/*.h'
s.resources = ['Classes/demo/Record/VideoRecordConfigViewController.xib','Classes/demo/Record/VideoRecord.xcassets','Classes/demo/Common/Resource/**/*','Assets/Assets.xcassets']
s.dependency 'Flutter'

s.frameworks    = "Accelerate", "SystemConfiguration"
s.libraries     = "sqlite3", "c++"

s.vendored_frameworks = "TXLiteAVSDK_UGC.framework"
s.ios.deployment_target = '8.0'

s.default_subspec = "precompiled"

s.subspec "precompiled" do |ss|
    ss.preserve_paths         = "TXLiteAVSDK_UGC.framework/Headers/*.h"
    ss.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/Headers/Public/#{s.name}" }
end

end
`

My problem is, if I add "use_frameworks!" in my main project's Profile,I can't refer to the header file in TXLiteAVSDK_UGC.framework in a .h file,such as "import 'TXLiteAVSDK_UGC/TXVodplayer.h' ",but in .m file it works normally;

hao can I solve this problem?
can you help me?
thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment