IOS App – Enjoy In Life
啟發:
平常想知道附近有什麼餐廳或者商店都會使用Google Map,但是地圖上的點散散的,讓我覺得不是很容易找同一類型的店,而且若想知道這家店有沒有開也需要點進去看,讓我覺得有點麻煩。
因此想為自己開發一個可蒐集附近店家並統整類型,且可快速知道是否有營業的App。
原始製作想法:
透過一些方法去取得Google Map或Apple Map的地圖資訊,並利用抓取回來的資料類型將資料分群,每筆資料用顏色區分是否營業,點擊後可觀看資料的詳細內容,如:位置、電話、營業時間或評論等,並且提供導航功能。
預期功能:
1. 抓取附近地圖資訊
2. 顯示是否營業
3. 顯示每個資訊的詳細資料,如:位置、營業時間或評論等
4. 透過目前位置與選擇的店家位置啟動導航功能
實際製作結果:
透過一些方法去取得Google Map或Apple Map的地圖資料,並利用抓取回來的資料類型將資料分群,每筆資料用顏色區分是否營業,點擊後可觀看資料的詳細內容,但詳細內容中營業時間雖有取得但是七天的營業時間,如:星期一16:00~18:00,因為還要判斷當天是星期幾所以不顯示正確時間,只已開始抓取位置後的時間判斷該店是否有營業;而評論部分由於Google Map每人每天最多要5個評論,資料量太少也就省略。
導航部分原本是想做成一般導航的樣子,但由於不知如何透過程式啟用就改成用地圖顯示當地位置與目的地位置,且繪製一條路線在地圖中。
目前功能:
1. 抓取附近地圖資訊
2. 顯示是否營業
3. 顯示每個資訊的詳細資料,如:位置、電話、website、評價等
4. 透過目前位置與選擇的店家位置繪製路線於地圖中
尚未完成:
1. 一些bug導致閃退
2. 導航功能
App操作展示:
 |
App的過場頁面 |
 |
上圖過後接著會顯示所有附近店家的店名 淡黃色代表該店正在營業中 |
 |
點擊店名的cell會進入對應的頁面 頁面中呈現的是該店的詳細資料 如:地址、電話、官網、評價、價格等 |
 |
點擊前一張圖的一鍵導航後會進入此頁面 圖中標記為目前所在位置與你選選取店家的位置 並提供一條路線讓你可以通往該店 |
 |
