-
2018-05-23 14:58:04
1. 删除 configuration/org.eclipse.update 目录
2. cmd 运行 eclipse -clean
还不行.
找到configuration/config.ini
修改值为true
org.eclipse.update.reconcile=true
更多相关内容 -
CAD智能影像加载插件.rar
2021-08-23 21:00:05用于CAD、CASS的影像加载插件 -
jquery.reload:jQuery插件,用于通过AJAX重新加载组件的内容
2021-05-25 17:34:20jQuery重新加载 jQuery插件,用于通过AJAX重新加载/同步组件的内容 捷径 依存关系 执照 请在阅读 -
CAD智能影像加载插件.zip
2019-08-06 13:06:25找了很久才找到的。 经测试测试CAD2011及2012均可以使用。使用方法在压缩包内 觉得好用可以给个五星好评(*^▽^*) -
jQuery懒加载插件页面滚动加载数据代码
2019-10-30 22:13:16jQuery懒加载插件页面滚动加载数据代码 jQuery懒加载插件页面滚动加载数据代码 -
Arcgis地图底图加载插件
2019-03-27 22:12:36SimpleGISforArcMapV2.7.1用于arcmap加载天地图、谷歌地图、高德地图、BingMap作为底图,安装之后,在工具栏上右键勾选simple gis即可显示底图加载工具栏 -
Xcode升级导致插件无法使用和点击skip bundle后怎么重新加载插件
2016-03-23 23:03:16Xcode升级导致插件无法使用和点击skip bundle后怎么重新加载插件Xcode升级导致插件无法使用
先关闭Xcode,然后打开终端输入如下代码,最后重新打开Xcode,点击load bundle按钮,记住不要点击skip bundle
find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth 3 | xargs -I{} defaults write {} DVTPlugInCompatibilityUUIDs -array-add `defaults read /Applications/Xcode.app/Contents/Info.plist DVTPlugInCompatibilityUUID
错误点击skip bundle后怎么重新加载插件
首先右键点击finder—>前往文件夹,输入如下地址进入到插件所在地方:
~/Library/Application Support/Developer/Shared/Xcode/Plug-ins
然后进入右键点击插件—>显示包内容—>Contents—>Info.plist,然后会看到如下图所示的界面,删除最后一个UUIDS,最后一个一般是最新Xcode的UUIDS,删除后然后再重启Xcode,记住这次一定要点击load bundle
PS:谢谢大家的观看,以上两个办法亲测可用 -
cass自动加载影像插件
2018-12-06 08:46:28cass自动加载影像插件 -
易语言源码易语言插件加载设计源码.rar
2020-02-19 21:39:52易语言源码易语言插件加载设计源码.rar 易语言源码易语言插件加载设计源码.rar 易语言源码易语言插件加载设计源码.rar 易语言源码易语言插件加载设计源码.rar 易语言源码易语言插件加载设计源码.rar 易语言源码... -
ArcGIS 加载中国地图插件.zip
2019-07-28 23:36:58ArcGIS 加载中国地图插件 ArcGIS 加载中国地图插件 ArcGIS 加载中国地图插件 -
Unity动态加载FBX模型插件UniFBX (2) v2.3.1
2019-03-26 11:55:04Unity动态加载FBX模型插件UniFBX (2) v2.3.1 需要的朋友可进行下载,有问题请联系 -
正射影像tif、jpg等文件导入CAD(智能影像加载插件)
2018-11-03 22:55:462.找到C:\Program Files (x86)\RiverMap\水经注万能地图下载器 X3\tools\cadaimg\水经注CAD智能影像加载插件.VLX 3.cad中输入APPload加载这个插件, 4.输入aimg,选择图片既可 5.成功了么,成功了把水经注卸载了,OK -
ArcMap10.2加载天地图、高德地图等在线地图所需插件
2020-11-24 20:02:36使用此插件可以在arcmap10.2中加载在线地图,先运行setup文件,在运行addin(双击即可)然后以管理员身份运行arcmap即可,若出现许可错误,重新获取许可即可 -
cad加载影像图插件
2014-12-12 10:12:50加载含有坐标信息的影像图,不需要另外校正 -
水经注影像加载插件 2.1正式版
2016-03-02 18:05:06arcmap是一款由水经注信息科技官方最新推出针对基于ArcMap加载离线或在线谷歌地图、腾讯SOSO地图、必应地图和雅虎地图的插件的地图加载工具,帮助用户解决ArcMap无法加载超大容量离线影像数据或加载困难的问题。 -
jquery点击加载更多内容插件.rar
2020-02-01 21:10:42此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容此插件为点击加载更多内容 -
iOS之深入解析CocoaPods的插件机制和如何加载插件整合开发工具
2022-04-08 13:24:59一、CocoaPods 插件机制 ① Ruby 在 Ruby 中,类永远是开放的,总是可以将新的方法加入到已有的类中,除了自己的代码中,还可以用在标准库和内置类中,这个特性被称为 Ruby Open Classes。 自定义一个类 Human,...一、CocoaPods 插件机制
① Ruby
- 在 Ruby 中,类永远是开放的,总是可以将新的方法加入到已有的类中,除了自己的代码中,还可以用在标准库和内置类中,这个特性被称为 Ruby Open Classes。
- 自定义一个类 Human,放在 human.rb 文件中:
class Human def greeting puts "hello everybody" end def hungry puts "I am hungry" end end
- 新增一个main.rb:
require_relative 'human' john = Human.new john.greeting # hello everybody john.hungry # I am hungry
- 再在 main.rb 中重新定义 hungry 方法:
class Human def hungry puts "I could eat a horse" end end john.hungry # I could eat a horse
- 可以看到,在新增 hungry 方法之后,所有的 Human 类的实例均调用新的实现,即使是已经创建好的实例,这里故意放到两个文件中是想说明这个特性是可以跨文件甚至跨模块的,对 Ruby 内置方法的替换也是可以的(谨慎使用)。
puts "hello".size class String def size puts "goodbye" end end # 5 # goodbye puts "hello".size
- 这个特性是十分强大的,让我们可以很容易的对三方模块进行扩展,也是 Cocoapods 的插件体系所依赖的基础。
② CocoaPods 流程分析
- 首先,Cocoapods 提供了一个便捷的命令行工具库 CLAide,CLAide 包含很多功能,例如,一套命令基类,一套插件加载机制等。
- Command 基类在 lib/claide/command.rb 中,提供了大量基础功能,包括 run 、 options、 help 等。当每次执行 pod xxx 命令时候,会执行 bin 目录下的可执行文件 pod:
require 'cocoapods' if profile_filename = ENV['PROFILE'] # 忽略不相关内容... else Pod::Command.run(ARGV) end
- 这里实际上是 Pod 模块从 CLAide 继承子类 Command < CLAide::Command,执行 Pod 命令时候,就会调用:
def self.run(argv) help! 'You cannot run CocoaPods as root.' if Process.uid == 0 verify_minimum_git_version! verify_xcode_license_approved! super(argv) ensure UI.print_warnings end
- 实际上只是扩展了一些检测 git 版本、Xcode 证书等,真正核心部分还是调用的 CLAide 的实现:
def self.run(argv = []) plugin_prefixes.each do |plugin_prefix| PluginManager.load_plugins(plugin_prefix) end argv = ARGV.coerce(argv) command = parse(argv) ANSI.disabled = !command.ansi_output? unless command.handle_root_options(argv) command.validate! command.run end rescue Object => exception handle_exception(command, exception) end
- 可以看到这里真正执行命令之前会遍历所有的插件前缀,并进行插件加载,回头来再查看 cocoapods/command.rb 会发现,这里指定了约定的插件前缀:
self.plugin_prefixes = %w(claide cocoapods)
- 可以看到这里的插件分为两种,我们目前只关心文件名为 CocoaPods 前缀的插件。深入 PluginManager 的具体实现看下:
def self.load_plugins(plugin_prefix) loaded_plugins[plugin_prefix] ||= plugin_gems_for_prefix(plugin_prefix).map do |spec, paths| spec if safe_activate_and_require(spec, paths) end.compact end def self.plugin_gems_for_prefix(prefix) glob = "#{prefix}_plugin#{Gem.suffix_pattern}" Gem::Specification.latest_specs(true).map do |spec| matches = spec.matches_for_glob(glob) [spec, matches] unless matches.empty? end.compact end def self.safe_activate_and_require(spec, paths) spec.activate paths.each { |path| require(path) } true # 不相关代码略去 # ... end
- 只分析核心相关代码,整体的流程大致是:
-
- 调用 PluginManager.load_plugins 并传入插件前缀;
-
- PluginManager.plugin_gems_for_prefix 对插件名进行处理,取出需要加载的文件,例如 CocoaPods 前缀在这里会转换为所有包含 cocoapods_plugin.rb 的 gem spec 信息及文件信息,例如 ~/cocoapods-qt/lib/cocoapods_plugin.rb;
-
- 调用 PluginManager.safe_activate_and_require 进行对应的 gem spec 检验并对每个文件进行加载。
③ Cocoapods-plugins
- 执行 pod plugins create cocoapods-test 之后,发现自动创建了一个 gem 工程,其中的 lib 文件夹下果然存在一个 cocoapods_plugin.rb 文件,整体的目录结构如下:
├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── cocoapods-test.gemspec ├── lib │ ├── cocoapods-test │ │ ├── command │ │ │ └── test.rb │ │ ├── command.rb │ │ └── gem_version.rb │ ├── cocoapods-test.rb │ └── **cocoapods_plugin.rb** └── spec ├── command │ └── test_spec.rb └── spec_helper.rb
- 这里最核心的就是 cocoapods_plugin.rb,前面分析过,执行 pod 命令时候会主动加载所有 cocoapods_plugin.rb 文件,那么只要将需要扩展的类加到这里面,执行命令时候就会生效:
class Test < Command self.summary = 'Short description of cocoapods-test.' self.description = <<-DESC Longer description of cocoapods-test. DESC self.arguments = 'NAME' def initialize(argv) @name = argv.shift_argument super end def validate! super help! 'A Pod name is required.' unless @name end def run UI.puts "Add your implementation for the cocoapods-test plugin in #{__FILE__}" end end
- 可以看到只是新增了一个 Test 命令,并加了一些描述信息。为了扩展能生效,可以通过几种方式:
-
- 本地 gem 源码依赖;
-
- 安装 gem 产物。
- 为了更贴近实际生产发布流程,可以采用第二种方式:
-
- 首先,编译生成 gem 产物:
gem build cocoapods-test.gemspec
-
- 其次,本地安装:
gem install ~/CocoapodsQt/cocoapods-test/cocoapods-test-0.0.1.gem --local
-
- 再执行 pod 命令:
- 可以看到扩展的命令已经生效,接下来就可以开始愉快的 coding。
二、CocoaPods 如何加载插件?
- CocoaPods 为开发者提供了插件注册功能,可以使用 pod plugins create NAME 命令创建插件,并在 Podfile 中通过 plugin ‘NAME’ 语句引入插件。虽然在一般情况下很少使用这个功能,但在某些场景下,利用插件能比较方便快捷地解决问题,比如清除 input,output 文件、创建 Podfile DSL 等。
- 首先,由于 pod install 过程会涉及到插件的加载,因此直接查看 installer.rb 文件:
# Runs the registered callbacks for the plugins post install hooks. # def run_plugins_post_install_hooks context = PostInstallHooksContext.generate(sandbox, aggregate_targets) HooksManager.run(:post_install, context, plugins) end # Runs the registered callbacks for the plugins pre install hooks. # # @return [void] # def run_plugins_pre_install_hooks context = PreInstallHooksContext.generate(sandbox, podfile, lockfile) HooksManager.run(:pre_install, context, plugins) end # Ensures that all plugins specified in the {#podfile} are loaded. # # @return [void] # def ensure_plugins_are_installed! require 'claide/command/plugin_manager' loaded_plugins = Command::PluginManager.specifications.map(&:name) podfile.plugins.keys.each do |plugin| unless loaded_plugins.include? plugin raise Informative, "Your Podfile requires that the plugin `#{plugin}` be installed. Please install it and try installation again." end end end
- 其中 run_plugins_pre_install_hooks 和 run_plugins_post_install_hooks 分别执行插件注册的 pre_install 和 pod_install 方法, ensure_plugins_are_installed 则确认插件是否已被安装。
- 接下来看下 Command::PluginManager,这个类在 claide/command/plugin_manager 文件内,属于 claide gem:
# @return [Array<Gem::Specification>] Loads plugins via RubyGems looking # for files named after the `PLUGIN_PREFIX_plugin` and returns the # specifications of the gems loaded successfully. # Plugins are required safely. # def self.load_plugins(plugin_prefix) loaded_plugins[plugin_prefix] ||= plugin_gems_for_prefix(plugin_prefix).map do |spec, paths| spec if safe_activate_and_require(spec, paths) end.compact end # @group Helper Methods # @return [Array<[Gem::Specification, Array<String>]>] # Returns an array of tuples containing the specifications and # plugin files to require for a given plugin prefix. # def self.plugin_gems_for_prefix(prefix) glob = "#{prefix}_plugin#{Gem.suffix_pattern}" Gem::Specification.latest_specs(true).map do |spec| matches = spec.matches_for_glob(glob) [spec, matches] unless matches.empty? end.compact end # Activates the given spec and requires the given paths. # If any exception occurs it is caught and an # informative message is printed. # # @param [Gem::Specification] spec # The spec to be activated. # # @param [String] paths # The paths to require. # # @return [Bool] Whether activation and requiring succeeded. # def self.safe_activate_and_require(spec, paths) spec.activate paths.each { |path| require(path) } true rescue Exception => exception # rubocop:disable RescueException message = "\n---------------------------------------------" message << "\nError loading the plugin `#{spec.full_name}`.\n" message << "\n#{exception.class} - #{exception.message}" message << "\n#{exception.backtrace.join("\n")}" message << "\n---------------------------------------------\n" warn message.ansi.yellow false end
- 以上代码调用几个的 Gem::Specification 方法如下:
# 获取最新 spec 集合 # Return the latest specs, optionally including prerelease specs if prerelease is true. latest_specs(prerelease = false) # 获取 gem 中匹配的文件路径 # Return all files in this gem that match for glob. matches_for_glob(glob) # 激活 spec,注册并将其 lib 路径添加到 $LOAD_PATH ($LOAD_PATH 环境变量存储 require 文件时查找的路径) # Activate this spec, registering it as a loaded spec and adding it's lib paths to $LOAD_PATH. Returns true if the spec was activated, false if it was previously activated. Freaks out if there are conflicts upon activation. activate()
- 可以看到在 loaded_plugins[plugin_prefix] 为空的情况下,程序会执行 plugin_gems_for_prefix 方法,plugin_gems_for_prefix 方法通过 latest_specs 获取了最新的 spec,并通过 spec 的 matches_for_glob 方法对文件进行匹配,当 spec 中存在匹配 “#{prefix}_plugin#{Gem.suffix_pattern}” 格式的文件时,则视其为 CocoaPods 插件。在拿到插件及其匹配文件后,safe_activate_and_require 方法将文件加入 $LOAD_PATH 中并 require 之。
- 另外 CLAide::Command 类会在 run 类方法中加载所有插件,然后根据解析后的信息,执行对应的命令:
# @param [Array, ARGV] argv # A list of (remaining) parameters. # # @return [Command] An instance of the command class that was matched by # going through the arguments in the parameters and drilling down # command classes. # def self.run(argv = []) plugin_prefixes.each do |plugin_prefix| PluginManager.load_plugins(plugin_prefix) end argv = ARGV.coerce(argv) command = parse(argv) ANSI.disabled = !command.ansi_output? unless command.handle_root_options(argv) command.validate! command.run end rescue Object => exception handle_exception(command, exception) end
- 对于通过 pod plugin create 命令创建的插件来说,lib 目录下都会自动生成一个 cocoapods_plugin.rb 文件,这个文件就是用来标识此 gem 为 CocoaPods 插件的。
- 如果想手动创建 CocoaPods 插件,需要满足以下两个条件:
# Handles plugin related logic logic for the `Command` class. # # Plugins are loaded the first time a command run and are identified by the # prefix specified in the command class. Plugins must adopt the following # conventions: # # - Support being loaded by a file located under the # `lib/#{plugin_prefix}_plugin` relative path. # - Be stored in a folder named after the plugin. # - 支持通过 `lib/#{plugin_prefix}_plugin` 路径的文件加载 # (也就是说,如果要对外暴露插件内部存的方法,需要在此文件中 require 之,比如自定义的 Podfile DSL 文件) # - 保存在以插件命名的文件夹中
- 在 CocoaPods 上下文中,以上的 plugin_prefix 如下:
self.plugin_prefixes = %w(claide cocoapods)
- 如果需要外部 gem 以插件的形式提供某些功能,可以通过和 CocoaPods 一样的方式实现,即规定特定的命名规则,然后通过 Gem::Specification 提供的方法获取满足条件的 gem,再 require 入口文件:
spec = Gem::Specification.find_by_name('naruto') spec.activate matches = spec.matches_for_glob('naruto') matches.each do |path| require(path) end
三、CocoaPods 插件整合开发工具
① Podfile 内声明公有源和私有源 source
- 如果组件化采用公有源和私有源双源的方案,为了 pod install 命令能够找到公有组件和私有组件,需要在 Podfile 里指定双源地址,如:
# 私有源地址 source 'https://xyz.com/ios/pod-specs.git' # 公有源地址 source 'https://github.com/CocoaPods/Specs.git'
- 但存在以下问题:
-
- 如果公司项目存在多个 APP,每个工程都要配置这样两行,各组件 Example 工程也存在这样的问题;
-
- 如果公司 git 换过地址,每次都要更换各个工程里的地址,且导致历史 tag 工程 pod install 失败;
-
- 新电脑需要手动添加私有源才能工作。
- 这次新建 cocoapods-lebby 插件工程,就通过 CocoaPods 提供的 source_provider hook 时机添加 source 来统一管理源地址,源不存在时可自动添加,注册插件如下:
Pod::HooksManager.register('cocoapods-lebbay', :source_provider) do |context| sources_manager = Pod::Config.instance.sources_manager context.add_source(sources_manager.private_source) context.add_source(sources_manager.public_source) end
- 闭包参数 context 对象提供了 add_source 方法用于添加 source 对象,这里借鉴 CocoaPods 源码做法,给 Pod::Source::Manager 扩展了两个方法分别提供私有源和公有源:
module Pod class Source class Manager # 私有源 source def private_source url = 'https://xyz.com/ios/pod-specs.git' source = source_with_url(url) return source if source Command::Repo::Add.parse(['lebbay-spec', url, 'master']).run source_with_url(url) end # 公有源 source def public_source url = 'https://github.com/CocoaPods/Specs.git' source = source_with_url(url) return source if source Command::Repo::Add.parse(['master', url, 'master']).run source_with_url(url) end end end end
② Podfile 内提供 dev_pods 自定义方法用于提测过程中实时拉取组件分支最新 commit
- 在组件开发过程中经常会修改几个 pod 的代码,需要一个个的将 pod 指向本地开发目录,在项目测试过程中又要将 pod 一个个指向提测分支,比如:
# 开发阶段 pod 'PodA', :path => '../PodA' pod 'PodB', :path => '../PodB' # 测试阶段 pod 'PodA', :git => 'https://xyz.com/ios/PodA.git', :branch => 'release/1.0.0' pod 'PodB', :git => 'https://xyz.com/ios/PodB.git', :branch => 'release/1.0.0'
- 为了简化写法,我们提供了 dev_pods 方法,简化逻辑后思路大致如下:
def dev_pods(pods, branch = '') if branch.length > 0 # 测试阶段 pods.each do |name| pod name, :git => "https://xyz.com/ios/#{name}.git", :branch => "#{branch}" end else # 开发阶段 development_path = File.read('./bin/.development_path').chomp pods.each do |name| pod name, :path => "#{development_path}#{name}" end end end
- 在 ./bin/.development_path 文件里配置本地开发目录,dev_pods 方法的用法如下:
# 开发阶段 dev_pods ['PodA', 'PodB'] # 测试阶段 dev_pods ['PodA', 'PodB'], 'release/1.0.0'
- 在测试阶段还有一个问题是,我们希望在组件的提测分支上修改了 bug、提交 commit 之后主工程 pod install 即可拉取最新代码。但因为 Podfile.lock 文件的存在,pod install 之后会把 commit 节点记下来,除非在提交 pod 改动后,再去更新主工程的 Podfile.lock 文件,否则是不会拉取最新代码的。为了实现这一需求,在 dev_pods 方法里修改了 Podfile.lock 文件,删掉 commit 节点信息,这样在拉取对应 pod 组件的时候就会拉取最新代码了。
- 在应用过程中发现的另一问题是:tag 冲突,当组件 PodA 指向的 release/1.0.0 分支里 podspec 里的版本号是 0.0.9,那么主工程的 Podfile.lock 文件里记录的就是 0.0.9。当测试完成,组件 podA 发版修改版本号为 1.0.0 并提交到了 release/1.0.0 分支里,这时主工程再执行 pod install 就会报 tag 冲突。为解决这一问题,避免提测组件版本号变更影响主工程提测打包,可以的做法是如果 PodA 通过 dev_pods 方法指向了分支,那么在 dev_pods 里删掉 PodA 在 Podfile.lock 里的记录(只删除 version、branch、commit 信息即可),这样在 pod install 的时候就会像下载一个新的 pod 一样。
- 问题、需求及解决思路大致如上,在以前的方案是写个 ruby 文件(lebbay.rb) 放在主工程目录,在 Podfile 里 require ‘./bin/lebbay.rb’,修改 Podfile.lock 文件也是脚本遍历文件内容操作字符串,现在统一整合到 cocoapods-lebbay 插件里,为 Podfile 扩充 DSL 方法,修改 Podfile.lock 文件可以直接使用 cocoapods-core 提供的 Lockfile 类及其方法:
module Pod class Podfile module DSL public def dev_pods(pods, branch = '') if branch.length > 0 pods.each do |name| pod name, :git => "https://xyz.com/ios/#{name}.git", :branch => "#{branch}" end pull_latest_code_and_resolve_conflict(pods) puts "lebbay: using remote pods with branch: #{branch}".green else # 自定义开发目录 development_path = Config.instance.dev_pods_path pods.each do |name| pod name, :path => "#{development_path}#{name}" end puts "lebbay: using local pods with path: #{development_path}xxx".green end end #--------------------------------------# private def pull_latest_code_and_resolve_conflict(pods) # 1、Podfile.lock rewrite_lock_file(pods, Config.instance.lockfile_path) # 2、Manifest.lock rewrite_lock_file(pods, Config.instance.sandbox.manifest_path) end def rewrite_lock_file(pods, lock_path) return unless lock_path.exist? lock_hash = Lockfile.from_file(lock_path).to_hash # 1、PODS lock_pods = lock_hash['PODS'] if lock_pods target_pods = [] lock_pods.each do |pod| if pod.is_a? Hash first_key = pod.keys[0] first_value = pod.values[0] if (first_key.is_a? String) && (first_value.is_a? Array) next if is_include_key_in_pods(first_key, pods) dep_pods = first_value.reject { |dep_pod| is_include_key_in_pods(dep_pod, pods) } target_pods << (dep_pods.count > 0 ? {first_key => dep_pods} : first_key) next end elsif pod.is_a? String next if is_include_key_in_pods(pod, pods) end target_pods << pod end lock_hash['PODS'] = target_pods end # 2、DEPENDENCIES locak_dependencies = lock_hash['DEPENDENCIES'] if locak_dependencies target_dependencies = [] locak_dependencies.each do |dependence| if dependence.is_a? String next if is_include_key_in_pods(dependence, pods) end target_dependencies << dependence end lock_hash['DEPENDENCIES'] = target_dependencies end Lockfile.new(lock_hash).write_to_disk(lock_path) end def is_include_key_in_pods(target_key, pods) pods.each do |pod| if target_key.include? pod return true end end return false end #--------------------------------------# end end end
- 我们同时修改了 Pods/ 文件夹下的 Manifest.lock 文件,是因为 CooaPods 在 pod install 过程中会对比 lock 文件里记录的 version 版本号,若 Manifest.lock 文件里记录的版本没变的话,在执行 pod install 时 Pods/ 文件夹里对应 Pod 的代码很可能是不会更新的。其中关于开发目录(development_path = Config.instance.dev_pods_path),给 Pod::Config 扩展了两个方法:设置开发目录 & 读取开发目录:
module Pod class Config # 读取目录 def dev_pods_path config_path_file = dev_pods_path_config_file dev_path = File.read(config_path_file).chomp end # 设置目录 def config_dev_pods_path(dev_path) raise Informative, "input can't be nil" unless dev_path.length > 0 dev_path += '/' unless dev_path[dev_path.length - 1] == '/' config_path_file = dev_pods_path_config_file File.open(config_path_file, "w") do |file| file.syswrite(dev_path) end end # 配置文件 def dev_pods_path_config_file config_path = File.expand_path('~/.cocoapods-lebbay') FileUtils.makedirs(config_path) unless File.exists?config_path config_path_file = config_path + '/dev_pods_path_config' unless File.exist?(config_path_file) File.open(config_path_file, "w") do |file| file.syswrite('../../') end end config_path_file end end end
- 给 pod 扩展了两个方法入口分别执行这俩方法,读取开发目录(pod dev-pods-path cat),设置开发目录(pod dev-pods-path set):
require 'cocoapods-lebbay/cache_config' module Pod class Command class DevPodsPath < Command self.abstract_command = true self.summary = 'set or cat dev_pods path' def self.options [] end end class Set < DevPodsPath self.summary = 'set dev_pods path' def run UI.puts "Please input dev_path for dev_pods command:".green answer = STDIN.gets.chomp.strip Config.instance.config_dev_pods_path(answer) end end class Cat < DevPodsPath self.summary = 'cat dev_pods path' def run UI.puts Config.instance.dev_pods_path.green end end end end
③ 解决 libwebp 网络问题:修改公有源里 podspec git 地址为 github 地址
- 这个问题因为 libwebp 的 podspec 里 git 地址是:https://chromium.googlesource.com/webm/libwebp,在 pod install 的时候大概率会因为网络原因而下载失败,将其改为:https://github.com/webmproject/libwebp.git 即可。
- 之前的做法是在 lebbay.rb 脚本里提供了 libwep_spec_fix 方法批量修改公有源里 libwebp.podspec 的 git 地址,然后在 Podfile 文件里调用下这个方法,现在也整合到了 cocoapods-lebbay 插件里,在 pre_install 的 hook 时机里执行:
Pod::HooksManager.register('cocoapods-lebbay', :pre_install) do |context| target_url = "https://chromium.googlesource.com/webm/libwebp" replace_url = "https://github.com/webmproject/libwebp.git" repo_path = File.expand_path('~/.cocoapods/repos/master/Specs/1/9/2/libwebp/*/*.json') Dir.glob(repo_path) do |json_file| json_text = File.read(json_file) json_text = json_text.gsub(target_url, replace_url) File.open(json_file, "w") do |file| file.syswrite(json_text) end end end
④ 解决 CocoaPods bug:一旦有任一组件在 podspec 里使用 resources 命令管理资源文件,CocoaPods 会把所有组件内的资源文件拷贝到 main bundle 里
- 关于这个问题的具体信息请查看:If there are one pod using xcassets via resources spec syntax, then all xcassets will be copied and compied twice during [CP] Copy Pods Resources build phase #8431,虽然目前没有 pod 在使用 resources 命令,但为了避免三方库会引入这个问题,还是需要左规避,在 post_install 的 hook 时机里修复 CocoaPods 的脚本,之前是将 post_install 的 hook 写在了 Podfile 里,现在放在了插件里来做:
Pod::HooksManager.register('cocoapods-lebbay', :post_install) do |context| target_label = context.umbrella_targets.first.cocoapods_target_label system %Q{sed -i "" "s/\\[\\[ \\$line != \\"\\${PODS_ROOT}\\*\\" \\]\\]/\\[\\[ \\$line != \\${PODS_ROOT}\\* \\]\\]/g" "./Pods/Target Support Files/#{target_label}/#{target_label}-resources.sh"} end # before #if [[ $line != "${PODS_ROOT}*" ]]; then # changed #if [[ $line != ${PODS_ROOT}* ]]; then
⑤ 使用
- 做完这些,各个工程里的 Podfile 文件就清爽了很多,之后再有需求的话也可以在 cocoapods-lebbay 插件里统一管理,可以很方便用户安装和命令维护,只需在 Podfile 里添加这样一行,即可全部实现:
plugin 'cocoapods-lebbay'
-
简单jQuery加载等待转圈页面插件
2016-11-08 17:48:25简单的jQuery加载等待转圈页面小插件 -
cad插件替代启动组-只需拖拽一次永久解决插件加载问题
2015-11-02 17:58:25cad插件替代启动组-只需拖拽一次永久解决插件加载问题 -
网页下拉刷新上拉加载插件(pull-to-refresh)完美修改版
2014-12-05 11:36:43iscroll插件的完全修改版,完美实现了上拉刷新,下拉加载等功能,附带实现分析数据,三个晚上的研究成果啊,最近缺分,求打赏啊 -
Qt创建插件加载插件以及插件与主程序之间通信
2019-04-09 10:37:271.Qt 创建插件 这几步就把一个插件创建好了,但是是个空的没有东西,我们加一个窗口类 form.h #ifndef FORM_H #define FORM_H #include <QWidget> namespace Ui { class Form; } class Form : public ...1.Qt 创建插件
这几步就把一个插件创建好了,但是是个空的没有东西,我们加一个窗口类
form.h
#ifndef FORM_H #define FORM_H #include <QWidget> namespace Ui { class Form; } class Form : public QWidget { Q_OBJECT public: explicit Form(QWidget *parent = 0); ~Form(); public slots: void setLabelColor_slot(QPalette p); signals: void labelColor_signal(QPalette p); private slots: void on_red_btn_clicked(); void on_green_btn_clicked(); private: Ui::Form *ui; }; #endif // FORM_H
form.cpp
#include "form.h" #include "ui_form.h" #include <QPalette> Form::Form(QWidget *parent) : QWidget(parent), ui(new Ui::Form) { ui->setupUi(this); } Form::~Form() { delete ui; } void Form::setLabelColor_slot(QPalette p) { ui->color_label->setPalette(p); } void Form::on_red_btn_clicked() { QPalette palette; palette.setColor(QPalette::Background,QColor(255,0,0)); ui->color_label->setAutoFillBackground(true); ui->color_label->setPalette(palette); emit labelColor_signal(palette); } void Form::on_green_btn_clicked() { QPalette palette; palette.setColor(QPalette::Background,QColor(0,255,0)); ui->color_label->setAutoFillBackground(true); ui->color_label->setPalette(palette); emit labelColor_signal(palette); }
form.ui
两个颜色按钮,点击 改变label的背景颜色
void Form::setLabelColor_slot(QPalette p) { ui->color_label->setPalette(p); }
这个槽是等会在主程序与插件通信调用插件的槽.
这样直接编译就生成个dll
2.加载Qt插件
#include <QPluginLoader> #include <QtDesigner/QDesignerCustomWidgetInterface> QWidget *loadPlugin(QString pluginPath) { QPluginLoader loader(pluginPath); if(loader.load()) { qDebug()<<"load ok"; } else { qDebug()<<"load failed !"; return NULL; } QObject* plugin = loader.instance(); if(plugin) { QDesignerCustomWidgetInterface* interface = qobject_cast<QDesignerCustomWidgetInterface*>(plugin); if(interface) { QWidget* w = interface->createWidget(NULL); return w; } } else { qDebug()<<"loader.instance failed!"; return NULL; } }
loadPlugin 会返回一个 QWidget 的指针 指向的就是 插件的Form 窗口
因为我们插件 createWidget 返回的就是 form
与插件通信
当我们拿到 插件的form 实例化的对象,我们就可以用信号和槽了
//信号槽 QWidget* m_plugin =NULL; m_plugin = loadPlugin("D:\\testQtPlugins\\myplugind.dll"); connect(this,SIGNAL(setLabelColor_signal(QPalette)),m_plugin,SLOT(setLabelColor_slot(QPalette))); connect(m_plugin,SIGNAL(labelColor_signal(QPalette)),this,SLOT(setLabelColor_slot(QPalette)));
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); signals: void setLabelColor_signal(QPalette p); public slots: void setLabelColor_slot(QPalette p); private slots: void on_red_btn_clicked(); void on_green_btn_clicked(); void on_loadPlugin_btn_clicked(); private: Ui::Widget *ui; QWidget* m_plugin; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QPluginLoader> #include <QDebug> #include <QtDesigner/QDesignerCustomWidgetInterface> //加载插件 QWidget *loadPlugin(QString pluginPath) { QPluginLoader loader(pluginPath); if(loader.load()) { qDebug()<<"load ok"; } else { qDebug()<<"load failed !"; return NULL; } QObject* plugin = loader.instance(); if(plugin) { QDesignerCustomWidgetInterface* interface = qobject_cast<QDesignerCustomWidgetInterface*>(plugin); if(interface) { QWidget* w = interface->createWidget(NULL); return w; } } else { qDebug()<<"loader.instance failed!"; return NULL; } } Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } void Widget::setLabelColor_slot(QPalette p) { ui->color_label->setPalette(p); } void Widget::on_red_btn_clicked() { QPalette palette; palette.setColor(QPalette::Background,QColor(255,0,0)); ui->color_label->setAutoFillBackground(true); ui->color_label->setPalette(palette); emit setLabelColor_signal(palette); } void Widget::on_green_btn_clicked() { QPalette palette; palette.setColor(QPalette::Background,QColor(0,255,0)); ui->color_label->setAutoFillBackground(true); ui->color_label->setPalette(palette); emit setLabelColor_signal(palette); } void Widget::on_loadPlugin_btn_clicked() { //load plugin m_plugin = loadPlugin("D:\\testQtPlugins\\myplugind.dll"); m_plugin->show(); //信号槽 connect(this,SIGNAL(setLabelColor_signal(QPalette)),m_plugin,SLOT(setLabelColor_slot(QPalette))); connect(m_plugin,SIGNAL(labelColor_signal(QPalette)),this,SLOT(setLabelColor_slot(QPalette))); }
widget.ui
效果就是加载插件,主程序点击 红色按钮 主程序的label 和 插件的 label 都变为红色 ,点击 插件的绿色按钮,主程序和插件的label都变成绿色
!!!重要:
插件的编译环境要和加载插件的程序的编译环境 一摸一样 比如 插件用 Qt5.9编译的
那么加载插件的程序 也要用Qt5.9 用 Qt5.8编译就加载失败,并且 debug 的插件 对应debug的加载程序, release 对应 release. -
ArcGIS加载在线的高德、天地图、OSM和谷歌地图的插件
2018-07-03 15:04:56ArcGIS不能加载在线的高德、天地图、OSM和谷歌地图,安装该插件,将会在ArcMap中创建一个名为ChinaMap的工具条,加载该工具条以后,就可以在ArcMap中打开在线的高德地图、天地图地图、OSM地图和谷歌地图啦。 -
30 个 jQuery & CSS3 加载动画和进度栏插件
2014-03-02 20:05:0930 个 jQuery & CSS3 加载动画和进度栏插件 -
CTK如何实现运行时插件加载
2018-08-13 08:02:05在编写好了调用插件的简单程序后,制作好dll插件,程序提供了一个按钮,这个按钮的作用是重新读取插件目录,加载并start新插件: 1.在程序启动时不添加插件,在启动后添加插件到目录,点击按钮,插件识别成功,启动... -
浩辰CAD中如何加载插件?CAD插件安装教程
2022-01-28 16:05:56为了提高绘图效率,很多设计师在使用CAD软件绘制图纸的过程中经常会用到各种实用的CAD插件,那么浩辰CAD中如何加载插件呢?下面小编就来给大家分享一下浩辰CAD软件中安装CAD插件的相关操作技巧吧! CAD插件安装步骤... -
unity 3D动态加载FBX插件 UniFBX 2_2.3.1
2018-01-16 14:07:21unity动态加载FBX模型UniFBX (2) 2.3.1,可以再运行时加载外部fbx模型 要求Unity 5.5.0 或更高版本。 -
ArcMap影像加载插件功能说明
2020-09-01 11:19:09EEDArcMap影像加载插件功能说明 一、谷歌地球影像数据加载 插件可以直接从谷歌地球服务器获取数据,加载全球任意地区的影像数据,分辨率最高0.26米,图层可以用于打印和导出。 二、天地图、维基地图等数据的... -
CobaltStrike加载插件
2020-05-12 23:59:51首先,安装MS17-010的插件 -
fullcalendar 插件,重新加载;
2020-10-26 11:56:37fullcalendar 插件,重新加载; id时div框的,根据自己html页面赋值即可 $('#id').fullCalendar('refetchEvents'); -
解决IDEA无法加载插件或者加载了插件下载超时的问题
2020-04-12 19:18:05一、解决IDEA无法加载插件问题 file->settings 按照下图设置 然后再加载插件就ok了 二、解决下载插件超时问题 重新勾选使用安全连接 保存设置之后再重新下载即可 ...