2016年8月2日 星期二

Swift Xcode的TableView設定Width寬度100%邊界Without Margin

iPhone和iPad的螢幕尺寸大小是不一樣的,還有iPhone Plus等多種尺寸,所以在放置TableView的時候,希望它可以自動調整寬度,寬度變成100%,直接根據螢幕的大小來縮放。

設定TableView寬度為100%
選擇TableView物件


 取消勾選Constrain to margins,並設定左邊和右邊的邊界為0
1)打開設定介面(在Xcode畫面右下角的位置)
2)取消勾選Constrain to margins
3)點選左邊界和右邊界
4)邊界填寫為0,有時候填寫完設定會跑掉,先點選一下其他地方,再重新填寫就可以了
5)完成設定


TableView設定的寬度完成



如果勾選了Constrain to margins
會自動留下20px的邊界


2016年7月16日 星期六

LaunchScreen語法寫在哪-APP啟動畫面

 關於啟動畫面,在研究是否需要寫語法,讓啟動畫面可以有更靈活的顯示。直到查詢了官方說明,原來並不支援這樣的作法。啟動畫面是越簡單越好,畢竟只是在等待程式載入時,匆匆的出現而已。

官方說明,LaunchScreen只是簡單的靜態啟動畫面,推薦使用Storyboard直接拉畫面,或是使用靜態圖片當做啟動畫面。不支援多語系,啟動畫面是靜態圖片或元件,所以不建議使用需要多語系的文字,因為如果要設定多語系時,文字並不會依照相關的設定顯示該語系的說明。

 啟動畫面,就是進入主程式前,會短暫顯示的那個畫面。

Apple Developer的介紹
https://developer.apple.com/ios/human-interface-guidelines/graphics/launch-screen/


本來想找有沒有可以讓APP啟動畫面背景圖片重複的方法,找很久都沒有看到
看來只能使用Launch Image的方式,針對不同螢幕大小設定不同的圖片囉

2016年6月27日 星期一

不用Log將資料標示為處理過的作法

需要將資料標示是否處理過時,最直覺的作法是有個欄位,記錄該筆資料是否處理過。

可以新增欄位的情況:
直接在原本的資料表加欄位,並且對這個欄位做Index,這個欄位放置資料是否處理過的標示。這個作法,是可以清清楚楚的確實知道是否這筆資料是否有處理過。

新增Log資料表的作法:
會採用這個作法是因為,很多資料表都需要新增欄位去標示這筆資料是否處理過,甚至得各別標示這個欄位是否處理過。可是又不是每個欄位都需要標示,所以不適合每個欄位都再各別新增一個欄位作標示。是否要標示,是根據設定來決定的。所以決定新增一個資料表統一記錄這個資料表的這個欄位是否處理過。如果日後原本的資料表新增了欄位,也可以很靈活的直接在這個新增的資料表作記錄。新增的資料表,放置TableName, KeyColumn, KeyID,  ColumnName,  Mark,作Log的記錄。

結果實際使用時,原本的資料量相當的龐大,造成新資料表記錄的Log也多。於是  JOIN 起來,速度非常的慢。 造成程式處理的效能相當的差,甚至是有加Index的情況也是。看來並不是個好辦法。

效能好的作法:
最後大家集思廣益的作法是,直接用 ID 或 時間,篩選這筆資料是否處理過。比如說,原本的資料表共有100筆資料,3個欄位需要標示是否處理過。可以用資料建立時間來記錄處理到哪一筆了,這時候只需要3筆記錄,用時間來篩選最後處理的資料是哪筆。上面提到的新增Log資料表的作法,是會記錄到100x3=300筆資料的。這種作法,由於需要處理的資料變少,大大的提升效能。姑且稱之為小Log資料表作法吧。先列出小Log資料表最後處理的時間,在用這個時間直接去對原本的資料表作篩選,把最後處理時間之後的資料都列出來。原本的資料表,時間篩選欄位,最好加上Index。或是列出最後處理的ID之後的資料。

當然,也要加上一些防止資料重複處理的作法,例如,篩選出來的資料,可以用邏輯判斷這筆資料是否有被處理過的特徵。

如果不需要記錄這麼多欄位,也可以簡單的把最後處理的時間,放到文字檔裡。

看你怎麼選擇囉。

2016年3月6日 星期日

GPS在背景執行時持續記錄位置


需要讓APP像Nike+或RunKeeper那樣,就算將APP退到背景,也會持續記錄GPS位置。
但是不知道為什麼在背景執行了20分鐘就停止了。研究後發現原來少了一行關鍵程式。

locationManager.pausesLocationUpdatesAutomatically = false
是否讓位置更新自動停止 ,預設為true
時間到了20分鐘左右,就會自動停止

