Zhihao's Studio.

Match开发笔记 伍 3.0版的新功能与上架

Word count: 1,695 / Reading time: 7 min
2018/10/31 Share

前言

Match问答3.0版本近期在App Store和各大安卓市场上架了,此次更新,我们让应用进一步完善。主要新功能有:

  1. 增加图片放缩、移动和本地保存的功能;
  2. 增加对图文混排的支持;
  3. 增加对问题关键词和问题难度的系统评判,并基于问题难度提升问题的奖励;
  4. 增加对问题的重新编辑功能;
  5. 修改赞/踩按钮点击延迟的bug;
  6. 优化部分界面UI

先放张主页预览图。

图文混排富文本

图文混排是本次升级的主要工作,也让我比较深入了学习了TextKit相关的知识。富文本在Github上可用的轮子不多,我试用了接近10个自带富文本的应用,发现基本都不可用,大部分是基于Webview的包装。

其实富文本是历史遗留问题,从Match1.0版本的时候就很想要这个功能,但苦于一直没有找到合适的轮子,一直在回避,用文字超链接的方式跳转到详情页,一直安慰自己小图反正也看不清。但看到知乎将图片拉到与手机屏幕等宽,效果还蛮好的,而且阿里云OSS也比较强大,可以支持很多参数,于是开始着手做富文本这块。基于我们系统前后台的json标准,我采取了一种递归的方式来解析文本,将图片的特殊标志替换成需要的图片,并提取出key,从阿里云获取相应的图片,插入到textview的合适位置上,参考实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
func insertImage(image: UIImage, imageName:String) {
let attString = createAttStringWithImage(image: image, height: imageheight, imageName: imageName)
//add this attributed string to the current position.
self.textStorage.insert(attString, at: self.selectedRange.location)
}
func insertImage(image : UIImage , index : Int, imageName:String){
let attrString = createAttStringWithImage(image: image, height: imageheight/2,imageName: imageName)
self.textStorage.insert(attrString, at: index)
self.adjustUITextViewHeight()
}
func createTextStorageByText(text : String , num : Int) -> [String]{
if(text.count == num && self.flag == false){
self.flag = true
return []
}
var pic_names : [String] = []
if(text.count > 0 && self.flag) {
if(text.hasPrefix("<--image_link-->")){
var tmpOffset = 0
while((text.substring(from: tmpOffset, to: text.count).hasPrefix("</--image_link-->"))==false){
tmpOffset = tmpOffset + 1
}
pic_names.append(text.substring(from: "<--image_link-->".count , to : tmpOffset))
if(self.image_names.contains(text.substring(from: "<--image_link-->".count , to : tmpOffset))==false){
self.image_names.append(text.substring(from: "<--image_link-->".count , to : tmpOffset))
}
self.readProvider = (UIApplication.shared.delegate as! AppDelegate).readProvider
self.readClient = (UIApplication.shared.delegate as! AppDelegate).readClient
self.bucketName = (UIApplication.shared.delegate as! AppDelegate).bucketName
let getObjectReq: OSSGetObjectRequest = OSSGetObjectRequest()
getObjectReq.bucketName = self.bucketName
getObjectReq.objectKey = text.substring(from: "<--image_link-->".count , to : tmpOffset)
getObjectReq.xOssProcess = "image/resize,m_fill,h_100,w_\(screenw),Q_60"
getObjectReq.downloadProgress = { (bytesWritten: Int64,totalBytesWritten : Int64, totalBytesExpectedToWrite: Int64) -> Void in
};
let task: OSSTask = self.readClient.getObject(getObjectReq);
task.continue({(t) -> OSSTask<AnyObject>? in
if(task.error == nil){
let avatar = task.result
DispatchQueue.main.async {
if(UIImage(data: (avatar?.downloadedData)!) != nil){
let image = UIImage(data: (avatar?.downloadedData)!)!
self.insertImage(image: image, imageName: text.substring(from: "<--image_link-->".count , to : tmpOffset))
self.offset = self.offset + tmpOffset + "</--image_link-->".count
// self.adjustUITextViewHeight()
var tmp_pic_names = self.createTextStorageByText(text: text.substring(from: tmpOffset + "</--image_link-->".count , to: text.count), num: 1000086)
tmp_pic_names.map{ pic in
pic_names.append(pic)
}
}
}
}
return nil
})
task.waitUntilFinished()
}
else{
self.appendLinkString(string: text.substring(from: 0, to: 1))
if(text.count > 1){
var tmp_pic_names = self.createTextStorageByText(text: text.substring(from: 1), num: 1000086)
self.offset = self.offset + 1
tmp_pic_names.map{ pic in
pic_names.append(pic)
}
}
}
}
return pic_names
}

