在上篇文章中稼虎,我介紹了在iPhone桌面生成快捷方式的原理,并介紹了最簡單的實現(xiàn)方式选调,網(wǎng)絡(luò)依賴嚴重夹供、用戶體驗差、開發(fā)簡單仁堪,這是我對這種方式的看法哮洽。用戶體驗差必然會導(dǎo)致我們的產(chǎn)品被用戶罵,作為開發(fā)者弦聂,我們自然就背鍋了鸟辅,這怎么能忍?但是在我們沒有實力在APP中搭建HTTPServer之前莺葫,我們只能盡力在這種方式上進行優(yōu)化匪凉,讓用戶體驗不那么差。
在這篇文章中捺檬,我會介紹一種優(yōu)化方式再层,希望能幫到你們。
在閱讀這篇文章之前,我希望你們知道什么是data url聂受,如果不知道蒿秦,那就去百度吧。
上篇文章中我們只有一個網(wǎng)頁蛋济,在這篇文章中渤早,我們會寫兩個網(wǎng)頁,一個是用來過渡和解析數(shù)據(jù)的網(wǎng)頁瘫俊,另外一個是正式的網(wǎng)頁鹊杖,這個網(wǎng)頁的所有的內(nèi)容會使用到data url。優(yōu)化有兩種方式扛芽,一種是將數(shù)據(jù)解析集成在APP中骂蓖,一種是將數(shù)據(jù)解析放在服務(wù)器上的網(wǎng)頁中進行,本文只介紹第一種川尖,因為兩種方式的實現(xiàn)過程也差不多登下,而且我是APP的開發(fā)者,對APP的開發(fā)語言更熟悉叮喳,所以就選擇了第一種進行介紹被芳,實際開發(fā)中可就不一定使用第一種哦~~~
1. 創(chuàng)建過渡網(wǎng)頁,放在服務(wù)器上的那個
<!DOCTYPE html>
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta content="text/html charset=UTF-8" http-equiv="Content-Type" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<title></title>
</head>
<body>
</body>
<script>
<!-- 這里面是本頁面最核心的馍悟,可以根據(jù)需要在此處設(shè)置圖片畔濒、標題等,如果使用第二種方式锣咒,可以在此處調(diào)用數(shù)據(jù)解析的方法侵状,然后進行頁面替換 -->
var url = location.search;
url = url.replace("?dataurl=", "") <!-- 這里被替換掉的字符串是針對APP中設(shè)置的,使用空字符串替換之后毅整,剩余的就是快捷方式展示頁的data url字符串了 -->
window.location.replace(url)
</script>
</html>
2. 創(chuàng)建快捷方式的展示網(wǎng)頁
這個網(wǎng)頁文件中的內(nèi)容將被讀取并進行解析趣兄,如果不想在數(shù)據(jù)解析中多寫很多代碼,那就不要在這個文件中寫不需要的東西悼嫉,例如:注釋等艇潭。如果寫了,那在數(shù)據(jù)解析的時候就得把不需要的東西過濾掉戏蔑,否則可能會出問題
<!DOCTYPE html>
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta content="text/html charset=UTF-8" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<link rel="apple-touch-icon" href="ZHMFIconImageString">
<title>ZHMFTitle</title>
</head>
<body>
<a href="ZHMFOperation" id="qbt" style="display:none"></a>
<span id="msg"></span>
</body>
<script>
if (window.navigator.standalone == true) {
document.getElementById("qbt").click();
} else {
document.getElementById("msg").innerHTML='<center><img width=400 src="ZHMFImageString" /></center>';
}
</script>
</html>
3. 創(chuàng)建一個Shortcut類蹋凝,用來封裝數(shù)據(jù)解析
直接把整個類的代碼貼出來吧,里面有注釋辛臊,應(yīng)該還是很容易看懂的
import UIKit
class Shortcut: NSObject {
override init() {
super.init()
}
convenience init(_ icon: UIImage?, _ title: String?) {
self.init()
self.iconImage = icon
self.title = title ?? ""
}
var iconImage: UIImage? = nil
/// 快捷方式的默認標題
var title = ""
/// 網(wǎng)頁打開APP的scheme
var operation = ""
/// 調(diào)用此方法開始數(shù)據(jù)解析仙粱,并跳轉(zhuǎn)到Safari
func open() {
let iconStr = image2String(iconImage)
let imageStr = "http://192.168.9.224/images/image_3.jpg"
let urlStr = "http://192.168.9.224/shortcut.html?dataurl="
guard let shortcutStr = creatShortcutString(iconStr, imageStr).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
let url = URL.init(string: "\(urlStr)\(shortcutStr)"),
UIApplication.shared.canOpenURL(url) else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
/// 創(chuàng)建快捷方式Data URL的字符串,這里面的操作也可以放在過渡網(wǎng)頁中使用JavaScript操作彻舰,以便隨時修改
private func creatShortcutString(_ iconStr: String, _ imageStr: String) -> String {
var str = readHtmlContent()
str = str.replacingOccurrences(of: "ZHMFIconImageString", with: iconStr)
str = str.replacingOccurrences(of: "ZHMFTitle", with: title)
str = str.replacingOccurrences(of: "ZHMFOperation", with: operation)
str = str.replacingOccurrences(of: "ZHMFImageString", with: imageStr)
return str
}
/// 讀取網(wǎng)頁內(nèi)容
private func readHtmlContent() -> String {
guard let path = Bundle.main.path(forResource: "content", ofType: "html"),
let data = FileManager.default.contents(atPath: path),
let content = String.init(data: data, encoding: String.Encoding.utf8) else {
return ""
}
var htmlStr = "data:text/html;charset=utf-8,"
htmlStr.append(content)
return htmlStr
}
/// 將圖片轉(zhuǎn)為字符串
private func image2String(_ img: UIImage?) -> String {
guard let image = img,
let data = UIImageJPEGRepresentation(image, 0.1) else {
return ""
}
/// 注意下面base64編碼的選項伐割,是endLineWithLineFeed候味,我在此處糾結(jié)了很長時間,瀏覽器解析一直報錯隔心,最終換成這個之后搞定
let str = data.base64EncodedString(options: Data.Base64EncodingOptions.endLineWithLineFeed)
return "data:image/jpeg;base64," + str
}
}
4. 在需要創(chuàng)建快捷方式的地方進行調(diào)用
let obj = Shortcut()
obj.iconImage = UIImage.init(named: "icon.jpg")
obj.title = "快捷方式"
obj.operation = "shortcut://zhmf.com"
obj.open()
5. 操作原理
這種方式是在用戶點擊“放到桌面”按鈕時打開一個過渡網(wǎng)頁白群,url后面跟一個參數(shù)dataurl,參數(shù)的值就是快捷方式的data url字符串硬霍,在過渡網(wǎng)頁中會截取到這個字符串帜慢,并替換當前頁面,當然如果使用文章開頭說的第二種方式唯卖,那么就不需要這個參數(shù)了粱玲,因為這個參數(shù)會在過渡頁面使用JavaScript生成。
Safari通過data url打開頁面后拜轨,會引導(dǎo)用戶點擊下方的按鈕 “添加到主屏幕”抽减,此時地址欄就是data url。添加到主屏幕這個功能會將當前頁面的url和圖標保存到本地橄碾,由于本頁面使用的是data url卵沉,頁面所有的內(nèi)容都存放在url中,所以法牲,在點擊快捷圖標時史汗,不需要網(wǎng)絡(luò)也可以執(zhí)行url里面包含的所有代碼,這就達到了生成快捷圖標后無需網(wǎng)絡(luò)也可以通過快捷方式打開APP中某項功能拒垃,減少了對網(wǎng)絡(luò)的依賴停撞,提升了用戶體驗。
6. 踩坑
在開始優(yōu)化的時候恶复,我就認為這個頁面有兩個圖片怜森,一個是桌面圖標,一個是頁面圖片谤牡。所以我在數(shù)據(jù)解析的時候,將兩個圖片全部進行base64編碼姥宝,放到url中傳到過渡頁面翅萤,結(jié)果,頁面提示url太長腊满。
其實套么,HTTP協(xié)議對url的長度是沒有限制的,但是碳蛋,瀏覽器和服務(wù)器為了提升性能胚泌,會對url的長度進行限制,Safari的長度據(jù)說超過80000肃弟,Apache的長度限制好像是8000+玷室,IIS大概不到1600+零蓉,具體的可以去百度搜索一下。
按照這個長度來說穷缤,放一個小圖片是沒有問題的敌蜂,也就是圖標是可以通過編碼放進去的,但是引導(dǎo)圖就不行了津肛,引導(dǎo)圖太大章喉,雖然我壓縮之后沒有超過Safari的限制,但遠遠超過Apache的限制身坐,也就是說把引導(dǎo)圖也進行編碼放在里面是不太現(xiàn)實的秸脱。
受到同事的提醒,我恍然大悟部蛇,添加桌面圖標基本上只是一次性的操作摊唇,用戶放到桌面的那時有網(wǎng)絡(luò)就行了,放到桌面后搪花,很少有人經(jīng)常重復(fù)放到桌面遏片,所以,只需要保證快捷方式能斷網(wǎng)執(zhí)行即可撮竿,引導(dǎo)頁中的圖片完全可以放到服務(wù)器吮便,data url里面只需要放一個圖片的地址即可,經(jīng)過測試幢踏,完全可行髓需。如果用戶沒有網(wǎng)絡(luò),那就打不開引導(dǎo)頁所在的頁面房蝉,引導(dǎo)圖來自哪兒都沒有用僚匆,如果用戶有網(wǎng)絡(luò),那就不用擔心圖片的問題搭幻,除非是弱網(wǎng)咧擂,在弱網(wǎng)情況下,用戶是可以添加的檀蹋,但是看不到引導(dǎo)圖松申。
當然,如果想在針對弱網(wǎng)也進行優(yōu)化俯逾,可以將引導(dǎo)頁使用代碼進行編輯放到data url中贸桶,再搭配小圖(或者直接用代碼畫圖)的形式,也能提升用戶體驗桌肴。
總結(jié)
作為APP的開發(fā)者皇筛,一旦APP的體驗不好,那么用戶首先罵的人估計就是我們(雖然有時候產(chǎn)品的設(shè)計就是如此坠七,但我們依然背鍋)水醋,或許旗笔,殺我們祭天的心都會有,為了保住小命离例,在代碼的海洋中再漂幾年换团,還是得花費點心思提升用戶體驗。