zoukankan      html  css  js  c++  java
  • 新浪微博客户端(53)-记录用户最近点击表情

    设计思路:每当用户点击一个表情,就将该表情(DJEmotion)存储到沙盒,当用户切换到“最近”栏目时,从沙盒中取出用户最近点击的表情列表,进行显示。

    1. 保存DJEmotion

    DJEmotion.h

    #import <Foundation/Foundation.h>
    
    // 因为要保存最近使用的表情到沙盒,所以该对象须实现NSCoding协议
    @interface DJEmotion : NSObject <NSCoding>
    
    /** Emotion 中文字符 */
    @property (nonatomic,copy) NSString *chs;
    /** Emotion 对应图片 */
    @property (nonatomic,copy) NSString *png;
    /** Emoji 二进制数字 */
    @property (nonatomic,copy) NSString *code;
    
    @end

    DJEmotion.m

    #import "DJEmotion.h"
    
    @implementation DJEmotion
    
    
    /**
     * 此方法用于比较两个对象是否是否相等,即:==
     * 类似于java中的isEqual方法
     * 重写该方法意味着覆盖系统的比较方式
     */
    - (BOOL)isEqual:(DJEmotion *)other {
    
        // 重写Emotion的比较方式,即:当Emotion对象中的chs或code相等时,就视这两个对象相等
        return [self.chs isEqualToString:other.chs] || [self.code isEqualToString:other.code];
        
    }
    
    
    // 解码
    - (instancetype)initWithCoder:(NSCoder *)decoder {
    
        if (self = [super init]) {
            self.chs = [decoder decodeObjectForKey:@"chs"];
            self.png = [decoder decodeObjectForKey:@"png"];
            self.code = [decoder decodeObjectForKey:@"code"];
        }
        return self;
    }
    
    
    // 编码
    - (void)encodeWithCoder:(NSCoder *)encoder {
    
        [encoder encodeObject:self.chs forKey:@"chs"];
        [encoder encodeObject:self.png forKey:@"png"];
        [encoder encodeObject:self.code forKey:@"code"];
    
    }
    
    
    @end

    2. 将表情存储到沙盒中的工具类

    DJEmotionTool.h

    #import <Foundation/Foundation.h>
    
    @class DJEmotion;
    @interface DJEmotionTool : NSObject
    
    /** 保存最近点击Emotion */
    + (void)saveRecentEmotion:(DJEmotion *)emotion;
    
    /** 获取存储在沙盒中最近点击的Emotion集合 */
    + (NSArray *)recentEmotions;
    
    @end

    DJEmotionTool.m

    #import "DJEmotionTool.h"
    
    
    // 最近表情保存路径
    #define DJEmotionPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"emotion.archiver"]
    
    // 类似于java里面的静态成员变量
    static NSMutableArray *_recentEmotions;
    
    @implementation DJEmotionTool
    
    
    /**
     * 这个方法会在第一次使用这个类的时候调一次,且只调一次
     * 类似于java中静态代码块
     */
    + (void)initialize {
    
        _recentEmotions = [NSKeyedUnarchiver unarchiveObjectWithFile:DJEmotionPath];
        if (_recentEmotions == nil) {
            _recentEmotions = [NSMutableArray array];
        }
    }
    
    
    
    /** 保存最近点击Emotion */
    + (void)saveRecentEmotion:(DJEmotion *)emotion {
        
        // 移除之前存储的相同Emotion
        [_recentEmotions removeObject:emotion];
    
        // 在数组的头部插入新的Emotion
        [_recentEmotions insertObject:emotion atIndex:0];
        
        // 保存当前数组
        [NSKeyedArchiver archiveRootObject:_recentEmotions toFile:DJEmotionPath];
    
    }
    
    /** 获取存储在沙盒中最近点击的Emotion集合 */
    + (NSArray *)recentEmotions {
        return _recentEmotions;
    }
    
    
    @end

    3. 因为存储在沙盒的最近表情是实时变换的,所以不能使用懒加载,因此在点击最近按钮时,重新给最近按钮的ListView赋值:

    DJEmotionKeyboard.m

    #pragma mark - DJEmotionTabBar 的代理方法
    - (void)emotionTabBar:(DJEmotionTabBar *)tabBar didSelectedButtonType:(DJEmotionTabBarButtonType)buttonType {
    
        // 1. 清空placeView中之前存在的其它View(类似于android中的ViewGroup.removeAllViews)
        [self.placeView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        
        // 2. 切换contentView
        switch (buttonType) {
            case DJEmotionTabBarButtonTypeRecent: // 最近
                [self.placeView addSubview:self.recentEmotionView];
                // 从DJEmotionTool中获取沙盒中存储的最近使用表情,注意!此处不能使用懒加载,因为这样会导致数据无法实时更新
                self.recentEmotionView.emotions = [DJEmotionTool recentEmotions];
                break;
            case DJEmotionTabBarButtonTypeDefault: // 默认
                [self.placeView addSubview:self.defaultEmotionView];
                break;
            case DJEmotionTabBarButtonTypeEmoji: // Emoji
                [self.placeView addSubview:self.emojiEmotionView];
                break;
            case DJEmotionTabBarButtonTypeLxh: // 浪小花
                [self.placeView addSubview:self.lxhEmotionView];
                break;
            default:
                break;
        }
        
        // 3.切换完毕后通知系统重新布局,相当于再次调用layoutSubViews
        [self setNeedsLayout];
        
        
    }

    4. 当ListView收到传来的新数据时,清空之前的控件,进行重新布局(目的是为了让新点击的最近表情排在前面)。

    DJEmotionListView.m

    - (void)setEmotions:(NSArray *)emotions {
    
        
        _emotions = emotions;
        
        // 先清空scrollView里面已有的子控件,便于刷新
        [self.emotionScrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        
        
        // emotion 总个数
        NSUInteger emotionCount = emotions.count;
        // 页码总个数
        NSUInteger pageNums = (emotionCount + DJEmotionPageSize - 1) / DJEmotionPageSize;
        
        // 更新pageControl 显示个数
        self.emotionPageControl.numberOfPages = pageNums;
        
        // 为scrollView 添加子View
        for (int i = 0; i < pageNums; i++) {
            DJEmotionPageView *pageView = [[DJEmotionPageView alloc] init];
    //        pageView.backgroundColor = DJRandomColor;
            
            NSRange range;
            range.location = i * DJEmotionPageSize;
            NSUInteger leftNums = emotionCount - range.location; // 求出当前剩余Emoji个数
            if (leftNums >= DJEmotionPageSize) { // 判断当前剩余Emoji个数是否满20
                range.length = DJEmotionPageSize;
            } else { // 如果不满20,则range.length就等于剩余的个数
                range.length = leftNums;
            }
            
            NSArray *singlePageEmotions = [emotions subarrayWithRange:range];
            pageView.emotions = singlePageEmotions;
            
            [self.emotionScrollView addSubview:pageView];
        }
        
        // 数据添加完毕后,通知系统进行重新布局
        [self setNeedsLayout];
        

    5. 当点击表情按钮或滑动表情按钮时,如果发出了输入通知,此时就将点击的表情按钮存储到沙盒中去。

    DJEmotionPageView.m

    // 发送点击广播(和android类似,区别在于android的广播是只要有上下文对象context,就可以发送)
    // iOS中的通知发送和接收都是通过NSNotificationCenter完成
    - (void)sendBtnClickNotification:(DJEmotionButton *)btn {
    
        // 存储当前Emotion表情
        [DJEmotionTool saveRecentEmotion:btn.emotion];
        
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
        userInfo[DJEmotionDidSelctedEmotionKey] = btn.emotion;
        
        [[NSNotificationCenter defaultCenter] postNotificationName:DJEmotionDidSelectedNotification object:nil userInfo:userInfo];
    
    }

    最终效果:

  • 相关阅读:
    电位器的使用
    序言
    跨域之options请求详解
    redis config 实现切库 和指定序列化
    巨坑! druid1.1.0
    跨域问题解决
    canal解决缓存穿透 对数据库同步数据至redis 或EleasticSearch
    oauth2+spring security +jwt 完成分布式服务认证
    oauth2的数据库设计
    Gson 转换 Localdate 使用 GsonBuilder setDateFormat 无效
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6135625.html
Copyright © 2011-2022 走看看