专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构
表情键盘添加最近使用表情
在
HMEmoticonManager
里面添加addFavorate
方法,添加最近表情,最近使用的表情添加到最前面// MARK: - 最近表情相关 /** 添加表情到最近表情包 parameter emoticon: 要添加的表情模型 */ func addFavorate(emoticon: HMEmoticonModel) { // 获取最近表情 var recentEmoticons = packages[0].pageEmoticons[0] recentEmoticons.insert(emoticon, at: 0) print("最近表情1: \(recentEmoticons)") print("最近表情2: \(packages[0].pageEmoticons[0])") }
在
HMEmoticonKeyboard
的HMEmoticonPageCellDelegate
的协议的emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel)
方法调用addFavorate
extension HMEmoticonKeyboard: HMEmoticonPageCellDelegate { func emoticonPageCellDidClickDeleteButton() { textView?.deleteBackward() } func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) { textView?.insertEmoticon(emoticon: emoticon) HMEmoticonManager.shared.addFavorate(emoticon: emoticon) // 刷新最近这组 var indexSet = IndexSet() indexSet.insert(0) collectionView.reloadSections(indexSet) } }
打印
发现表情模型
没有添加进去
,需要重新赋值回去/** 添加表情到最近表情包 parameter emoticon: 要添加的表情模型 */ func addFavorate(emoticon: HMEmoticonModel) { // 获取最近表情 var recentEmoticons = packages[0].pageEmoticons[0] recentEmoticons.insert(emoticon, at: 0) // 需要赋值回去 packages[0].pageEmoticons[0] = recentEmoticons print("最近表情1: \(recentEmoticons)") print("最近表情2: \(packages[0].pageEmoticons[0])") }
发现相同的表情会重复添加.需要先将相同的表情移除在将表情添加到数组最前面
// MARK: - 最近表情相关 /** 添加表情到最近表情包 parameter emoticon: 要添加的表情模型 */ func addFavorate(emoticon: HMEmoticonModel) { // 获取最近表情 var recentEmoticons = packages[0].pageEmoticons[0] // 判断是否有重复表情 var repeatEmoticon: HMEmoticonModel? for e in recentEmoticons { // emoji if (emoticon.emoji != nil && emoticon.code == e.code) || (emoticon.chs != nil && emoticon.chs == e.chs) { repeatEmoticon = e break } } print("是否已经存在repeatEmoticon: \(repeatEmoticon)") if let e = repeatEmoticon { let index = recentEmoticons.index(of: e) recentEmoticons.remove(at: index!) print("有重复表情,删除: \(index), \(e)") } recentEmoticons.insert(emoticon, at: 0) // 需要赋值回去 packages[0].pageEmoticons[0] = recentEmoticons print("最近表情2: \(packages[0].pageEmoticons[0])") }
当最近这一页的表情超过20个的时候会出现数组越界,原因是,cell里面只添加了20个按钮,但是模型不只20个,按钮的数组就越界了,所以最近表情模型不能超过20个
// MARK: - 最近表情相关 /** 添加表情到最近表情包 parameter emoticon: 要添加的表情模型 */ func addFavorate(emoticon: HMEmoticonModel) { // 获取最近表情 var recentEmoticons = packages[0].pageEmoticons[0] // 判断是否有重复表情 var repeatEmoticon: HMEmoticonModel? for e in recentEmoticons { // emoji if (emoticon.emoji != nil && emoticon.code == e.code) || (emoticon.chs != nil && emoticon.chs == e.chs) { repeatEmoticon = e break } } print("是否已经存在repeatEmoticon: \(repeatEmoticon)") if let e = repeatEmoticon { let index = recentEmoticons.index(of: e) recentEmoticons.remove(at: index!) print("有重复表情,删除: \(index), \(e)") } recentEmoticons.insert(emoticon, at: 0) // 判断是否超过20个,如果超过20,将数组最后的表情删除 if recentEmoticons.count > HMEmoticonNumberOfPage { recentEmoticons.removeLast() } // 需要赋值回去 packages[0].pageEmoticons[0] = recentEmoticons print("最近表情2: \(packages[0].pageEmoticons[0])") }
- 最近表情归档到沙盒,让
CZEmoticonModel
实现NSCoding
协议,并实现init?(coder aDecoder: NSCoder)
和encodeWithCoder(aCoder: NSCoder)
// MARK: - 归档和解档 required init?(coder aDecoder: NSCoder) { id = aDecoder.decodeObject(forKey: "id") as? String ?? "" chs = aDecoder.decodeObject(forKey: "chs") as? String png = aDecoder.decodeObject(forKey: "png") as? String fullPngPath = aDecoder.decodeObject(forKey: "fullPngPath") as? String code = aDecoder.decodeObject(forKey: "code") as? String emoji = aDecoder.decodeObject(forKey: "emoji") as? String } // func encode(with aCoder: NSCoder) { aCoder.encode(id, forKey: "id") aCoder.encode(chs, forKey: "chs") aCoder.encode(png, forKey: "png") aCoder.encode(fullPngPath, forKey: "fullPngPath") aCoder.encode(code, forKey: "code") aCoder.encode(emoji, forKey: "emoji") }
- 在
HMEmoticonManager
定义最近表情模型归档
的路径recentEmoticonPath
/// 最近表情模型归档的路径 private let recentEmoticonPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! + "/recentEmoticons.plist"
- 在
HMEmoticonManager
定义saveRecentEmoticons
方法来将最近表情保存到沙盒
/** 保存最近表情 */ private func saveRecentEmoticons() { print("NSHomeDirectory: \(NSHomeDirectory())") print("保存的表情模型: \(packages[0].pageEmoticons[0])") NSKeyedArchiver.archiveRootObject(packages[0].pageEmoticons[0], toFile: recentEmoticonPath) }
- 运行测试,可以将最近表情模型数组
[HMEmoticonModel]
保存到沙盒
- 从
沙盒
加载最近表情
, 在HMEmoticonManager
定义loadRecentEmoticons
方法/** 加载最近表情 returns: 最近表情 */ private func loadRecentEmoticons() -> [HMEmoticonModel] { if let emoticons = NSKeyedUnarchiver.unarchiveObject(withFile: recentEmoticonPath) as? [HMEmoticonModel] { return emoticons } else { return [HMEmoticonModel]() } }
- 在
HMEmoticonManager
的loadPackages
里面加载最近表情包/// 加载所有的表情包 private func loadPackages() -> [HMEmoticonPackageModel] { let recentPackage = HMEmoticonPackageModel(id: "", groupName: "最近", emoticons: loadRecentEmoticons()) return [recentPackage, loadPackage(id: "com.sina.default"), loadPackage(id: "com.apple.emoji"), loadPackage(id: "com.sina.lxh")] }
- 运行,发现最近表情并没有显示.但是可以点击,说明模型加载出来了,只是图片没有显示,原因是: 每次运行程序
沙盒路径是变化的
,将fullPngPath
归档到沙盒,下次再运行找不到图片. - 在
对象
的init
方法里面赋值,不会调用对象属性的didSet
方法.在init:coder
方法重新计算fullPngPath
required init?(coder aDecoder: NSCoder) { id = aDecoder.decodeObject(forKey: "id") as? String ?? "" chs = aDecoder.decodeObject(forKey: "chs") as? String png = aDecoder.decodeObject(forKey: "png") as? String code = aDecoder.decodeObject(forKey: "code") as? String emoji = aDecoder.decodeObject(forKey: "emoji") as? String // fullPngPath = aDecoder.decodeObject(forKey: "fullPngPath") as? String // 重新拼接全路径,因为在模拟器上面重新运行沙盒的路径会变化pngPath会失效 if let p = png { fullPngPath = bundlePath + "/" + id + "/" + p } }
点击
最近
发现这页的内容会被刷新,其实最近
这组的表情不要参与排序func emoticonPageCell(didSelectedEmoticon emoticon: HMEmoticonModel) { textView?.insertEmoticon(emoticon: emoticon) let indexPath = collectionView.indexPathsForVisibleItems.first! if indexPath.section == 0 { return } HMEmoticonManager.shared.addFavorate(emoticon: emoticon) // 刷新最近这组 var indexSet = IndexSet() indexSet.insert(0) collectionView.reloadSections(indexSet) }