## first View - 在 storyboard 中點選要設為啟動的 controller 後, 在屬性視窗勾選 is initial controller ## nav, tab controller 使用 - embed in: 是在當前所選的 controller 使用 - cmd + shift + L: 是直接新增一個獨立的 ## 切換 controller Use this shortcut to instantiate ViewController in Swift https://chanakya-hirpara.medium.com/use-this-shortcut-to-instantiate-viewcontroller-in-swift-ecba7ea6136f How to transition from login screen to tab bar controller https://fluffy.es/how-to-transition-from-login-screen-to-tab-bar-controller/ IOS Swift 界面跳轉以及傳值 https://www.twblogs.net/a/5ee86a086040a668d92fdc83 Swift 不同Controller互動 與 Navigation Bar https://cdfq152313.github.io/2016-10-03/ ## 少量的使用者資訊 UserDefault https://medium.com/@albert1994/%E4%BD%BF%E7%94%A8swift%E9%96%8B%E7%99%BCapp-%E7%B0%A1%E6%98%93%E5%84%B2%E5%AD%98-userdefault-eda46f6e28ea save time https://stackoverflow.com/questions/55776143/how-to-store-date-in-userdefaults ## Xcode 中如果檔案重複會怎麼樣呢? 在你腦袋不清楚的時候會掉入無窮迴圈, 試著做了所有的嘗試之後. 最後還需要你剛好從版本控制中看到那筆可愛的檔案 errMsg Multiple commands produce '/Users/CymmetrikDev2/Library/Developer/Xcode/DerivedData/EzPrint-egdfssexygmyfocjtgihqezjdaqd/Build/Intermediates.noindex/EzPrint.build/Debug-iphoneos/EzPrint.build/Objects-normal/arm64/BaseHttpAPI.stringsdata' Target 'EzPrint' (project 'EzPrint') has compile command for Swift source files ## custom tableview cell, u need konw 其實主因是不熟悉 uikit 框架, 在使用某些物件時沒有依據規則導致發生預期的例外。比如這次使用到的 UINib(nibname, identity).... ## bluetooth - pravicy 需要設定相關的權限說明,否則無法使用藍芽。以下兩個屬性在開啟新專案時就已經建立在 project info 中。(不確定是不是 brook 添加的) 而且有預設的提示文字,根據手機當言的語系來做呈現 ```swift= < ios 13: Privacy - Bluetooth Peripheral Usage Description >= ios 13: Privacy - Bluetooth Always Usage Description ``` ## stroyboard view 與 view 在畫面中是誰在誰上面? 透過 storyboard 左邊控件列表越往下,显示就会越往上,这个是可以拖动顺序的。 ## button layer.cornerRadius 在設定 background 時,執行到目標手機時效果都沒有出來(background configuration)。所以後來改用另一個設定(view)的 background,但沒辦法直接設定 connerRadius。所以改從 user defined runtime attribute 增加屬性 ```swift= //key path layer.cornerRadius //Type Number //value 16 ``` 上述設定都透過 storyboard,都沒有透過程式碼。 ## swift 計算小數點的運算 由於 Swift 程式語言儲存浮點型的方式問題, 浮點型 (Double/Float) 的精度丟失問題是必然會發生的。解決這個問題的方法不多,但是講回來他的小數位數補得很滿,所以也不至於丟失太多。(其實其他語言也是一樣,只是大多會自動配上四捨五入 網上查了很大多數的解決方案 要點是運算都用同一個型別,最後轉出給伺服器實在改為字串。 - Json 全部改用 Double,不用 Float。在各系統間也能達到一制,不用再轉來轉去 - Json 全部改用 Decimal,但在 Json decode & encode 需要多一手轉換,移去預設的 Double 機制。 - Json 全部改用 String,比較麻煩的是如果要計算都還需要再轉乘數值,到後端也是相同的概念。但這個方法幾乎可以避免精度失真 - 最後是將小數位數變成整數做運算,ex: 10.23 先乘上 100 得到 1023 後再下去做整數的運算,其實很多金錢的運算也會這麼做。 最後考量 App 本身對於這些後端來的資料不進行計算,為了降低網路傳輸量。想讓後端如果有小數點的都用字串來交換資料,當然也可以再轉換成四捨五入,但可能未來在邏輯增加時有丟失資料的可能性。 ## localization - [Cocoa Keys](https://dev**eloper.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW1) - [iOS 10 and Permissions localization description](https://stackoverflow.com/questions/38954885/ios-10-and-permissions-localization-description) - [#31 多語系設定 Localization](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E6%95%99%E5%AE%A4/ios-31-%E5%A4%9A%E8%AA%9E%E7%B3%BB%E8%A8%AD%E5%AE%9A-localization-ffe31a772677) - localized 帶參數,可透過 string format & String.localizedStringWithFormat & CVarArg 來完成 - [Formatting Localized Strings with Multiple Values](https://stackoverflow.com/questions/51369282/formatting-localized-strings-with-multiple-values) - [How to create a String with format?](https://stackoverflow.com/questions/24074479/how-to-create-a-string-with-format) - [localizeWithFormat and variadic arguments in Swift](https://stackoverflow.com/questions/27914053/localizewithformat-and-variadic-arguments-in-swift) - sample code ```swif=1 // localable.string "loginFailedAPI"="error msg:%1$@, code: %2$d"; // code var args = [CVarArg]() args.append("internal err") args.append(500) let nsStr = NSLocalizedString("loginFailedAPI", comment: "") let result = String.localizedStringWithFormat(nsStr, args) ``` 關於藍芽、GPS 的提示如果要走自定義的多語系,需要新增 string file 檔名只能是 InfoPlist,然後有固定的 key 值,比如 “Privacy - Bluetooth Peripheral Usage Description” 對應的 key 會是 "NSBluetoothPeripheralUsageDescription",那就必須使用這組 key 來調整開啟藍芽的提示訊息內容。 ## xcode 不同專案要複製檔案 通常你會看到兩種情形,加進來的 swift 檔案找不到 target membership,另一種是看的到 target membership 但無法加入版控.... 上述的步驟先在專案中建立相同的 group,再將檔案透過 finder 複製過來,並且透過 add files to "your project name"。(另外也試過不建立 group 直接加入複製過來的 folder + file) [將 Xcode 專案的檔案 & 畫面複製到另一個專案](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%B0%87-xcode-%E5%B0%88%E6%A1%88%E7%9A%84%E6%AA%94%E6%A1%88-%E7%95%AB%E9%9D%A2%E8%A4%87%E8%A3%BD%E5%88%B0%E5%8F%A6%E4%B8%80%E5%80%8B%E5%B0%88%E6%A1%88-7759ca37e02e) - Step1: 讓兩個專案的目錄同時出現在螢幕中 - Step2: 將要複製的檔案透過拖拉的方式移動到另一個專案對應的位置 - Step3: **這裡的選擇很重要** 請選擇: - Destination: 勾 copy items if needed - Added folders: 選 create groups - add to targets: 選 "your project name" ## change info.plist location ### step - 將 info.plist 移動到位置後,設定 location 為 relative to project - 找專案屬性的 Target -> Build Setting -> packaging -> info.plist File -> 將路徑改為現在的路徑 ## SceneDelegate function is never called 情竟是在初始化 storyboard app 專案時,依據現有專案調整專案目錄後 debug 時會出現黑畫面網上還找不到解方(情境不相同 後來開新專案後可正常執行,所以紀錄以下步驟,請依序做 - 專案建立後先跑 debug - 設定專案屬性 ex: env, core, infra, debug/release config, project setting - 設定好後再跑一次 debug - 移動 info.plist 到指定目錄,並到 project setting - 再跑一次 debug - 在移動 SceneDelegate AppDelegate 到指定目錄 - 再跑一次 debug - 最後在移動跟 view 相關的 - 這樣就不會再遇到這個問題了 ## segmented controll & 畫面切換 segmented controll 可以想像畫面上方有 nav bar,但沒有實作切換分頁的效果。以下的文章介紹都是如何透過 segmented controll 來達成畫面切換。 **segmented controll 常見搭配招式如下** - 搭配 contrainer view,是 apple 提供的 component。[# Switch between container views using segmented control](https://www.youtube.com/watch?v=A6vxDDAUj2o)、[# 利用多個 container view 切換頁面](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%88%A9%E7%94%A8%E5%A4%9A%E5%80%8B-container-view-%E5%88%87%E6%8F%9B%E9%A0%81%E9%9D%A2-6d00fe848572) - 搭配 controller view,透過撰寫程式碼來完成控制。約六份中那 [# How to Use Child ViewControllers (Container Views) in Swift](https://www.youtube.com/watch?v=B5-1_aR20rE) - 多個子 view 可透過 array 來管理,就只需一個屬性。ex: uiViews = \[UIView\]() **手刻 segmented** [# How to Make a Custom Segmented Control (iOS, Xcode 8, Swift 3)](https://www.youtube.com/watch?v=xGdRCUrSu94) ## scroll view & stackview 切換畫面 [ref][https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/stack-view-scroll-view-%E8%A3%BD%E4%BD%9C%E5%88%86%E9%A0%81-tutorial-%E6%87%B6%E5%BE%97%E5%AF%AB%E7%A8%8B%E5%BC%8F%E7%89%88-7ff9021317a0] 因為設定上不熟悉,因而特別記錄這篇。 - 要點 - scroll view 必要設定除了上下左右的約束,詳細的拖拉範圍大小 - scroll view 拖拉範圍大小對應的是 **content layout guide** - scroll view 中的 ui item 要設定與螢幕對應的關係是 **frame layout guide** **步驟** 1. 新增 scroll view 並設定上下左右 constraint 2. 新增 stackview 於 scroll view 中 - 設定 distribution(cmd + opt + 5) 為 fill equally - 透過 cmd 同時選取 "stack view" & "content layout guide" 並設定上下左右的 constraint 3. 新增 View 於 stackview 透過 cmd 同時選曲 "View" & "frame layout guide" 並設定大小同螢幕 - 勾選 "Equal Widths" & "Equal Heights" ## Apple devoloper 新增 account [Authorise an Additional User to your iOS Developer Account ](https://support.appmachine.com/support/solutions/articles/80000978467) **Step** 1. Login to App Store Connect (https://appstoreconnect.apple.com/). 2. Open the Users and Access section. 3. Click the '+' button in the top-left corner of the page. 4. Enter the new users details. 5. Grant the user with at least the Admin or App Manager role. 6. Enable 'Access to Certificates, Identifiers & Profiles'. **後台相關** - [Apple store connect](https://appstoreconnect.apple.com) - MAC 上架 app 的程式: Transpoter ## signin with apple id on website - [Sign in with Apple Tutorial, Part 4: Web and Other Platforms](https://sarunw.com/posts/sign-in-with-apple-4) - [How to configure Sign In with Apple](https://medium.com/identity-beyond-borders/how-to-configure-sign-in-with-apple-77c61e336003) - [sign_in_with_apple clientconfigi scope](https://developer.apple.com/documentation/sign_in_with_apple/clientconfigi/3230955-scope) 下述的流程是由第一個跟第二個參考連結而來的,一開始只看第二個後來發現文章中沒有特別提及 App IDs (推測是在其他部分提到),所以才去找了第一個。 ### Step **Step** register App IDs => register ServiceID(client ID, redirectURL) => private key => Apple Service Email Notification(有使用我們服務並且想跟我們聯絡的) - Step1 register App IDs (主要設定這組 App IDs 有提供哪些能力,供後面其它的服務來設定 App IDs 取得能力) - 從 Apple Develope 後台找到 **Certificates, Identifiers & Profiles** => 點選左邊選單 Identifiers => 點擊上面的 "+" 號在上面的 “Identifiers” 的左側 - 選取 App IDs 並點擊 continue - 跳轉畫面後要輸入 Description 與 Bundle ID(畫面上面有規則),滑動到下方的功能清單點選 **Domain associated**、 **Sign In with Apple** (右邊有 edit 按鈕記得點進去看一下),回到上點 continue - 到了確認頁面後確認沒問題後按 Register - Step2 register ServiceID(client ID, redirectURL) (主要是提供 Web 能使用 Apple ID 登入的功能) - 從後台找到 Certificates, Identifiers & Profiles => 點選左邊選單 Identifiers => 點擊上面的 "+" 號在上面的 “Identifiers” 的左側 - 選取 Service IDs 點擊 Continue - 跳轉畫面後要輸入 **Description 與 identifier** 並且勾選 **Sign In with Apple**,此時點擊它旁邊的 **Configure** - 選取對應的 **App ID** - 設定 **domain name** (不需要包含 https:// - 設定 return url 提供 Apple ID 登入後回傳的資訊 - 按下 Save - Step3 create private key (主要提供 server 與 Apple servie 通訊時所需使用的 client_secret) - Certificates, Identifiers & Profiles => 點選左邊選單 Identifiers => 點擊上面的 "+" 號在上面的 “Identifiers” 的左側 - 選取 Key 並點 continue => 點擊 register a new key - 跳轉畫面後輸入 key a name 並勾選 **Sign In with Apple** ,接著點擊旁邊的 Configure 選取對應的 App ID 後按下 save - Apple 會生成 key ID & p8 檔案,這個檔案要保存好只會有這一次下載,不見只能重新再生成一個 - Step4 設定 Apple Service Email Notification ### notice - Apple ID 登入使用到的技術是等同於: OAuth 2.0 and OpenID Connect - user email 可能會取不到,這段到時要確認。若真的得另想解決方案 - 使用 Apple JS 時有四個參數 - clientId : Service ID, - scope : 可以請求使用者提供 name & Emai,for example, `"scope=name email"`. - redirectURI: Apple ID 登入後要將資訊給? - state: 減少 CSRF 攻擊的風險,文章中有提供如何產生唯一碼 [Google where they use SHA1 over a random string]([https://developers.google.com/identity/protocols/OpenIDConnect?hl=fr#createxsrftoken](https://developers.google.com/identity/protocols/OpenIDConnect?hl=fr#createxsrftoken))