iOS-关于链表与历史追溯功能的探讨

众所周知,在面试的时候Runtime、数据结构等等都是面试常问的题目,当然,不少朋友会吐槽面试问题常常脱离实际开发,毕竟那些只有一两人两三人组成的小开发组的项目,整个项目往往只有一两次使用到Runtime的机会,甚至有的项目根本就是从头到尾都没用到过。
当然嘛,就算没用到过,但这方面的知识储备还是需要的,不然面试根本就没啥问题好问,全都是UI层次、业务逻辑的问题,别说面试官,面试者都可能会觉得蛋疼的紧吧?
话题扯远了,言归正传,Runtime还有使用到的机会,那么链表这一概念在移动端开发到底会在什么时候被应用到呢?在厕所中沉思的时候我突然想到这个问题,移动端开发到底有什么功能开发会使用到链表的概念,非链表不能,又或者是使用链表会达到最好效果的呢?
身体放空的同时心灵也得到了升华,我终于想到了一个可能性,那就是Web的历史追溯。
在PC使用谷歌浏览器的时候在一次偶然的巧合下我发现了谷歌浏览器让人眼前一亮的功能,具体模拟使用场景是这样的:

1、松鼠症的我堆积了大量的标签页,其中一些标签页是有下一级的Web链接及上一级的Web链接
2、不小心错误关闭了其中一个标签页,那个标签页是我找了很久的资料,标签页的前进跟后退都是同一个网站的重要资料
3、通过谷歌浏览器的打开最近关闭的标签页我重新打开了标签页,并且,上一级的Web链接以及下一级的Web链接依然存在。

这是很棒的功能,让人眼前一亮,而遗憾的是手机上的浏览器大多没有这样的功能(至少我日常使用的都没见到),那么作为一个开发者,我们要如何将这样的功能挪移到手机上呢?
我想到了链表,Web一级一级的连接方式无疑是链表的最佳诠释,当页面被关闭时将完成的链表保存下来,当页面被从新打开时从链表读取数据似乎是很好的解决办法。
为了佐证我的想法,首先先写一个Web Demo.

        let web = WKWebView(frame: CGRect.zero)
        web.navigationDelegate = self
        view.addSubview(web)
class ViewController: UIViewController,WKNavigationDelegate {
    ......
//实现代理方法来获取URL地址,亦可通过监听Loading状态,这些都随便,需要注意的是,度娘会做相关网址转译,这些转译需要根据自己选是否筛选。
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        print(navigationAction.request.url?.absoluteString)
        decisionHandler(WKNavigationActionPolicy.allow)
    }
}

   func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        print(navigationResponse.response.url)
        decisionHandler(WKNavigationResponsePolicy.allow)
        
    }

   func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print(webView.url)
    }

public class ListNode {
//商业项目中我们不应该直接添加URLString,而是一个完整的数据模型,不过在此,我们简化一些操作。
    public var url: String
    public var next: ListNode?
    public init(_ url: String) {
        self.url = url
        self.next = nil
    }
}
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let node = ListNode(webView.url!.absoluteString )
        if let l = list {
            node.next = l
            list = node
        } else {
            list = node
        }
    }


如此,我们便获得了一个完整的链表,里面记录了标签页从新建之始记录的所有URL地址,并且,这是从尾到头的,若想要进行历史回溯便一层一层地将list.next中的url数据取出即可。

   func goBack() {
        let urlString = list?.next?.url ?? ""
        list = list?.next
        let request = URLRequest(url: URL(string: urlString)!)
        web?.load(request)
    }

但是这样在实际使用上是会出很大问题的,首先是每次历史回溯都将数据替代了,要是想回到原先的界面就只能使用WebView的goBack API,原本是最尾末的页面但因为关闭而重新打开却成了最初始的,这样很容易造成业务逻辑上的混乱。
其二,如果是同时具有上一级以及下一级URL(即不处于链表的首末尾)的Web,这样的逻辑并不能使得Web goForward,功能并没有完全实现。
除此之外还有等等问题在实际项目会有很多不同之处,需要一一调整。

在此,我认为可以这么设计,一个链表不够就再加一个,两个链表分别代表当前页面之前的数据以及这个页面之后的数据,当前页面可以选择性地放在两个链表的首末。

        //当页面处于正常状态而非是被打开的最近关闭标签页时按正常流程走
        //当页面处于正常状态而调用webView的goBack API 及 goForward API时改动双链表
        //当调用goBack API 时,将goBack之前的页面从before List删除,添加到 after List,并成为after List的 First Node.
        //当调用goForward API 时,逆转而使
        //如此,确保双链表模拟的完整链表的正确性以及当前页面的url在完整链表中位置的正确性
        //当页面是最近被关闭的标签页时检查页面的双链表,确定页面的url在链表中的位置
        //根据链表是否有值判断当前页面是否存在上一级的页面或者下一级的页面
        //同样的,根据调用的API对双链表做出修正。
    ......
    //双链表
    var before:ListNode?  //当前网页之前的链表数据,当前网页处于链表头部
    var after:ListNode?   //当前网页之后的链表数据

//监听按钮点击以挪移链表
@IBAction func goBack(_ sender: AnyObject) {
   if web!.canGoBack {
            if let b = before {
                let node = b
                before = b.next
                if let a = after {
                    node.next = a
                }
                after = node
            }
        } else {
            
        }
    }
@IBAction func goForward(_ sender: AnyObject) {
       if web!.canGoForward {
            if let a = after {
                let node = a
                after = a.next
                if let b = before {
                    node.next = b
                }
                before = node
            }
        } else {
            
        }
    }

如此在正常状态不断挪移链表,在最近关闭的标签页中获取数据时方能获取到正确数据。
目前正在写一个完整的Web项目以正确模拟商业项目如此使用可能会出现的问题,所以本文仅是探讨如此的功能实现,不能避免逻辑上可能存在的问题。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,957评论 25 707
  • (10/100) 此文章引用的部分均出自目标达成专家、幸福进化俱乐部创始人,易仁永澄老师公众号。自我管理系统重启初...
    xiaolubobo阅读 168评论 0 0
  • 什么是Thunk函数 本段内容无耻抄袭自阮一峰的《ESMAScript 6 入门》中对Thunk函数的介绍 Thu...
    pure懒人阅读 1,126评论 0 2
  • UITableView中将分割线样式改为None tableView.separatorStyle = UITab...
    张群阅读 2,551评论 1 6
  • 第23周话题,让我们思考人生对与错。 个人觉得,人生没有对错,每一种选择都代表一种不同的人生,选择的适合与否是来自...
    Natsuka阅读 253评论 2 2