完整範例下載

以下簡介一下程式的內容,完整程式請直接下載範例

設定APP權限
Capabilities->Background Modes 選擇 ON
勾選 Location updates


加入GPS相關函式庫
General->Linked Frameworks and Libraries
點選 + ,加入 CoreLocation.framework


因為是Swift的關係,需要加入Header File



檔案的內容加上
#import <CoreLocation/CoreLocation.h>


建立Header檔案的關聯
Build Settings-> Swift Compiler-Code Generation
->Objective-C Bridging Header 填入 LocationTrack/Header.h
LocationTrack為專案資料夾
Header.h是剛剛建立的Header File


編輯請求權限時的說明文字
編輯Info.plist
加入  NSLocationAlwaysUsageDescription
裡面的文字,是APP請求相關權限時,向使用者說明的文字內容

以下兩個選擇其中一個填入,差別在於,一個是向使用者請求APP使用期間時,才使用GPS;一個是不管是不是APP使用期間,都可以使用GPS
NSLocationWhenInUseUsageDescription APP使用期間才使用GPS的文字說明
NSLocationAlwaysUsageDescription 任何時間都可以使用GPS的文字說明


向使用者請求權限的畫面


權限的差別
設定->隱私權->定位服務
可以看到兩個權限的差別


當APP的權限是選擇"使用App期間"才可以使用GPS時
將APP退到背景時,會顯示正在使用您的位置
像Nike+和RunKeeper


在程式中,要求請求權限的部份,以下選擇一個就可以了
//在APP使用期間才能使用GPS
locationManager.requestWhenInUseAuthorization()
//隨時都可以使用GPS
locationManager.requestAlwaysAuthorization()

範例APP簡介
這個APP在點選"START開始記錄座標"按鈕時,會開始記錄GPS
把GPS資料寫入GPSRecord.plist檔案裡
在開啟APP時,會先讀取GPSRecord.plist檔案的內容
使用iTools等工具就可以將這個記錄檔案取出


初始化
在ViewController當中先定義一些變數
並加上CLLocationManagerDelegate


初始化CLLocationManager
@IBAction func btnStartGPS(sender: UIButton) {
        let btnStartGPSLabel: String = btnStartGPS.titleLabel!.text!
        if((btnStartGPSLabel).rangeOfString("START")?.startIndex == (btnStartGPSLabel).startIndex){
            //簡易的判斷現在是要停止或是開始
            

            btnStartGPS.setTitle("STOP停止記錄座標", forState: UIControlState.Normal)
            //初始化變數
            locationManager = CLLocationManager()
            locationManager.delegate = self
            //設定精確度
            locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
            
            //相當重要的一行
            //如果不加的話,會在背景執行20分鐘左右,就停止記錄了
            locationManager.pausesLocationUpdatesAutomatically = false
            
            if #available(iOS 9.0, *){
                locationManager.allowsBackgroundLocationUpdates = true
            }
            
            //---請求權限---
            //在APP使用期間才能使用GPS
            //locationManager.requestWhenInUseAuthorization()

           //隨時都可以使用GPS
           locationManager.requestAlwaysAuthorization()
           //----------
            
            //設置距離篩選器,表示設備至少移動?米,才通知委託更新
            locationManager.distanceFilter = 10
            locationManager.startUpdatingLocation()
            
        }else{
            btnStartGPS.setTitle("START開始記錄座標", forState: UIControlState.Normal)
            locationManager = nil
            
        }
      
        
    }

座標更新的事件
//座標有更新時會呼叫這裡
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //經緯度
        var userLocationLat: String = String(locations[0].coordinate.latitude)
        var userLocationLon: String = String(locations[0].coordinate.longitude)
        
        var GPSText = getNowTime() + "=>" + userLocationLat + "," + userLocationLon
        textGPS.text = GPSText + "\n" + textGPS.text
        
        setPlistContent(GPSText)

    }
需要設定BackgroundTask,才可以在背景執行
override func viewWillAppear(animated: Bool) {
        myTimer.invalidate()
        
        //停止背景執行
        backgroundTask = UIBackgroundTaskInvalid
    }
    
    override func viewWillDisappear(animated: Bool) {
        //當程式進入背景時,執行這段
        //這段是測試用,可以不用有這段
        //監控APP是否還有在執行
        myTimer.invalidate()
        myTimer = NSTimer.scheduledTimerWithTimeInterval(1.0,
            target: self,
            selector: "timerMethod:",
            userInfo: nil,
            repeats: true)
        
        //加這個,才會在背景執行
        //時間到了會執行這裡
        backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
            [unowned self] in
         
        }
        assert(backgroundTask != UIBackgroundTaskInvalid)
    }


