家裡老舊的蘋果mini 2012 late版本只能更新到10.13,無法使用XCODE。使用M1(13.6)下載XCODE版本15.0。
XCODE是IDE,對比於EClipse和Android Studio。基本操作語言為swift(類比於JAVA或Kotlin)。專案分成兩種,可開新專案,TAB選擇IOS,下面跳出Application和LIB兩大類,選擇Application類的第一項APP(
連結)。
- Product Name : HelloWorld
- Team : skip
- Organization : com.xxx
- Bundle Identifier : 送審使用,先不用管
- Interface : Storyboard,Xcode支援兩種 UI 建構方式Storyboard和SwiftUI
- Language : Swift,Xcode支援 Objective-C 與 Swift
- Use Core Data : 資料庫先不管
- Include Tests : 測試先不管
或是開啟舊專案。如下載github的zip解壓縮,範例(
連結)。對於從零開始寫IOS程式很有用(
GITHUUB)。副檔名是xcodeproj。功能是按鈕直接傳送資料,收到回應後顯示在TEXTBOX內。
畫面
最基本的StoryBoard,UI入口為Main(介面編輯器)。點選右上方的加號,跳出元件選單。選擇Button拉到白色畫面中間,預設的名稱是Button,從右邊選單更改名稱為Hello World。右側選單還有非常多更新介面例如顏色等等的功能。
按鈕按下後,會帶動程式,程式在哪裡呢?因為APP模板預設有View對應架構,只要將動作直接放進View中即可。
@IBAction func showMessage(sender: UIButton) {
let alertController = UIAlertController(title: "Welcome to My First App", message: "Hello World", preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
present(alertController, animated: true, completion: nil)
}
連結方式很"抽象",以外接滑鼠為例,回到Main畫面,點選button,按住右鍵就會拉出直線,將直線拖拉到(按鈕仍然維持在原本位置上)畫面上方有三個按鈕的最左邊,也就是viewcontroller上。放開右邊按鈕,就會跳出viewcontroller中可以連結的function。例如剛剛的showmessagexxxx。完成。
storyboard使用就是uikit,更多操作說明
連結對應這幾年推出更新的開發方案稱為swiftUI
連結
MVC架構
Basic Chat是MVC架構(藍芽的部分紀錄在另外一篇),無論是Android或是XCode都大量運用MVC,也算是軟體工程的一大進步吧。
MODEL沒有內容
VIEW很簡單
CONTROL有兩個
ConsoleViewController 負責與VIEW溝通
包含在ViewController中
MAIN中有三個項目,這讓我想到,如何在MAIN中增加VIEW(
連結)
NAVIGATION CONTROLLER(找不到)
VIEW CONTROLLER
CONSOLE VIEW CONTROLLER
IDE編輯技巧
使用tab會跳出可選擇項目
滑鼠點擊某個文字後,按下option,就會跳出這個物件能夠使用的項目
執行:模擬器
menu->product->run 或是右邊箭頭,就會開始執行,執行有幾種,若有裝模擬器就能往模擬器送,模擬器是要另外下載IOS模擬器(模擬器是否支援藍牙不確定)。當設定過一次後,會記住。模擬器本身是個單獨的application,這個概念在Android Studio是一樣的。
模擬器不具備藍芽功能
程式中加入print("hello"),會在xcode的右下方出現hello。
連結
print("Function: \(#function),Line: \(#line)")
結果是 Function: centralManager(_:didDiscover:advertisementData:rssi:),Line: 169
print("Peripheral Discovered: \(peripheral)")
結果是 Peripheral Discovered: <CBPeripheral: 0x28353e630, identifier = DDBFB78C-8690-C039-877E-556D31A8DA1B, name = OneTouch J05D, mtu = 0, state = disconnected>
執行:實機
SWIFT:語法
BLE
基本character:範例(連結)。完整範例(連結 GITHUUB)。尋找和管理BLE裝置。方式有二,最直覺是右上方文字啟動,比較特別是程式啟動畫面切到viewcontroller,因為viewcontroller有繼承CBCentralManagerDelegate,只要進入這個頁面就會開始啟動,若先前已經允許藍芽,當藍芽是啟動狀況就會執行startScanning。
- 找到空間中全部藍芽裝置 centralManager?.scanForPeripherals(withServices: nil , options: [CBCentralManagerScanOptionAllowDuplicatesKey:true])
- 列印出各個項目(可能上百個,會進入的下面function)func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { }
在這個function print("Peripheral Discovered: \(peripheral)"). 結果是 Peripheral Discovered: <CBPeripheral: 0x28353e630, identifier = DDBFB78C-8690-C039-877E-556D31A8DA1B, name = OneTouch J05D, mtu = 0, state = disconnected>
有時候會重複,但沒有關係。RSSI : 訊號強弱 Advertisement : BLE 裝置透過 Advertising 告知周邊 BLE 裝置自己的存在,其中, 考慮到 WiFi 的干擾,Advertising 封包在以下 3 個 bluetooth channel 上廣播:channel 37 (2402 MHz), channel 38 (2426 MHz), 和 channel 39 (2480 MHz) - 連線 centralManager.connect(peripheral, options: nil) //參數很多,不用理會( 連結 )。連線後,有兩種反應,一種是成功,一種是失敗。
centralManager(CBCentralManager, didConnect: CBPeripheral)
centralManager(CBCentralManager, didFailToConnect: CBPeripheral, error: Error?)
實驗結果是onetouch無法connect,下載了appstore軟體也沒有辦法連結,因此有點病急亂投醫,胡亂搞。但原相可以往下走,暫時歸因於硬體因素? - Service。連結
stopscan
peripheral.delegate = self
peripheral.discoverServices(nil)
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
print(“Found \(services.count) services! :\(services)”)
對每個services可以取得數字確認是否符合,並且繼續詢問後續characteristic,確認符合Service和Characteristic。另外一種做法是,scan的時候就直接填入service號碼,只有符合號碼才會顯示出來。 - Characteristic
func peripheral(peripheral: CBPeripheral,didDiscoverCharacteristicsForService service: CBService,error: NSError?)
peripheral.readValueForCharacteristic(characteristic)
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?)
print(“characteristic uuid: \(characteristic.UUID), value: \(characteristic.value)”)
if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Rx) {
rxCharacteristic = characteristic
BlePeripheral.connectedRXChar = rxCharacteristic
peripheral.setNotifyValue(true, for: rxCharacteristic!)
peripheral.readValue(for: characteristic)
print("RX Characteristic: \(rxCharacteristic.uuid)")
}
if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Tx)
{
txCharacteristic = characteristic
BlePeripheral.connectedTXChar = txCharacteristic
print("TX Characteristic: \(txCharacteristic.uuid)")
} - Bonding,這步驟完成才算是pairing完成。裝置列表會在table中,點選其中一個就會connectToDevice。也就是後續寫入和讀取資料。
- 寫入資料
peripheral.writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse)
func peripheral(peripheral: CBPeripheral,didWriteValueForCharacteristic characteristic: CBCharacteristic,error: NSError?)
print(“Succeeded!”)
writeValueForCharacteristic的方法將值寫入characteristic
CBCharacteristicWriteWithResponse CBPeripheralDelegate didwriteValueFor
CBCharacteristicWriteWithoutResponse 不能使用上面方法判斷 - 讀出資料
- 斷線didDisconnectPeripheral