专业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)方法调用addFavorateextension 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方法重新计算fullPngPathrequired 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) }