右上方可切換不同交通工具所走的路線 只有走路與開車兩種路線可選擇 |
結論:
雖然整體做起來不算太困難,但是動態抓取資料並顯示其實不好弄,而且有些想法因找不到可參考的方法而不知如何使用;製作過程中使用很多框架(framework),每個框架有各自的用法,要一個一個的研究,花費我許多時間,幸好有學長強力支援,才能讓我實現許多心中所想的功能。
遇到的挫折總整理:
由於在實作上碰到各式各樣的問題,有些問題很詭異也有些值得讓學弟妹知道,因此在這裡整理我所碰到的問題及解決方法當學弟妹碰上同樣問題時可以參考,記得若碰上問題最優先需知道哪裡錯誤以及為何錯誤,可以的話把訊息印出來,讓Google幫忙。
Q1:
使用cocopods創建了workspaces檔,開啟後直接執行發生連結錯誤?
A1:
遇到這個問題是很詭異的,試試重開專案有沒有辦法解決,若無法只好重建
Q2:
為何使用Google Map而不使用Apple Map,明明Apple已經有內建Mapkit可以使用了?
A2:
一開始我也是執行嘗試Apple Map,但是Apple Map必須要自己設定naturalLanguageQuery,簡單來講就是搜索類型,例如今天要搜尋這個區域的所有咖啡店,就要設定naturalLanguageQuery=”coffee”,這跟我原本的想法相違背,又找不到能解決的方法因此不使用Apple Map實作。
而使用Google Place API後它會依照目前位置自動抓取附近位置的資料,雖然我也不確定抓取範圍多廣,這點跟我的想法比較相近,所以就採用這個方法了。
Q3:
按照官方流程使用Google Place API後還是抓不到資料?
A3:
這有幾種可能,官方的流程中沒特別明講CLLocationManager,這個是CoreLocation框架中的一個方法,它的目的是跟使用者要使用地圖的權限以及當收到地圖資訊時把操作資料的權限交給對應的class,若沒有使用此方法是無法拿到資料的。
也有另一種可能是你使用虛擬機打開後,虛擬機本身沒有地圖資訊,因此你必須要啟動後回到Xcode自行設定假地圖位置才能夠得到目前所在的附近資訊。
Q3:
使用Google Place API後營業時間都一樣感覺不大對?
A3:
Q4:
拿到資料後要如何將資料顯示?
A4:
Q5:
要如何繪製路線?
A5:
Q6:
想顯示不同路線卻不知如何消去已繪製的路線?
A6:
我一開始的想法是用白色的線將原本的路線塗掉再用別的顏色畫想要的路線,但是多按幾次路線切換後會發生重疊問題,一直都修不好,後來學長教我在繪製新路線時先使用mapView.removeOverlays(MapView.overlays)將原本路線消除即可,若還是不清楚可以問學長。
Q7:
在使用tableView顯示資料時如果內容超過cell的長度後面會變成…,是否有辦法全部顯示出來?
A7:
這是因為cell中儲存資料的label預設寬度為無限大,這表示你不管多長的內容皆會被擠在同一列中,而內容超過cell的大小則會顯示成…,這並不是cell不支援自動調整高度的問題。若要顯示所有內容,只要在你創造cell時把cell.textLabel.numberOfLines設為0,那麼當內容超過cell大小時label會自動換行,而tableView又提供根據內容高度自動調整,此時你的cell會變高,內容也會全部顯示出來。
Q8:
若想要在不同View中傳資料或想切換頁面該怎麼做?
A8:
這方法有很多種,而我是採用設定View的storyboardID,預設是沒有的,可以點選View在右邊的Identity
inspector中設定,並把Use StoryboardID勾起來,在程式中撰寫以下程式碼:
1. let vc =
storyboard?.instantiateViewController(withIdentifier: ”StoryboardID”) as! 要轉移的頁面所對應的class名稱
2. 在要接收資料的class中設定一個變數,然後直接在要送資料的class中撰寫vc.變數名稱,即可把要傳送的資料存到該變數中
3. 使用present(vc, animated:true, completion:nil)進行頁面切換
4. 若要返回上個頁面則使用dismiss(animated:true,
completion:nil)即可
Q9:
要怎麼使用陣列或字典?
A9:
在處理動態資料時總是需要陣列或字典來幫忙預存資料,而swift又是新語法,很多初學者常常面對明明很簡單卻不知怎寫的問題
陣列: var array:[型態] = []
字典:var
dic:Dictionary<型態,型態> = [:]
上面的[]與[:]只是代表空陣列與空字典,並不是初始化,swift若不預設為空會產生很多error,要特別注意。
Q10:
在處理某些資料時它回傳的型態為NSString,導致顯示時會變成optionals(“…”),但我只想要字串的值該怎麼辦?
A10:
我曾經被這點搞得很難過,swift中NSString跟String幾乎可以互轉,但怎麼轉顯示出來都怪怪的,我也曾經異想天開用迴圈跳過optionals直接吃成另一個字串,但碰到各種問題,因為NSString不允許取得字串的某個字元,而且強制轉型後String也不能跟char互接,最後發現根本不需要這麼麻煩,你直接在NSString的變數後面加!就可以幫你處理掉討厭的optionals了,不要再去走一次我走過的路了…。
Q11:
使用CLLocationManager的startUpdatingLocation()每隔一小段時間就會在抓取一次資料,若不想一直抓取該怎麼辦?
A11:
當初被這個問題搞到,害我不斷顯示重複的資料,我的方法是執行完一次startUpdatingLocation()後就直接執行stopUpdatingLocation(),這樣一來它就只會抓取一次資料,而若還需要重抓資料則建一個button讓使用者自行刷新即可。
Q12:
當動態產生某個物件時希望它大小是全螢幕該怎麼辦?
A12:
Swift有方法可以抓取手機螢幕大小,範例如下:
var fullScreenSize = UIScreen.main.bounds.size
全螢幕的寬度 : fullScreenSize.width
全螢幕的長度 : fullScreenSize.height
Q13:
想要依照某些條件把特定幾個cell的背景顏色換掉,卻發生不符合條件的cell顏色也改了,該怎麼辦?
A13:
這是因為你使用了tableView.dequeueReusableCell,它是tableView的一個函式,是當tableView中有空閒的cell時(猜測是沒有被顯示在螢幕上但已被產生),它會拿空閒的cell來用,若沒有則產生新的cell,這方式能提高效能,但對於要改特定cell的工作來會有點麻煩,因此不能只判斷符合條件後更改背景顏色,還要另外多判斷若沒有符合條件要改成原本的顏色才可以正確執行出你想要的結果。
Q14:
在滾動tableView發現有殘影的現象該怎麼辦?
A14:
這部份在我試著要改tableView的backgroundColor時有發生過,主要原因就是因為我是動態產生tableView,而我產生tableView的函式是當我每次抓取地圖資料時就會執行,而抓取地圖資料部份又因為CLLocationManager會一小段時間就執行一次,而以上這些巧合導致了我動態產生好幾個tableView,原本看不出來是因為預設tableView的背景顏色是不透明的,因此會把後面的tableView擋住讓你看不到,但是實際上已經產生了好幾個重複的tableView,現在你嘗試更改背景顏色並為了好看而調整透明度,導致原本被擋住的tableView中的內容顯示出來,造成了殘影現象。
瞭解事情的原委後試著測試看看你是否真的動態產生多個tableView,若真如此應該改成只產生一次tableView,而以後想依照更新後的資料更改其內容應使用tableView.reloadData()。
Q15:
要怎麼用程式碼更改textLabel的字體大小?
A15:
其中一個方法:textLabel.font = UIFont.systemFont(ofSize:
20)
Q16:
要怎麼用程式碼更改tableView中section的背景顏色?
A16:
這個有一點麻煩,我使用的方法如下:
1. let header = view
as! UITableViewHeaderFooterView
2. header.contentView.backgroundColor
= UIColor(red: 237/255, green: 177/255, blue: 124/255, alpha: 0.8)
記得在使用UIColor的顏色,原本RGB的值都要除255,alpha是控制顏色的不透明度,1代表完全不透明,0代表完全透明。
Q17:
若想改變App在手機上顯示的小圖示怎辦?
A17:
我的方法是利用以下網站轉出所有icon,再將對應的圖片放入Assets的App icon中
以上是我在製作此App時所碰到的各種問題,在這裡留下經驗讓以後學弟妹們有個參考方向。
期末心得:
雖說會有人覺得用我的App不如直接用Google Map好,反正也有提供類似的功能,而且介面更好更棒,但這是我想要的App,我製作時樂在其中,不僅稍微學會swift語法,更學會framework的使用方法,也知道cocoapods如何使用,這對我自己來說已經足夠了,我很感謝老師給我機會讓我做自己想做的東西,我只有一句話:這個App我不後悔。
參考網址如下:
6. 陳奕穎學長的facebook