完整範例下載



------------
iOS后台持续定位并定时上传

2016年2月17日 星期三

用Fiddler模擬慢速度的網路

因為需要測試手機APP在網路慢或不穩的情況下的執行狀況,但是網路不穩的環境去哪找呢?

其中一個方式是用手機開2G模擬,當然你的手機網路是要吃到飽的方案比較好。如果是桌機想要測試網路慢的情況,或是將筆電的網路分享給手機的時候,這時候,可以用Fiddler幫你降速。


選擇 Rules->Performance->勾選 Simulate Modem Speeds
就可以幫你懷念數據機時代的網路時光


如果想要嘗試更慢的速度
Rules->Customize Rules


會開啟一個純文字的文件,可以客製化你想要的設定


找到這段,修改成你想要的數字
儲存後,需要重新勾選Simulate Modem Speeds,設定才會生效
if (m_SimulateModem) {
            // Delay sends by 300ms per KB uploaded.
            oSession["request-trickle-delay"] = "300";
            // Delay receives by 150ms per KB downloaded.
            oSession["response-trickle-delay"] = "150";

        }

如果直接將m_SimulateModem設定為true,設定會直接生效
只是每次開啟fiddler,預設都會勾選 Simulate Modem Speeds
var m_SimulateModem:boolean=true;



如果想知道網路慢到什麼程度可以使用 遠傳的測速網頁
當然因為網路很慢,所以要等很久,才會有結果
 其他線上測速測不出來fiddler限速的結果,或是因為網路太慢,連測速網頁都無法跑
遠傳的測速網頁



網路限速測試,Fiddler的設定
if (m_SimulateModem) {
            // Delay sends by 300ms per KB uploaded.
            oSession["request-trickle-delay"] = "30000";
            // Delay receives by 150ms per KB downloaded.
            oSession["response-trickle-delay"] = "15000";

        }


測速結果
 

2016年2月5日 星期五

Mac Air常常讀不到usb外接硬碟

已經將外接硬碟格式化成exFAT,每次讀取都要靠運氣,主要是當做Mac Air的資料備份用,畢竟Mac Air容量實在太小了。就算資料不小,也要備份啦。

用了n年之後,突然很好奇這個問題。因為正在做重要的備份,可承受不起資料丟失的風險。將備份硬碟連接另一台Windows筆電,讀取和儲存超穩定的,完全沒有壞掉的跡象。

好奇之下,上網查詢,原來是Mac Air供電量不足導致的。Mac Air使用USB外接硬碟,需要外接電源,供電量才會足夠。但是Mac Air的兩個USB孔差這麼遠,要外接電源,恐怕需要USB延長線吧。

可以參考這個網站關於Mac Air外接硬碟的說明

2016年2月4日 星期四

桌上型電腦用Fiddler偵測手機網路流量

使用筆記型電腦偵測手機流量簡單多了,只要將筆記型電腦的網路分享給手機,在做一些相關的設定就可以了。

如果使用桌上型電腦,需要有可以將電腦的網路分享出去的裝置,除了無線網卡外,有些手機支援USB連接電腦,就可以讓手機使用電腦的網路的功能。這時候,再將這台手機的網路分享給另一台測試手機,這隻測試手機,就可以讓桌上型的Fiddler偵測到網路流量了。

方式一:無線網卡+測試手機
方式二:可以USB上網的手機+測試手機
            為什麼需要兩台手機?因為手機網路需要設定proxy,USB上網無法設定proxy 

USB無線網卡很便宜,就看看手邊剛好有什麼設備囉

這裡以紅米手機做示範,紅米剛好可以使用USB上網。
若要直接看Fiddler設定的話,請點選這裡

紅米機USB上網,紅米機當熱點分享網路
安裝小米助手
點選下圖按鈕,紅米機就可以使用USB上網了


點選"變身Wifi熱點",紅米就變成無線基地台了


 輸入想要顯示的wifi名稱和密碼



開啟測試手機的Wifi偵測功能,選擇紅米手機
測試手機就可以上網囉



Fiddler偵測手機網路流量  
 開啟Fiddler,選擇Tools->Fiddler Options



點選Connections頁籤,設定要監測的port
勾選 Allow remote computers to connect
Fiddler設定完成後,需要重新開啟,設定才會生效


 接著需要設定測試手機
 將測試手機使用電腦的Wifi上網,在Wifi列表長按網路名稱


點選"修改網路"


勾選"顯示進階選項"
Proxy設定選擇"手動"


輸入電腦IP和剛剛在Fiddler設定要偵測的Port
儲存後,Fiddler就可以偵測到手機的網路流量了



----------
Android利用Fiddler进行网络数据抓包