iOS开发 WMPageController消息提醒,设置menuView上title的小红点

笔者性懒,腹中无墨
关于WMPageController,不再赘述.本文旨在简述使用了WMPageController的web页面加入消息提醒等功能,有新消息时以小红点标记,查看之后小红点消失.

简略图:

有新消息.png
绕过活动则红点不消失.png
点击活动红点消失.png

1.进入控制器首先需要获得所有的webView,控制器继承自WMPageController.如果需要js交互,可以先写一个存放js交互信息的swift文件,方便管理,数据请求也放在这个交互信息的文件里.

WebUrlService.shared.updateUrls { finish in
    if finish {
        DispatchQueue.main.async {
            self.webUrls = WebUrlService.shared.urls
            self.reloadData()
        }
    }
}

其中,WebUrlService即为存放js交互信息的swift文件,updateUrls是数据请求的函数,函数里以将返回的结果保存,通过单利获取这些url数据WebUrlService.shared.urls,给到当前WMPageController的webUrls.

2.通常WMPageController的menuView的各个title是确定的,这个需要与web开发同事沟通好,指定某个或者某几个web页面有消息提醒业务.例如,在众多的菜单title中,有一个"活动"项目,实现需要确定"活动"的位置是否固定,若不固定,那么标题是否固定.假设有一个页面就叫"活动",需要给"活动"加小红点提醒. WMPageController有如下方法:

override func pageController(_ pageController: WMPageController, titleAt index: Int) -> String {
    guard let title = webUrls?[index].name else {return "未知"}
    if title == "活动" {
        redPointIndex = index
    }
    return title
}

其中webUrls是上一步中获取的所有url信息,redPointIndex是Int型的变量,用于记录"活动"的位置. override - 控制器继承自WMPageController.

3.判断是否有新活动需要提醒

ActivityUrlService.shared.updateActivity { (hasNews) in
    if hasNews {
        DispatchQueue.main.async {
            self.unRead = reload
            self.reloadData()
        }
    }
}

其中,unRead是Bool值的变量,判断是否有未读消息,消息条数若有需要也可以获取.

4.添加小红点,WMPageController有下面方法:

override func menuView(_ menu: WMMenuView!, badgeViewAt index: Int) -> UIView! {
    if index == redPointIndex && unRead == true {
        let view = UIView(frame: CGRect(x: itemWidths[index]-10, y: 7, width:6, height: 6))
        view.layer.cornerRadius = 3
        view.layer.masksToBounds = true
        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 6, height: 6))
        imageView.image = #imageLiteral(resourceName: "btn_red_normal")
        view.addSubview(imageView)
        return view
    }
    return nil
}

设置好badgeView的frame,太大会遮挡title.

5.当点击了"活动",将小红点去掉,若跳过"活动",只是任意点击其他的title,则小红点不消失.

override func pageController(_ pageController: WMPageController, didEnter viewController: UIViewController, withInfo info: [AnyHashable : Any]) {
    if pageController.selectIndex == Int32(redPointIndex) {
        unRead = false
        menuView?.updateBadgeView(at: redPointIndex)
    }
}

其中, WMPageController的selectIndex属性是Int32,需转换.

6.注意:
以上只是将关键步骤列出, WMPageController的代理方法应根据需要进行处理.
是否显示小红点的判断根据项目的不同而不同,例如:
1) 根据数据请求返回的某个字段.
2)根据请求的时间和消息的发布时间.
3)请求的时间是否要存储,存储在哪里合适.
4)多少分钟之内不再重新请求.
这些均可在类似于上文提到的 ActivityUrlService中做处理.返回Bool值有没有新消息,需不需要刷新menuView即可.

7.举例子,笔者是根据请求与消息的发布时间以及时间间隔判断的,略作参考

// userInfo 存储上一次请求返回的发布时间
let activity_lastReleaseDate_key = "activity_lastReleaseDate_key"

static let shared = ActivityUrlService()
let userDefuaults = UserDefaults.standard
fileprivate var lastRequestDate: Date? //上一次请求的时间

// 闭包返回给控制器
func updateActivity(_ completionHandler: @escaping (Bool) -> Void) {
    
    updateActivityRequest { (finish) in
        
        completionHandler(finish)
    }
}

 // 数据请求 闭包返回是否有小红点
 fileprivate func updateActivityRequest(_ completionHandler: @escaping (Bool) -> Void) {
    
    WebService.request("/api/promotions/latest").validate().responseData { (response) in

        guard response.result.isSuccess, let data = response.result.value else {
            completionHandler(false)
            return
        }
        guard let dic = JSON(data: data).dictionary else {
            completionHandler(false)
            return
        }
        guard let dataDic = dic["data"]?.dictionary else {
            completionHandler(false)
            return
        }
        
        guard let promotion = dataDic["promotion"]?.dictionary else {
            completionHandler(false)
            return
        }
        guard let releaseDate = promotion["releaseDate"]?.string else {
            completionHandler(false)
            return
        }
        // 判断几个重要的时间
        let completion = self.judgeRequestAndRelease(with: releaseDate)
        completionHandler(completion)
    }
}

/// 比较活动的请求和发布时间
///
/// - Parameter releaseDateStr: 本次请求返回的发布时间
fileprivate func judgeRequestAndRelease(with releaseDateStr: String) -> Bool {
    if let last = lastRequestDate {
         //有上一次请求的时间
        let minute = Date().timeIntervalSince(last)/60

        if minute > 10 { 
           //与当前时间对比,若大于10分钟,则重新请求
            lastRequestDate = Date()
            guard let value = userDefuaults.object(forKey: activity_lastReleaseDate_key) as? String else {
                return false
            }
            guard let lastReleaseStamp = Int(value) else {
                return false
            }
            // 自己写的一个方法,返回Date
            let releasedate = DateConversion.shared.dateStringSwitchToDate(with: releaseDateStr, dateFormate: "yyyy-MM-dd HH:mm:ss")
            // 返回时间戳
            let releaseStamp = DateConversion.shared.dateSwitchToStamp(with: releasedate)
            guard let currentReleaseStamp = Int(releaseStamp) else {
                return false
            }
            if currentReleaseStamp > lastReleaseStamp {
                userDefuaults.set(currentReleaseStamp, forKey: activity_lastReleaseDate_key)
                return true
            } else {
                return false
            }
        }
        return false
        
    } else {
        // 没有第一次请求的时间,则第一次请求数据
        firstRequest(with: releaseDateStr)
        return true
    }
}

//首次请求
fileprivate func firstRequest(with releaseDateStr: String) {
    lastRequestDate = Date() //上一次请求时间当前时间
    let releasedate = DateConversion.shared.dateStringSwitchToDate(with: releaseDateStr, dateFormate: "yyyy-MM-dd HH:mm:ss")
    let releaseStamp = DateConversion.shared.dateSwitchToStamp(with: releasedate)
    userDefuaults.set(releaseStamp, forKey: activity_lastReleaseDate_key)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容