寫作時間:2016-02-14 22:13
動態(tài)輸入法 iOS 版 v2.0.1 已經(jīng)于昨天提交審核了瑟蜈,這個浩大的工程算是告一段落棍苹。為了那些心力憔悴的日日夜夜,留下一些回憶吧。
感謝我的老婆和女兒的支持笆檀,沒有老婆辛苦的帶女兒橄维,沒有女兒獨自玩耍尺铣,我不會有足夠的時間來完成這些工作。
開發(fā)歷程:
2015年5月:啟動争舞。
2015年6月:注冊了一個開發(fā)者賬號凛忿。6月~8月間,出差1個月竞川。
2015年9月2日:發(fā)布1.0版店溢。
2015年9月17日:發(fā)布1.0.3版。更正若干BUG委乌。
2015年10月25日:發(fā)布1.2版床牧,使用了表格UI,添加了長按功能遭贸,添加了內(nèi)支付戈咳,添加了按鍵提示。
2015年11月21日:發(fā)布1.3.1版,使用NSDictionary查找筆畫著蛙,添加了快捷筆畫删铃,添加了字母顏文字鍵盤等。
2016年1月22日:發(fā)布1.3.2版踏堡,更正了鍵盤無法彈出的BUG猎唁。
2015年5月的一天,得知iOS 8開始支持第三方輸入法顷蟆,上網(wǎng)查了查胖秒,發(fā)現(xiàn)有教程,于是就試著做一下慕的。正好也是老婆有MAC電腦阎肝。開發(fā)iOS APP 需要用Xcode,教程語言是SWIFT肮街。興奮的去ZBB買了本SWIFT的書风题。其實這本書沒有太多的用處,大部分的問題都是網(wǎng)絡(luò)解決嫉父。有書的唯一好處就是沛硅,有時候可以在手邊應(yīng)急。
在1.0版發(fā)布之前绕辖,主要的工作在于:(1)最早的問題在于摇肌,怎么設(shè)計鍵盤按鍵,按鍵的排列都是依靠Constraints來限定的仪际,需要自己編排围小。而在Android,這些都不用管树碱,只要在xml文件里填寫按鍵上的字符就可以生成鍵盤了肯适。教程代碼里的按鍵約束是循環(huán)引用的,不好成榜,我改成了根據(jù)按鍵數(shù)量來計算尺寸框舔。這里涉及的都是UI的問題,例如赎婚,按鍵上的文字刘绣,怎么改顏色,字體挣输,背景色纬凤,邊框等等。在Container的UI上歧焦,控件的位置經(jīng)常錯亂移斩,是一個很大的困擾肚医,默認(rèn)的UI不能VScrow绢馍,總之克服了很多困難做出一個簡單的UI向瓷。(2)然后,要解決按鍵的滑動舰涌、長按猖任、滑動和長按。iOS的機(jī)制和Android完全不同瓷耙。在Android里朱躺,只有 onPress 和 onLongPress,為了判斷按鍵的滑動搁痛,可費了不少腦筋长搀。在iOS里,判斷按鍵滑動很簡單鸡典,只要在保持按鍵按下而沒有抬起的過程中加一個計數(shù)器就可以了源请,而判斷按鍵的長按,比較復(fù)雜彻况,需要為父視圖添加一個長按的observer谁尸,還要自定義長按觸發(fā)時間,默認(rèn)為0.8秒好像纽甘。Android里的長按沒有設(shè)置觸發(fā)時間的方法良蛮。長按的功能直到10月才完成。(3)AES加密和解密:在CSDN找到了示例代碼悍赢,并且可用决瞳,不過是ObjectC的,需要加入一個bridge文件橋接OC和SWIFT左权。(4)代碼的移植:把主要的算法從java轉(zhuǎn)寫為SWIFT瞒斩,并盡量保持與java相同的結(jié)構(gòu)。SWIFT對字符串缺乏很多常用的方法涮总,例如取子串胸囱,替換等等,都需要自己寫瀑梗。其中烹笔,String類型有From(to end)和(from start)To兩種方法,但是取中段還是要自己實現(xiàn)抛丽,不太方便效率也不高谤职。(5)軟件參數(shù)設(shè)置:這是一個大坑,很久才爬出來亿鲜。原本允蜈,iOS在設(shè)置冤吨、通用、鍵盤里饶套,為第三方輸入法保留了一個參數(shù)設(shè)置界面漩蟆,然而怎么都不起作用,許久之后才在stackoverflow查到妓蛮,這是iOS的一個BUG怠李。然后,考慮把參數(shù)放置在Container的設(shè)置里面蛤克,但是這里參數(shù)的改變捺癞,不能通知Container,還得讓Container設(shè)置一個監(jiān)聽构挤,太麻煩了髓介。最后只好吧設(shè)置參數(shù)放置到Container的UI上。傳遞參數(shù)的原理是筋现,Container和Extension共享一個AppGroup唐础,類型還是NSUserDefault,在Container里設(shè)置保存的參數(shù)夫否,Extension立馬就能知道彻犁,很簡便。(6)為APP編寫使用幫助凰慈,這里的幫助非常詳細(xì)汞幢,為此又深入研究了一遍筆順的規(guī)律,這部分內(nèi)容都作為文本放置在Container的設(shè)置里面微谓。(7)iOS的速度比不上普通的Android手機(jī)森篷,在Android里,可以即時地把12筆畫簡化為5筆畫豺型,在iOS里太慢了仲智,于是單獨制作了帶5筆畫的碼表。(8)真機(jī)調(diào)試姻氨,按照百度經(jīng)驗上的步驟配置開發(fā)者賬戶钓辆,也是很麻煩的。(9)補(bǔ)充:最初的文件讀取也是一個起點肴焊,iOS支持UTF-8前联,Windows下處理的碼表格式為Unicode即UTF-16,代碼轉(zhuǎn)換要留心娶眷。(10)橫屏豎屏的判斷似嗤,以及鍵盤高度,不管怎么設(shè)置鍵盤高度届宠,在彈出時總是要閃一下原始尺寸烁落,百試不得其解乘粒,后來才發(fā)現(xiàn)百度,搜狗皆然伤塌,是iOS的BUG灯萍。
1.0.3版的主要工作是,在使用中發(fā)現(xiàn)了若干字的筆畫有誤寸谜。對漢字筆畫表又進(jìn)行了詳查竟稳,又更正了幾十個字的筆畫属桦。
1.2版的主要工作是熊痴,(1)經(jīng)過與用戶的初步的溝通,了解到一般人不習(xí)慣我的按鍵布局聂宾,于是增加了自定義布局果善,由于設(shè)置參數(shù)的增加,原先的UI不便于擴(kuò)展系谐,于是整個更改為TableView巾陕,并擴(kuò)展為多頁面結(jié)構(gòu),對TableCell可以像按鈕一樣添加響應(yīng)函數(shù)纪他,實現(xiàn)了一些功能鄙煤。(2)添加了內(nèi)支付功能,這也是找的示例代碼茶袒,經(jīng)過艱苦的調(diào)試梯刚,湊效了。(3)添加按鍵提示薪寓,這是一個子視圖亡资,在iOS中創(chuàng)建視圖非常的簡便,而在Android中十分的繁瑣向叉,要專門寫一個類锥腻。為了這個按鍵提示,動用PS制作了12種筆畫的典型筆形圖片母谎。按鍵提示也有創(chuàng)新點瘦黑,能提示4種按鍵操作。(4)增加了長按輸入數(shù)字的功能奇唤。
1.3.1版的主要工作是:(1)采用java的算法匹配連筆鍵幸斥,效率十分低,為此使用了NSPredicate的方法冻记,把所有的筆畫匹配算法替代了睡毒,并且對數(shù)據(jù)類型也做了更改,原先是若干獨立的String數(shù)組冗栗,為了能用NSPredicate演顾,新建了一個cnChara的類供搀,匹配到筆畫后同時獲得其字頻等信息,此外還有valueForKey過濾钠至,總之是盡量利用固有的方法避免自己編寫低效率的循環(huán)葛虐。(2)數(shù)據(jù)持久化方法的改動,原先是每次彈出鍵盤后棉钧,讀取加密的碼表屿脐,然后解密,造成運算量大宪卿,鍵盤顯示遲緩的诵,為此,采用了歸檔的方法佑钾,第一次解密后存檔西疤,以后再彈出鍵盤直接解檔即可。如果歸檔自帶數(shù)據(jù)類型休溶,數(shù)據(jù)是透明的代赁,因此必須歸檔自定義類型,因此又新建了cnDict的類兽掰,其中有一些encode,decode的方法芭碍。(3)增加了字母鍵盤、希臘文孽尽、俄文窖壕、注音字母、假名泻云、常用符號艇拍、顏文字等鍵盤,并支持自定義鍵盤宠纯。自定義數(shù)據(jù)可以在Container里設(shè)置卸夕。(4)為APP制作了精美的視頻、圖片婆瓜。(5)更新了字頻信息快集。在網(wǎng)上找到若干版本的字頻表,但還是有不合常理的地方廉白。
1.3.1版本在12月初提交个初,由于一個簡單的錯誤,在UI上顯示了版本號猴蹂,被退回院溺,于是快速更正再次提交,順利趕在了圣誕節(jié)前上線磅轻。倉促上線珍逸,沒有經(jīng)過iPhone6的真機(jī)調(diào)試逐虚,只經(jīng)過了iPadmini2的測試,結(jié)果在上線后谆膳,發(fā)現(xiàn)在iPhone6上不能彈出鍵盤叭爱。這是一個重大的BUG,可能是這個原因?qū)е铝讼螺d量下降漱病。問題發(fā)現(xiàn)后买雾,一度以為是iOS版本問題,直到1月初杨帽,有用戶反映無法使用漓穿,才引起重視。經(jīng)過一番排故睦尽,發(fā)現(xiàn)是歸檔造成的錯誤器净。這個錯誤至今沒有找到根本原因型雳,只是采取措施回避了当凡。可能是歸檔數(shù)據(jù)量大纠俭?問題是歸檔數(shù)據(jù)中必須有一個空成員變量才行沿量。更正后的版本1.3.2版于1月底上線。
隨后冤荆,又展開了對詞語預(yù)測和分詞的攻堅戰(zhàn)朴则。(1)實現(xiàn)了對分詞符號的按鍵處理,包括插入钓简、顯示乌妒、刪除等等,為處理詞庫提供操作框架外邓。(2)對詞語的預(yù)測撤蚊,采用即時計算下一個字的列表的算法,實際上很順利损话,在1月底實現(xiàn)了侦啸。(3)分詞,這是一個異常摧心的算法丧枪,經(jīng)過幾天的突擊光涂,也在春節(jié)前實現(xiàn)了,主要的問題在于:減少載入數(shù)據(jù)量拧烦,把詞庫分成了25個忘闻;處理刪除鍵;使用正則表達(dá)式過濾詞庫恋博。(4)算法的優(yōu)化:春節(jié)后齐佳,經(jīng)過iPhone6真機(jī)調(diào)試葵蒂,發(fā)現(xiàn)彈出鍵盤時崩潰,于是又突擊2天解決了問題重虑。原因有很多践付,集中在readStrokeTable函數(shù)中,主要問題有:頻繁同步AppGroup共享缺厉,單個共享文件太大永高,歸檔時崩潰等等。解決措施為:優(yōu)化了共享數(shù)據(jù)的結(jié)構(gòu)提针,最大限度減少彈出鍵盤時的運算量命爬;把詞庫分割存儲趟咆,并且在彈出鍵盤時不讀詞庫垄分,只有在打字時即時讀取,竟然也不影響速度概作。這是因為嗜价,如果在彈出鍵盤時讀取艇抠,需要保留所有9萬多條詞匯,嚴(yán)重占用內(nèi)存導(dǎo)致崩潰久锥,而在打字時讀取家淤,則立即使用前一個字過濾,僅剩下很少的條數(shù)瑟由,其余的丟棄了絮重。經(jīng)過優(yōu)化之后,彈出鍵盤加速了歹苦,詞語預(yù)測和分詞功能都不受影響青伤。(5)對Sqlite3進(jìn)行了研究,也找到了示例代碼殴瘦,不過難以操作狠角,因為只在Extension里處理數(shù)據(jù)庫是不可能的,仍然需要把db.data保存在AppGroup中痴施,和之前的方法沒有本質(zhì)區(qū)別擎厢,于是放棄了。目前的算法辣吃,處理約10萬條詞匯动遭,可能已經(jīng)達(dá)到了極限,如果后續(xù)還要擴(kuò)充詞匯量神得,可能還需要更高級的工具厘惦。
總的來說,用到了以下比較高級的工具:
(1)AES 加密解密;
(2)APP 內(nèi)支付模塊宵蕉;
(3)NSPredicate過濾酝静,valeForKey過濾,正則表達(dá)式的運用羡玛;
(4)數(shù)據(jù)持久化:AppGoup别智,歸檔,解檔稼稿。