需要注意的是插入图片的操作要放到主线程。当然,实际过程中也遇到了一些问题,比如为了让两张连续图片中间有一定距离,引入了行距。但是如果这个问题/回答本身并没有文字,只有图片,行距是不生效的,这种情况就需要在前面加入\t制表符。

这次允许编辑用户自己之前发表过的问题或回复,当然也是涉及富文本的,图片提交之前判断了以前是不是保存过了,还是新添加的。

插入图片后,Tableview中富文本Cell的高度自动计算就不正确了,需要自己给出高度的计算方法。这里,我设置了图片的高度为100,宽度为屏幕等宽,因此需要统计图片的数量。还需要统计的是\n的数量、文字的数量,这部分是乘以行距和行高也是Cell高度的有效组成部分。

这个部分内容较多,在这先不展开了,后面有机会仔细写一下,顺便把这个richtext轮子开源。目前还不能称作轮子,是辆整车,需要将业务从现有代码中抽离,尽量做的通用一些。

富文本改造前后对比

上架过程

和以往不同,这次的上架过程显得异常艰难,遇到了很多困难。首先是打包的时候报错。

因为之前真机测试和模拟器测试都是没有报错的,在周日晚上发现了这个问题,必然会影响睡眠质量了。经查,有个库PhotoBrowser必须要求使用Swift 4.2,而我现有的库是基于Swift 4.1的。在工程下看到了有别人提了类似的issue,于是,我将工程升到了4.2,修改了大概100个地方,时间也来到了近2点。。。结果蛋疼的地方又出现了,有些库只支持到Swift 4.1!!!

因为现在Xcode正式版还没放出来,第三方库也都没有支持 Swift 4.2 ,通过修改podfile让不支持 Swift 4.2 的第三方库在4.1下编译,等到所有依赖的第三方库都支持 Swift 4.2 之后,再把 podfile 改回去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
swift_41_pod_targets = ['SnapKit','MonkeyKing','RxCocoa', ...]
post_install do | installer |
    installer.pods_project.targets.each do |target|
        if swift_41_pod_targets.include?(target.name)
            target.build_configurations.each do |config|
                config.build_settings['SWIFT_VERSION'] = '4.1'
            end
        end
    end
end

在 Build Setting 中搜索 Swift Language Version 将 Swift 版本号改为 Swift 4.2,完成了整个工程的语言版本升级。

logo更新

在某宝上买了一个Logo设计的服务,400大洋,说是总监级别的设计师,结果前三次完全是搞笑,最后搞出来一个差强人意的logo。

没想到在上架过程中也遇到了问题ERROR ITMS-90717:

Invalid App Store Icon. The App Store Icon in the asset catalog in ‘Some.app’ can’t be transparent nor contain an alpha channel.

在简书搜到了解决方法,原来苹果需要调整Alpha通道为否

这次总算上传成功了。后面的审核也是异常顺利,不到10小时就完成了审核,非常迅速,给苹果的审核团队点赞。

后记

这小半年时间,不知不觉已经为Match写下了2,5000+多行代码,现在回头看看,挺感谢Match的,他让我专注思考和动手,激发了我精益求精的态度,也成了我独有的一份精神寄托。他就像我的孩子一样,看着他从无到有,越来越好,心里挺满足的。

引用

  1. 升级 Swift 4.2 教程
  2. Text Kit Tutorial
  3. PhotoBrowser
  4. 关于Swift 4.2的issue
  5. ERROR ITMS-90717
CATALOG
  1. 1. 前言
  2. 2. 图文混排富文本
  3. 3. 上架过程
  4. 4. logo更新
  5. 5. 后记
  6. 6. 引用