天天看點

watchOS中進行異步圖檔加載和緩存的政策

        iwatch是智能手表的一次革命。iwatch的應用也将會越來越多,基于watch的一些特點,watchos的開發者需要更加精益的把握watch的ui和性能。運用watchos自帶的緩存體系進行資料的緩存,是增強使用者體驗度的一種方式,這篇部落格,介紹在watchos中進行異步加載圖檔和緩存的方法,願與志同道合的朋友,一起交流。

        在進行設計之前,我們應該先了解,watchos的緩存容量為最大20m,因為有限,我們更應該認真的利用每一份空間,是以,緩存我們不僅可以存,在即将裝滿的時候,我們還要有辦法從緩存中删去一些東西,讓出空間,那麼應該删除哪些東西了,我們應該都可以想到,當然是舊的了,把最早的緩存删掉,是以,在存的時候,我們要設計一種規則,可以儲存存入的時間,并且不影響我尋找這個緩存檔案。我的方法是通過格式化的命名:

<a href="http://my.oschina.net/u/2340880/blog/521527#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code>//這是一個規範緩存命名的方法</code>

<code>func checkstring(str:nsstring)-&gt;nsstring{</code>

<code>    </code><code>let result:nsmutablestring=nsmutablestring()</code>

<code>    </code><code>//先将所有的非字母和數字剔除掉</code>

<code>    </code><code>for</code> <code>var i=0 ; i&lt;str.length ; i++ {</code>

<code>        </code><code>if</code> <code>(str.characteratindex(i)&gt;=48&amp;&amp;str.characteratindex(i)&lt;=57)||(str.characteratindex(i)&gt;=65&amp;&amp;str.characteratindex(i)&lt;=90)||(str.characteratindex(i)&gt;=97&amp;&amp;str.characteratindex(i)&lt;=122){</code>

<code>            </code><code>result.appendformat(</code><code>"%c"</code><code>,str.characteratindex(i))</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

<code>    </code><code>//拼接上目前時間戳</code>

<code>    </code><code>let date:double = nsdate().timeintervalsince1970</code>

<code>    </code><code>result.appendformat(</code><code>"?%.0f"</code><code>,date)</code>

<code>    </code><code>return</code> <code>result</code>

<code>}</code>

通過?符号将名稱和時間戳進行了拼接。

        這一步是如下的設計思路:通過圖檔url從緩存的路徑中進行尋找,如果有,直接取出圖檔,如果沒有,開啟一個線程進行異步加載,完成後重新整理主線程ui并将圖檔檔案規範命名後進行緩存:

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

<code>//進行存取緩存的操作</code>

<code>//取出watchos的緩存目錄</code>

<code>let imagedic:nsdictionary = wkinterfacedevice().cachedimages as nsdictionary</code>

<code>    </code><code>//取圖檔存儲的名稱</code>

<code>    </code><code>let imageurl:nsmutablestring=nsmutablestring()</code>

<code>        </code><code>//這裡的url是外界傳進來的圖檔位址url,進行去掉特殊字元</code>

<code>        </code><code>for</code> <code>var i=0 ; i&lt;url?.length ; i++ {</code>

<code>            </code><code>if</code> <code>(url?.characteratindex(i)&gt;=48&amp;&amp;url?.characteratindex(i)&lt;=57)||(url?.characteratindex(i)&gt;=65&amp;&amp;url?.characteratindex(i)&lt;=90)||(url?.characteratindex(i)&gt;=97&amp;&amp;url?.characteratindex(i)&lt;=122){</code>

<code>                </code><code>imageurl.appendformat(</code><code>"%c"</code><code>,(url?.characteratindex(i))!)</code>

<code>             </code><code>}</code>

<code>        </code><code>//查找緩存中是否有圖檔</code>

<code>        </code><code>//周遊watchos的緩存目錄</code>

<code>        </code><code>for</code> <code>var i=0 ; i&lt;imagedic.allkeys.count ; i++ {</code>

<code>           </code><code>//通過規定好的?進行分割</code>

<code>           </code><code>let str:nsarray =  imagedic.allkeys[i].componentsseparatedbystring(</code><code>"?"</code><code>)</code>

<code>                </code><code>if</code> <code>str[0].isequaltostring(imageurl as string) {</code>

<code>                    </code><code>//找到圖檔 view是要設定的interfaceimage</code>

<code>                    </code><code>view.setimagenamed(imagedic.allkeys[i] as? string)</code>

<code>                    </code><code>return</code><code>;</code>

<code>                </code><code>}</code>

<code>            </code><code>}</code>

<code>            </code><code>//設定預設圖檔 這裡是外界傳進來的預設圖檔,如果需要下載下傳,先設定預設圖檔</code>

<code>            </code><code>if</code> <code>defaultimage != nil {</code>

<code>                </code><code>view.setimagenamed(defaultimage as? string)</code>

<code>            </code> 

<code>            </code><code>//進行下載下傳和存儲</code>

<code>            </code><code>let dispath = dispatch_get_global_queue(dispatch_queue_priority_high, 0)</code>

<code>            </code><code>//在新的線程中下載下傳</code>

<code>            </code><code>dispatch_async(dispath, { () -&gt; void in</code>

<code>                </code><code>let imgurl:nsurl = nsurl(string: url as! string)!</code>

<code>                </code><code>let imagedata:nsdata? = nsdata(contentsofurl: imgurl)</code>

<code>                </code><code>if</code> <code>imagedata != nil {</code>

<code>                    </code><code>//主線程中重新整理</code>

<code>                    </code><code>dispatch_async(dispatch_get_main_queue(), { () -&gt; void in</code>

<code>                        </code><code>view.setimagedata(imagedata!)</code>

<code>                    </code><code>})</code>

<code>                    </code><code>//寫緩存  如果緩存滿了 就删掉時間戳最早的一張緩存</code>

<code>                    </code><code>//這個方法會傳回bool值,判斷是否存入成功</code>

<code>                    </code><code>while</code> <code>!wkinterfacedevice().addcachedimagewithdata(imagedata!, name: checkstring(url!) as string) {</code>

<code>                        </code><code>//如果存入失敗,删去時間戳最早的緩存</code>

<code>                        </code><code>var temp:nsstring?</code>

<code>                        </code><code>//儲存最早的緩存名稱</code>

<code>                        </code><code>var result:nsstring?</code>

<code>                        </code><code>for</code> <code>var i=0 ; i&lt;imagedic.allkeys.count ; i++ {</code>

<code>                            </code><code>let str:nsarray =  imagedic.allkeys[i].componentsseparatedbystring(</code><code>"?"</code><code>)</code>

<code>                            </code><code>if</code> <code>temp == nil {</code>

<code>                                </code><code>temp = str[1] as? nsstring</code>

<code>                                </code><code>result = imagedic.allkeys[i] as! string</code>

<code>                                </code><code>break</code>

<code>                            </code><code>}</code>

<code>                            </code><code>if</code> <code>str[1].doublevalue &lt; temp?.doublevalue {</code>

<code>                                </code><code>//找到更早的緩存</code>

<code>                        </code><code>}</code>

<code>                        </code><code>//删掉緩存</code>

<code>                        </code><code>wkinterfacedevice().removecachedimagewithname(result as! string)</code>

<code>                    </code><code>}</code>

<code>            </code><code>})</code>

上面的代碼和注釋,已經介紹了所有的思路,有錯誤之處或者更好的方式,還望多多指點。