前言
最近对一个Flutter项目升级了一波依赖库版本,在开发的电脑上测试没问题后提交改动,结果到打包机打新包时遇到问题报错了。
开发环境
- Flutter: 3.10.5
- Dart: 3.0.5
- Fluwx: 4.2.6
问题描述
报错信息:
/xxx/plist-3.6.0/lib/plist/parser.rb:29:in `parse_xml': wrong number of arguments (given 2, expected 1) (ArgumentError)
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:72:in `block (2 levels) in <main>'
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:63:in `each'
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:63:in `block in <main>'
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:50:in `each'
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:50:in `<main>'
问题分析
从报错信息看,问题出在parse_xml
方法,这个方法只接受一个入参,但是现在却给了两个。找到报错的具体位置(/xxx/fluwx-4.2.6/ios/wechat_setup.rb:72
):
Fluwx
调用解析属性列表文件的方法时确实传入了两个参数,第一个是属性列表文件路径,第二个参数暂时不知道有什么作用。根据报错信息(/xxx/plist-3.6.0/lib/plist/parser.rb:29
)找到parse_xml
方法的定义:
module Plist
...
# Note that I don't use these two elements much:
#
# + Date elements are returned as DateTime objects.
# + Data elements are implemented as Tempfiles
#
# Plist.parse_xml will blow up if it encounters a Date element.
# If you encounter such an error, or if you have a Date element which
# can't be parsed into a Time object, please create an issue
# attaching your plist file at https://github.com/patsplat/plist/issues
# so folks can implement the proper support.
def self.parse_xml(filename_or_xml)
listener = Listener.new
# parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
parser = StreamParser.new(filename_or_xml, listener)
parser.parse
listener.result
end
...
end
咦🤔️,parse_xml
方法确实只接受一个入参,这是怎么回事?这个问题是在打包机上遇到的,但是在平时开发的电脑上是没问题的,在开发的电脑上找到parse_xml
方法:
module Plist
...
# Note that I don't use these two elements much:
#
# + Date elements are returned as DateTime objects.
# + Data elements are implemented as Tempfiles
#
# Plist.parse_xml will blow up if it encounters a Date element.
# If you encounter such an error, or if you have a Date element which
# can't be parsed into a Time object, please create an issue
# attaching your plist file at https://github.com/patsplat/plist/issues
# so folks can implement the proper support.
#
# By default, <data> will be assumed to be a marshaled Ruby object and
# interpreted with <tt>Marshal.load</tt>. Pass <tt>marshal: false</tt>
# to disable this behavior and return the raw binary data as an IO
# object instead.
def self.parse_xml(filename_or_xml, options={})
listener = Listener.new(options)
# parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
parser = StreamParser.new(filename_or_xml, listener)
parser.parse
listener.result
end
...
end
经过对比发现,没问题的电脑上装的plist
包是3.7.0
版本,有问题的打包机装的plist
包是3.6.0
版本。从3.7.0
版本开始,parse_xml
方法支持了第二个参数,默认情况下该方法会将读取的文件序列化为Ruby对象并返回,而marshal: false
的作用就是禁用这个默认行为,改为返回IO对象。
3.6.0
版本:
module Plist
...
require 'base64'
class PData < PTag
def to_ruby
data = Base64.decode64(text.gsub(/\s+/, '')) unless text.nil?
begin
return Marshal.load(data)
rescue Exception
io = StringIO.new
io.write data
io.rewind
return io
end
end
end
end
根据源码可以看到,这个版本只有当Marshal.load
方法调用出现异常,才会在处理异常时返回IO对象。
3.7.0
版本:
module Plist
...
require 'base64'
class PData < PTag
def to_ruby
data = Base64.decode64(text.gsub(/\s+/, '')) unless text.nil?
begin
return Marshal.load(data) if options[:marshal]
rescue Exception
end
io = StringIO.new
io.write data
io.rewind
io
end
end
end
这个版本则加了if options[:marshal]
判断,当有设置marshal: false
(这时return Marshal.load(data)
语句将不会执行)或Marshal.load
方法调用出现异常时,返回IO对象。
参考文档:
解决方案
执行以下命令安装最新版本(3.7.0
及以上版本)的plist
包即可:
gem install plist
如果要安装指定版本的plist
包,可以使用以下命令:
gem install plist --version [版本号]
卸载命令同理也可以指定版本号,不过一般不需要,如果有多个版本同时存在时执行gem uninstall xxx
卸载命令,会出现多个选项供你选择是卸载指定某个版本还是全部版本。
补充内容1
如果遇到以下类似报错:
<internal:/xxx/kernel_require.rb>:148:in `require': cannot load such file -- plist (LoadError)
from <internal:/xxx/kernel_require.rb>:148:in `require'
from /xxx/fluwx-4.2.6/ios/wechat_setup.rb:8:in `<main>'
这是由于未安装某个包导致的。从报错信息可知,需要安装plist
包,执行以下命令安装即可解决:
gem install plist
补充内容2
如果遇到以下类似报错:
[!] Invalid podspec file at path `/xxx/ios/.symlinks/plugins/fluwx/ios/fluwx.podspec`.
按报错信息中的路径找到问题文件,如果里面内容缺失了,那很可能是因为第三方库没下载完整导致的报错。
解决方法:
- 首先在Android Studio左侧项目目录中找到[External Libraries]并展开
- 接着找到报错的第三方库并选中,右键选择删除。插件库在[Flutter Plugins]展开列表中查找
- 然后执行
flutter pub get
命令重新下载第三方库 - 最后切换到Flutter项目下的ios目录,执行
pod install
命令,问题一般就解决了
最后
如果这篇文章对你有所帮助,点赞👍收藏🌟支持一下吧,谢谢~
本篇文章由@crasowas发布于CSDN。