作者:劉小壯
前段時間由於剛入職新公司,開發公司新版本很忙(公司招人肯定是因為忙才找人....),有一段時間沒有寫博客了。
最近正好用到了Newsstand的技術,這方面參考資料比較少,而且水平也參差不齊,我這裡把我做項目的時候用到的技術和開發流程寫在這裡,希望大家多多指出其中存在的問題,如果能幫到你那就最好了。
簡介
在iOS 5之後蘋果推出了一種輕應用,叫做Newsstand應用,主要都是報刊雜志,在系統自帶的Newsstand應用中,Newsstand應用都是一些輕的展示類雜志應用。
iBook和Newsstand看起來非常類似,但是是不一樣的,Newsstand是我們自己制作的可交互的應用,交互方式是由我們自己決定的,內部雜志的下載也是由我們自己決定的。iBook是一個純粹的文本展示,交互方式以及下載都是由iBook決定的,而且iBook類似於app Store一樣是一個購買商城,可以下載不同的圖書。
Newsstand就是將之前在系統桌面的應用放在了報刊文件夾中,之前桌面圖標以報刊封面的形式來進行展示,其實內部的代碼實現大多還是一樣的。
注意:在iOS 9之後,蘋果取消了Newsstand這個系統的報刊應用,取而代之的是用一個桌面分組文件夾來存放Newsstand應用。
Newsstand應用開發
開發雜志應用首先要設置CFBundleIcons和UINewsstandApp。
報刊雜志 App 的 Info.plist 必須包含“Application presents content in Newsstand”字段,需要設置為YES,在項目中源代碼是:UINewsstandApp = true,實際上我們直接敲UINewsstandApp就可以,系統會將key自動變為下面的key名。
和UINewsstandApp是一碼事
然後我們需要設置應用圖標,源代碼叫做UINewsstandIcon,顯示給我們的是Icon files(iOS 5),我們可以
關於裡面圖標詳細的設置,請參考官方文檔:https://developer.apple.com/library/ios/qa/qa1686/_index.html
NewsstandKit框架
蘋果這個框架由於比較“年輕”,提供的接口也比較簡單,具體的操作內部都封裝好了。這個框架只能是Newsstand類的應用,其他應用程序不能使用。
最後一個類沒什麼卵用
在這個框架中主要有三個類
NKLibrary用來管理Newsstand的內容,管理的方式是通過管理NKIssue對象來進行管理的
NKLibrary是一個單例對象,管理所有的NSIssue對象,可以獲取當前正在下載的issue、所以的issue、以及添加刪除issue等。用戶正在閱讀的issue需要設置給NKLibrary對象的currentlyReadingIssue屬性,以防止閱讀過程中內存被清理。
NKIssue雜志每一期的抽象對象
NKIssue沒有單獨的實例化方法,雖然繼承自NSObject基類,但是連NSObject類的alloc方法也不能用,如果使用了NSObject方法之後創建的對象也是nil,必須通過NSLibrary類進行創建和管理。
NKIssue可以通過states屬性來獲取當前刊物的狀態,主要分為三個狀態:None-沒有可用的刊物, Downloading-下載中,Available-可用。
NKAssetDownload用於下載雜志和管理下載中的雜志,可以通過NewsstandKit在後台進行下載
我們可以使用NKAssetDownload類對雜志進行下載,下載的時候非常簡單,只需要調用downloadWithDelegate:方法來設置代理之後,然後通過NSURLConnectionDownloadDelegate方法來獲取到下載進度、斷點續傳、下載完的二進制文件路徑等數據。關於下載的數據格式,可以是HTML、js文件、圖片等都可以,也可以將所有文件打包為ZIP文件來下載,只需要在本地通過和服務器約定好的格式進行解析就可以。
代碼實現
我發現代碼發在博客中太挫,所以直接截圖了????
下載代碼
代理方法回調
代理方法
NKAssetDownload類負責issue的下載,這個類實現了NSURLConnectionDownloadDelegate代理方法,我們可以通過這個協議中的代理方法很容易的獲取下載狀態。
connection:didWriteData:totalBytesWritten:expectedTotalBytes 開啟新的下載時執行這個代理方法。
connectionDidResumeDownloading:totalBytesWritten:expectedTotalBytes: 斷點續傳時調用這個代理方法。
connectionDidFinishDownloading:destinationURL 下載完畢之後調用這個方法,我們可以通過這個代理方法獲取到下載完畢的文件路徑。
注意:我們也可以不使用這個類進行下載,也可以使用其他類進行下載。但是這樣就不能在後台進行下載,而且需要自己管理issue。
下載完畢
一般我們的一個issue下載完畢之後,大多數下載完畢的都是一個壓縮包,我們需要將壓縮包解壓,然後放在另一個目錄中。(友情提示:做Newsstand的下載時,一般每一個issue都是一個壓縮包,下載完畢之後再解壓,這樣也方便管理)
我們一般都是通過NSFileManager類對文件進行管理,並且通過一些第三方解壓庫來對Zip壓縮包進行解壓。
應用程序狀態
經過我的測試:我們的程序退出到後台之後,系統會繼續幫我們下載,而且程序會一直在後台運行。我們將程序退出之後,由於NewsstandKit框架是系統級別的框架,程序下載並不會終止,而是在程序被結束進程的情況下繼續下載。
也可以理解為一旦一個下載任務開啟之後,無論當前應用是前台運行、後台運行、終止的狀態,應用程序都會繼續下載。所以盡量不要使用其他下載方式!
但是,我們的應用程序無論是在前台還是後台,都是出於運行狀態的。如果應用程序被推出之後,雖然下載還是繼續的,但是應用程序的app delegate已經不存在了,只是系統級別的下載還在繼續。所以我們如果想要在下載完之後做一些操作就比較麻煩了,需要在background狀態下重新將當前app啟動,然後會執行application:didFinishLaunchingWithOptions:代理方法,我們在這個代理方法中進行操作就可以了。
後台下載
我們如果想要實現後台下載最好使用NewsstandKit框架,由於NewsstandKit屬於系統級別的框架,所以如果應用程序退出到後台,在後台下載也是由系統決定的,如果想要實現後台下載最好使用NewsstandKit,框架已經實現了後台下載的邏輯,而且UIBackgroundModes有一種狀態就是Newsstand。
我們在項目中主要使用NKAssetDownload進行下載,通過遵循NSURLConnectionDownloadDelegate代理來獲得下載進度、是否完成、以及實現斷點續傳的功能。
注意:我們如果想要後台下載,在上線之後每24小時只能執行一次,其他超出的下載都是無效的。在測試階段我們可以通過下面的代碼來獲取更多次的後台下載機會,但是上線之後不要用。後台下載是系統級別的,系統只會在WiFi環境下進行後台下載,其他網絡環境下也是無效的。
[[NSUserDefaultsstandardUserDefaults]setBool:YESforKey:@"NKDontThrottleNewsstandContentNotifications"]
通過通知來實現更新封面和下載
首先需要注冊類型為UIRemoteNotificationTypeNewsstandContentAvailability遠程通知。
每次有新雜志發布後,由服務器發通知,通知中可以包含封面圖片的地址,下載圖片後,使用[[UIApplictaion sharedApplication] setNewsstandIconImage:XXXX]方法更新封面
邏輯可以寫在didFinishLaunchingWithOptions和didreceiveRemoteNotification方法中,這樣創建的通知從服務器接收到消息之後可以直接通過NewsstandKit在後台進行下載,也就是通過通知推送過來的下載任務,可以直接下載,下載完畢之後然後更新雜志封面。
當發送一條更新Newsstand的push消息時,和一般的push消息有相同的語法,不過稍微不同的是包含一個key為content-available包含的值為1:
多了一個字段