Flutter开发 - 开发flutter的plugin时,怎么把第三方的framework引入到工程中

1,845 阅读3分钟

在iOS中,我肯定不会写这篇博客。如果我写了,读者会说:你这不是骗流量的么?我又不是小白。哼,取关!😂

打扰了,这里虽然是flutter工程,不过最终体现还是以pod的形式存在于Xcode原生工程中,博主看过一些类似的博文,有博主就是直接在pod中建文件夹把framework拖进去的。不过我们今天肯定不会讲这种方式,第一:太打脸,第二:太没水平,都做flutter了,还按照原生的方式来做,不太好。况且这么做是不安全的,你总不能删了pod之后,每次都要重新做一遍导入的过程吧?

这里博主给大家提供一种便捷的方式,为了方便大家理解,博主这里将新建一个工程来给大家演示:
1.新建工程+plugin(不用演示了吧,小伙伴们)

这是建好的工程目录:
在这里插入图片描述

2.在plugin下引入framework
1)打开flugin吓的iOS目录
在这里插入图片描述
2)在这个目录下建一个新的文件,名为framework
在这里插入图片描述
3)把你的framework拖进来
博主这里叫demo.framework
在这里插入图片描述
3.修改podspec文件

#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint flutter_plugin.podspec' to validate before publishing.
#
Pod::Spec.new do |s|
  s.name             = 'flutter_plugin'
  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/**/*'
  s.public_header_files = 'Classes/**/*.h'
  s.dependency 'Flutter'
  s.platform = :ios, '8.0'

  s.vendored_frameworks = 'framework/*.framework'
  s.resource = 'framework/*.*'
  s.libraries = 'stdc++'
  s.resources = 'Assets/*.*'

  s.pod_target_xcconfig = {
    'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64',
    'CLANG_CXX_LANGUAGE_STANDARD' => 'compiler-default',
    'CLANG_CXX_LIBRARY' => 'libc++',
    'OTHER_LDFLAGS' => '$(inherited) -ObjC'
  }
end

4.要在yaml引入这个plugin,否则pod install是拉不到这个plugin的
在这里插入图片描述
注意路径不要写错了

5.podfile需要自己创建下,给大家提供一个模版

source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
# 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'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def parse_KV_file(file, separator='=')
  file_abs_path = File.expand_path(file)
  if !File.exists? file_abs_path
    return [];
  end
  generated_key_values = {}
  skip_line_start_symbols = ["#", "/"]
  File.foreach(file_abs_path) do |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)
      generated_key_values[podname] = podpath
    else
      puts "Invalid plugin specification: #{line}"
    end
  end
  generated_key_values
end

target 'Runner' do
  # Flutter Pod
  use_frameworks!

  copied_flutter_dir = File.join(__dir__, 'Flutter')
  copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
  copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
  unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
    # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
    # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
    # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.

    generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
    unless File.exist?(generated_xcode_build_settings_path)
      raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
    end
    generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
    cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];

    unless File.exist?(copied_framework_path)
      FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
    end
    unless File.exist?(copied_podspec_path)
      FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
    end
  end

  # Keep pod path relative so it can be checked into Podfile.lock.
  pod 'Flutter', :path => 'Flutter'

  # Plugin Pods

  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
  # referring to absolute paths on developers' machines.
  system('rm -rf .symlinks')
  system('mkdir -p .symlinks/plugins')
  plugin_pods = parse_KV_file('../.flutter-plugins')
  plugin_pods.each do |name, path|
    symlink = File.join('.symlinks', 'plugins', name)
    File.symlink(path, symlink)
    pod name, :path => File.join(symlink, 'ios')
  end
end

# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 9.0
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
      end
    end
  end
end

这个模版比较全面,博主项目中的模版和这个就基本差不多,关键是可以区分环境,debug,release这些。

6.这些都做完了,那么就运行下pod install吧
在这里插入图片描述
可以看到我们自己的plugin已经被pod装载了

7.打开Xcode看下,你会发现pod中已经存在framework了
在这里插入图片描述

8.framework引入完了,这时候我们可能会在plugin中创建一些新的iOS的类,这个时候为了方便调试,我们可以直接在Xcode里面操作了
在这里插入图片描述
建的文件或者文件夹要放在Classes文件目录下,这样你会发现你建的文件都会出现在flutter中的Classes下

9.建个新的文件夹和文件看下
在这里插入图片描述
接下来看下flutter工程中的Classes下
在这里插入图片描述
神奇的发现竟然是同步的,开不开心。

10.到这里,你就学会了如何去自建一个新的plugin,同时你也学会了如何建一个需要依赖第三方framework的plugin,写作不易,给个👍吧!