Posted on

Swift初探

條件編譯

這是 Swift 的條件編譯(Conditional Compilation)的一個示例,它允許你根據特定的條件選擇性地編譯代碼。在這段代碼中,它確定代碼是在 iOS 模擬器中運行還是在實際的 iOS 裝置上運行。

    #if targetEnvironment(simulator)
    self.videoCapturer = RTCFileVideoCapturer(delegate: videoSource)
    #else
    self.videoCapturer = RTCCameraVideoCapturer(delegate: videoSource)
    #endif

判斷變數是否存在

Swift的空值會是nil

什麼 是 Protocol 與 Delegate

1. Protocol

在 Swift 中,協議(Protocol)定義了一套規範或合約,但不提供具體的實現。任何型別(如 classstructenum)都可以遵循(implement)這些協議,並為協議中的要求提供具體的實現。

例如,我們可以定義一個表示可序列化對象的 Serializable 協議:

protocol Serializable {
    func serialize() -> String
}

然後,我們可以讓某個 structclass 遵循這個協議:

struct Person: Serializable {
    var name: String
    var age: Int

    func serialize() -> String {
        return "\(name),\(age)"
    }
}

2. Delegate

Delegate 是一種設計模式,允許一個物件將某些決策或功能外包給另一個物件。在 Swift 中,Delegate 通常是通過協議來實現的。這意味著當一個類想要成為另一個類的代理時,它必須遵循一個特定的協議。

例如,假設我們有一個 Downloader 類,當下載完成時,我們希望通知另一個物件。我們可以定義一個 DownloaderDelegate 協議:

protocol DownloaderDelegate: AnyObject {
    func didFinishDownloading(data: Data)
}

然後,Downloader 類可以有一個 delegate 屬性:

class Downloader {
    weak var delegate: DownloaderDelegate?

    func download() {
        // 下載過程...
        // 完成後通知代理:
        delegate?.didFinishDownloading(data: someData)
    }
}

其他類(例如 ViewController)可以遵循 DownloaderDelegate 協議並成為 Downloader 的代理,以響應下載完成事件。

這兩個概念在 iOS 和 Swift 開發中都是核心的,用於很多不同的場景和功能。

強大的extension

在 Swift 中,類別 (class)、結構體 (struct)、列舉 (enum)、或者協定 (protocol) 都可以使用 extension 來增加功能。這是 Swift 中一個非常強大的功能,使得你可以將類別或結構體的定義分散到多個區塊,使其更具組織性和可讀性。

以下是使用 extension 的一些常見原因:

  1. 組織性: 你可以使用 extension 來組織你的程式碼,將相似的功能或者與某個特定主題相關的方法放在一起。
  2. 遵循協定: 如果你的類別需要遵循某個協定 (protocol),你可以使用 extension 來隔離所有與該協定相關的實現。
  3. 可讀性: 將類別或結構體分成小區塊可以提高程式碼的可讀性。
  4. 重用和模組化: 你可以定義多個 extension,並將它們放在不同的檔案中,以便於重用或者模組化。

在你給出的例子中,原始的 WebRTCClient 類別可能已經有了一些基本功能。然後,通過使用 extension,增加了關於視頻控制的功能。這種方式可以讓每個 extension 專注於一個特定的功能或者主題,從而使得整體的程式碼更加清晰和有組織性。

總的來說,Swift 中的 extension 功能允許我們對既有的類別或其他資料結構進行進一步的擴展,這樣可以使得程式碼更具組織性、可讀性,並且更容易維護。

分開寫 extension 和將其寫在一起,從功能的角度來看,並沒有區別。不過,程式碼的組織方式往往是為了達到更好的可讀性和易於維護。將不同的功能或與特定主題相關的方法分開在不同的 extension 中,可以幫助讀者和開發者更快地了解該區塊的主要功能,也更容易定位和修改相關的代碼。

使用guard控制流結構

guard 是 Swift 語言中的一個控制流結構,用於提前退出(early exit)方法或函數的執行,當某些條件不成立時。它是為了減少嵌套(nested)的深度和提高程式碼的可讀性。

以下是 guard 的一些特點:

  1. guard 之後必須跟一個條件,如果這個條件為 false,則執行 else 裡面的代碼。
  2. else 裡面必須有一個轉移控制語句,例如 returnbreakcontinuethrow,以確保退出當前的執行流程。
  3. 如果 guard 的條件為 true,則會繼續執行 guard 之後的代碼。

例如:

guard let dataToSend = alert.textFields?.first?.text?.data(using: .utf8) else {
    return
}

這段代碼試圖從 alert 的第一個文本欄位中獲取文本,然後將其轉換為 UTF-8 編碼的 Data 對象。如果其中任何一步失敗(例如,文本欄位為 nil、文本為空或轉換失敗),則整個條件為 false,並執行 else 裡面的 return 語句,從當前函數或方法中提前退出。

使用 guard 而不是嵌套的 if-let 可以使程式碼更加整潔、易讀,特別是當有多個條件需要檢查時。

在Swift中使用閉包

在Swift中,$0, $1, $2, … 是在閉包中使用的隱式名稱,代表閉包的第一個、第二個、第三個…參數。

peerConnection.transceivers
    .compactMap { return $0.sender.track as? T }
    .forEach { $0.isEnabled = isEnabled }

這裡有兩個閉包:一個是用於 compactMap 的閉包,另一個是用於 forEach 的閉包。

  1. 對於 compactMap 的閉包:$0 代表 peerConnection.transceivers 集合中的每一個元素,即每一個 RTCRtpTransceiver 對象。在這個閉包中,它試圖取出每個 transceiver 的 sender 的 track 並嘗試將其轉型為指定的 T 類型。
  2. 對於 forEach 的閉包:在 compactMap 運行之後,我們獲得一個包含符合指定類型 T 的軌道的集合。在 forEach 的閉包中,$0 代表這些軌道。閉包的作用是設置這些軌道的 isEnabled 屬性。
Posted on

UI進化論-行動裝置使用者介面設計

此文為閱讀此書的讀後心得:http://www.books.com.tw/products/0010471021

閱讀想法

這本書算是為專業的產品設計師所寫的,會講到許多有關於如何管理一個專業的設計團隊、制定開發流程、設計師頭銜討論,以及設計師如何訓練自己的藝術感等。並且也有說到一些相關電腦知識,例如掌上型行動設備的基礎知識之類。主要是以設計師的角度,去探討該如何去成為一個產品經理,然後開發一個產品。

也因為此書完全是以設計師角度去撰寫的,我是程式師,以想了解怎麼設計行動裝置的角度去看此書,很多地方會因身份角度不同而較無意義,不過或許對於設計師而言是一本很有意義的書。

重點筆記

使用者如何看待產品:這邊告訴我們使用者會怎樣看待我們的產品

  1. 合格的產品
    螢幕快照 2014-02-28 下午11.52.28
  2. 優秀的產品
    螢幕快照 2014-02-28 下午11.52.38
  3. 卓越的產品
    螢幕快照 2014-02-28 下午11.52.54

如何將設計商品化

  1. 做市場需求的觀察:包括人口特徵、使用行為、利潤潛力、價值觀、需求、動機、購買因素、態度、產品使用場合、地理位置
  2. 使用者研究:目標族群的身份、使用場合、怎樣會讓使用者感覺這是個好商品、為使用者和產品間建立感情的聯繫(例如遊戲打寶,因為有感情因素,使用者會願意花時間去練功)、觀察使用者想買這個APP的目的,要能符合他們想像中的目的。
  3. 研究目標市場的文化內涵

使用者分析與研究

分析方法

當我們想要做一個行動介面的產品設計圖,除了美術的畫面及色彩設計外,對使用者的分析及研究也非常重要,這一篇是這本書裡我覺得最喜歡的,它提供我們怎麼去設計一個行動介面的動線的方式。在此介紹如下:

  1. 任務分析法:把特定的任務分成好幾個階段,先想好自己的APP想要提供給使用者那些功能,然後把特定的功能分解成多個步驟。例如像穿襯衫,可以分解為:雙手抓住襯衫領子>把襯衫披在肩上>右手穿進袖子裡,從袖口伸出>左手穿進袖子裡,從袖口伸出>把後襟拉平>把左右門襟對齊
    這邊也列出一些心智模型工具:物理符號系統、諾爾曼模型、流程認知模型、SOAR模型、心智的社會模型、動力振盪理論模型、大腦協調學。
  2. 情境設定法:要包含角色和劇情。如在那邊、發生什麼事、怎樣的狀況下會想操作系統,不同情境下會需要不同的設計。例如會議中,靜音模式就很重要,或是在家裡,那就要有輕鬆、方便的感覺。
  3. 社會性研究法:研究一些社會的事件影響產品的事件。例如使用者的使用心得影響銷售的狀況、或是被影響等等。理解不同地域、文化背景、社會環境中的介面風格。

範例:MP3播放器

  1. 定義產品功能:明確定義出產品要有的功能有那些
    螢幕快照 2014-03-02 下午9.49.53
  2. 繪製互動設計流程圖:
    螢幕快照 2014-02-28 下午11.46.40
  3. 繪製介面原型:最簡單的版面元件位置配置
  4. 視覺設計:先設定APP主要要使用的色彩有那些(先配色),然後再繪製介面細節

如何讓圖型介面更有創意

  1. 更人性化
  2. 情感化因素不可忽視:應該要從美學本能和功能主義的瓶頸中跳脫,營造一種感覺,這種感覺能讓使用者把產品和品牌連繫在一起
  3. 互動特效的引入
  4. 產品=體驗=品牌
  5. 臨場的體驗決定購買意願

視覺設計的原則

  1. 介面清楚明瞭
  2. 讓機器幫助記憶,減少短期記憶的負擔
  3. 依賴認知而非記憶。例如列印圖示的記憶等
  4. 提供視覺線索
  5. 完善的視覺清晰度
  6. 介面的協調一致:如手機介面的按鈕排放、左鍵肯定右鍵否定或內容擺放位置
  7. 色彩與內容:整體設計不要超過五的色系,相近的色系表示相似的意思

制定設計流程

在本書的最後幾章一直在強調設計流程的重要性,其實這有點像程式開發的流程圖的設計師版本…XD

大概就是在強調一致的設計產出流程對設計師而言很重要,可以確保多個產品間的一致性,也可以提高產出效能。總而言之和程式的開發流程方法有點像。流程大概會劃分為十個步驟:

  1. 制定流程
  2. 確定工作內容
  3. 圖示風格:這本書前面有提到在設計圖示的風格上,可以分為兩個部份的會議去討論(也就是3與4)。
    第一次的會議採用Brainstorming的方式,Brainstorming的討論方式其實和這篇的原則類似,總之就是不要特別限定某種想法,讓點子越多越好,讓所有人發表所有他們所想的到的可能風格和idea,不去評斷idea的優劣,所有的討論內容越自由越好,隨意的讓點子發想。在會議之後,讓各個設計師去分別設計自己想要的圖示風格及理念想法
  4. 首次檢查:展開討論設計方向、設計師闡述設計概念、第一次設計評審會議。
    然後第二此的會議則和第一次完全相反,由某個人去引導會議,並且由每個人提出前一個會議中提出各個點子的優劣,並由主導者來決定以那個圖示為主。
  5. 介面風格:定義色彩、解析度、關鍵介面數量、介面元素、通用性等
  6. 互動特效:定義合適的互動效果、思考如何更好的表現互動模型、視覺化介面風格、並要考慮最終實現的難度
  7. 介面設計:設計師分別獨立完成
  8. 準備演練展示
  9. 互動模型:例如用flash去做一個demo檔案
  10. 最終提案:最後決定要用那一個介面
Posted on

套件管理工具CocoaPods介紹

這是1/9的cocoaHeads裡,SuperBil分享的套件管理工具。
之前小岡也有和我推薦過這個工具,當時沒有去深入研究如何使用。
這次與會完後,便開始試著學習使用這個管理套件。(裝完後心得:天呀!實在太好用了!必裝~)

分享資料

投影片:做自己的可可豆夾
錄影檔:CocoaPods

CocoaPods介紹

CocoaPods是一個管理套件的工具。

過去在開發app時,如果我們想要用一些第三方的Library,通常會要到GitHub下載專案到本地端,然後把它載入專案裡。這樣如果套件有更新時,都要手動更新,若是不同版本的ios要用到不同的library,又要手動去管理,會比較麻煩。

並且如果是直接把原始碼放到專案裡,會很容易和自己寫的code混在一起,管理和瀏覽都會較為困難。

CocoaPods就是用來管理這些第三方套件,使用CocoaPods之後,專案會變這樣:

螢幕快照 2014-01-12 下午4.48.50
要改成點選GourmentGroup.xcworkspace開啟專案

螢幕快照 2014-01-12 下午4.44.44
下方會多一個Pods的套件資料,裡面放的是所有使用到的套件

 安裝方法

這篇文章有非常詳細的方法:CocoaPods

比較要注意的是,我今天在安裝時,因為Podfile檔案所使用的編碼錯誤,會出現如下錯誤
incompatible character encodings: ASCII-8BIT and UTF-8 cocoaPods
後來我雖然把檔案改成utf-8,還是一直跑出同樣的錯誤。
後來才發現,如果有錯誤,要先把終端機關掉再打開,才會再一次執行。

接下來,如果要更新Podfile,到終端機打入
$pod update
就可以了!

投影片另外有講到podSpec,如果有在cocoaPods裡面沒有包含的Library
(現有的Library可到http://cocoapods.org/去輸入函式庫的名稱找有沒有現有的)
如果沒有的話(或者是自己製作的Library),就可以自己去寫spec
這邊有教學:Specs and the Specs Repo

參考資料

Posted on

AutoLayout介紹

投影片分享

過去的作法…

  1. 使⽤用frame和bounds去決定物件的位置和⼤小。
  2. 使用autosizing masks
    1. 設定當畫⾯面⼤大⼩小變動時,要固定 那些值(struts)。
    2. 在view的⼤大⼩小改變時,可以偵測 super view的⼤大⼩小改變去改變物 件的寬和⾼高的值(springs)。

AUTOLAYOUT和AUTORESIZING MASK的區別

Autoresizing Mask是AutoLayout的⼦子集。 AutoLayout更多的功能

    1. 指定任意兩個view的相對位置
    2. 可指定⾮非相等約束(⼤大於或者⼩小於等)
    3. 可以設定約束的優先級

WHAT IS AUTO LAYOUT

一種基於約束的,描述性的佈局系統。 Auto Layout Is a Constraint-Based, Descriptive Layout System.

      • 基於約束 – 以所謂相對位置的約束來定義的
      • 描述性 – 使⽤用接近⾃自然語⾔言的⽅方法來進⾏行描 述
      • 佈局系統 – 設計界⾯面的各個元素的位置。

使⽤用約束條件來描述佈局,view的frame會依據這 些約束來進⾏行計算。
Describe the layout with constraints, and frames are calculated automatically.

影片分享

Posted on

在Windows下產生.p12及.mobileprovision

在 Windows 產生憑證簽名要求

對 Windows 開發人員而言,最簡單的方法是取得 Mac 電腦上的 iPhone 開發人員憑證。不過,他們也可以在 Windows 電腦上取得憑證。首先,使用 OpenSSL 建立憑證簽名要求 (CSR 檔):

  1. 在 Windows 電腦上安裝 OpenSSL (移至http://www.openssl.org/related/binaries.html,或直接在此下載openssl-0.9.8k_X64)。
    開啟 Windows 命令工作階段,然後使用 CD 命令切換至 OpenSSL bin 目錄 (例如 c:\OpenSSL\bin\)。在命令列輸入以下命令以建立專用密鑰:
    openssl genrsa -out mykey.key 2048
    儲存此專用密鑰。您稍後將會用到它。使用 OpenSSL 時,請勿忽略錯誤訊息。OpenSSL 即使產生錯誤訊息,可能仍會輸出檔案。但這些檔案可能無法使用。如果發生錯誤,請檢查您的語法並重新執行命令。
  2. 在命令列輸入以下命令以建立 CSR 檔:
    openssl req -new -key mykey.key -out CertificateSigningRequest.certSigningRequest -subj “/emailAddress=yourAddress@example.com, CN=John Doe, C=US”
    以您自己的值取代電子郵件地址、CN (憑證名稱) 及 C (國家/地區) 值。

至APPLE申請.cer檔案

  1. https://developer.apple.com/membercenter/index.action以開發者身份登入。
  2. 選擇Certificates, Identifiers & Profiles,如下圖
    2014-01-07_153638
  3. 選擇Certificates
    2014-01-07_153659
  4. 接著按右上角的+
    2014-01-07_155542
  5. 身份選【iOS App Development】
    2014-01-07_155602
  6. 在最後會要求上傳.certSigningRequest,選擇剛剛在【在 Windows 產生憑證簽名要求】所產生的檔案,按確認。
    2014-01-07_155713
  7. 下載.cer檔
    2014-01-07_155843

將開發人員憑證轉換成 P12 檔案

  1. 將從 Apple 收到的開發人員憑證檔案轉換成 PEM 憑證檔案。從 OpenSSL bin 目錄執行以下命令列陳述式:
    openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM
  2. 現在可以根據 iPhone 開發人員憑證的密鑰及 PEM 密鑰,產生有效的 P12 檔案:
    openssl pkcs12 -export -inkey mykey.key -in developer_identity.pem -out iphone_dev.p12

產生.mobileprovision檔案

  1. 首先先產生一個APP的ID(已註冊過1~2項可跳過),選左側的”Identifier=>App IDs”,註冊一個APP的ID。
    2014-01-07_160759
  2. 填寫你要做的APP的前置字等識別,若是只想練習則選”Wildcard App ID”,然後Bundle ID填入”*”
    2014-01-07_161119
  3. 接著註冊你的測試機(已註冊過3~5項可跳過),再選左邊側欄的Devices=>All,新增開發機的UUID
    2014-01-07_162122
  4. 打開iTunes,連接iPhone,打開摘要頁,點紅框處的序號一下,會變成顯示UUID,把它記下來。
    2014-01-07_162323
  5. 回到網頁,把上面的UUID填入下面UUID那欄,並且為這隻手機取個名字
    2014-01-07_162508
  6. 現在要去產生.mobileprovision檔案。點選左邊側欄的”Provisioning Profiles”,接著按右上的+號新增一個Profiles
    2014-01-07_160633
  7. 身份選擇【iOS App Development】
    2014-01-07_160650
  8. App ID選擇剛剛所產生的ID
    2014-01-07_161714
  9. 選擇剛剛產生的certificates身份
    2014-01-07_161843
  10. 選擇要測試發佈的手機
    2014-01-07_163645
  11. 為這個發佈設定命名
    2014-01-07_163655
  12. 下載.mobileprovision檔案,完成。

在Flex裡設定發佈檔案

  1. 在專案點右鍵,選Properties,在此選擇要使用的檔案
    2014-01-07_164424
Posted on

UITableView的小問題

紀錄一下今天開發我的APP時遇到的小問題,
因為要使用UITableView,發現UITableView放在UIView裡時,
若要使用static cells是不能直接使用的。

當我們要用UIView,裡面有放一些自己的東西,再加上一個Static cells的UITableView時,
會發現雖然在storyboard裡能夠正常的顯示表格的樣子,如下圖
螢幕快照 2013-12-11 下午6.28.52
但是當執行出來卻無法顯示已設定好的static cells,而會顯示為一片空白,如下圖
螢幕快照 2013-12-11 下午6.31.55
查問Google大神後,在這邊有看到文章有相關的建議,也就是要我們不要實作下面這三個方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
}

不過,我檢查過後,我並沒有設定這三種方法,但是還是一樣無法正常顯示定義好的static cells,
最後這篇文章解決了我的疑問:How do I put a UITableView into a UIView
原來,我們不能夠直接在UITableView裡直接使用static cells,
如果必需在static cells的畫面裡加上其他元素,則應該要在該位置放入Container,然後Container連接至UITableViewController畫面,
如下圖:
螢幕快照 2013-12-11 下午6.41.42

這樣子便能夠正常的顯示在storyboard裡設定的static cells的樣式了!
螢幕快照 2013-12-11 下午8.15.14
PS:這邊有Container View與母容器互動的範例文章與範例專案

Posted on

iOS6以上控制螢幕旋轉

一般的設定方式

//支援Xcode 4.5
- (NSUInteger) supportedInterfaceOrientations{
//僅正面
// return UIInterfaceOrientationMaskPortrait;

//支援縱向 (利用 | 設定多參數)
// return UIInterfaceOrientationMaskPortrait
// | UIInterfaceOrientationMaskPortraitUpsideDown;

//支援橫向
//UIInterfaceOrientationMaskLandscape: 支援按鈕在左、按鈕在右
// return UIInterfaceOrientationMaskLandscape;

//支援四個方向
return UIInterfaceOrientationMaskAll;

}

- (BOOL) shouldAutorotate {
return YES;
}

TabBarController設定方式

假使今天要控制所有畫面中,某些可支援旋轉,某些不行,
在有使用Navigation Controller和TabBarController的狀況時,
則需要這樣設定:

  1. 勾選支援畫面旋轉
    螢幕快照 2013-12-11 下午3.36.26
  2. 在AppDelegate加上這段程式碼
    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        NSUInteger orientations = UIInterfaceOrientationMaskAll;
    
        if (self.window.rootViewController) {
            UIViewController* presented = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
            orientations = [presented supportedInterfaceOrientations];
        }
        return orientations;
    }
  3. 在tabBarController裡加上
    -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
        return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
    }
    
    -(NSUInteger)supportedInterfaceOrientations{
        if (self.selectedViewController)
            return [self.selectedViewController supportedInterfaceOrientations];
    
        return UIInterfaceOrientationMaskPortrait;
    }
    
    -(BOOL)shouldAutorotate{
        return [self.selectedViewController shouldAutorotate];
    }
  4. 支援旋轉的子畫面加上
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    - (BOOL)shouldAutorotate
    {
        return NO;
    }
    
    - (NSUInteger)supportedInterfaceOrientations
    {
        return UIInterfaceOrientationMaskPortrait;
    }
  5. 要支援旋轉的子畫面加上
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        return YES;
    }
    
    - (BOOL)shouldAutorotate
    {
        return YES;
    }
    
    - (NSInteger)supportedInterfaceOrientations
    {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }

Navigation Controller設定方式

若要控制在Navigation Controller之下的單獨畫面是否支援旋轉,則需要在Controller裡加上這段

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return [self.visibleViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

- (BOOL)shouldAutorotate {
    return [self.visibleViewController shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.visibleViewController supportedInterfaceOrientations];
}
Posted on

iOS app security - 分析和防範

講者 :Hokila
mail:hokila.jan@splashtop.com
blog:josihokila.blogspot.com
FB:fb.me/hokilaj

這是10/17分享的第一個講者,在分享有關app的安全上攻防的相關議題
因為這是我第一次參加cocoahead聚會,誤信了google map而迷路,遲了半小時入場,因此有部份內容沒有聽完整>”<
幸好後來找到Hokila很好心的預錄了當天的內容,在投影片最後一頁的QR code裡(有列在參考資料裡)。

ps:報名網頁的地址『台北市大安區敦化南路一段205號6樓600室』,打入google map會出現在忠孝復興站@@
說到這,當天我到會場時,有另一個漂亮女生也遲到,我就和她打招呼,結果她問我:妳也是用google map嗎?
嗚哇~所以不只我一個人這樣阿!(握手

今天Hokila講的內容大致如下:

  1. iOS app 資料結構
    在一個APP裡面大概會有幾個資料夾
    2013-10-29_105710
    MyApp.app裡面會存放一些APP會用到的照片、XAB、貼圖(PVR)或素材PNG、JPG等檔案(裡面的值無法修改)。
    Documents是建議存放永久性資料的地方,我們可以在裡面創建、修改、刪除要永久存放的檔案,如DB工具、抓影片放裡面,好處是只要plist裡宣告可以file share的話,他會可以用iTune打開來。PS: 這個資料夾會被iCloud自動備份。
    Library則是較為複雜的資料夾裡面一般會有下面這些資料夾

    1. Application Support:也是放一些設定檔的地方,它不會不見
    2. Cache:不會備份,存放可以再次從網路上下載的資料(每隔一段時間會清掉,何時清也不確定)
    3. Cookie:存放webView的Cookie,要注意的是這個cookie和safari瀏覽器的並不一樣。
    4. Preferences:放使用者相關設定檔的地方(NSUserDefault)

    tmp這個地方,重要的東西千萬不要放在裡面,因為只要每一次NSTemporaryDirectory重新restart時都會清掉,一般講者都是放download到一半的檔案,下次app開啟時再繼續download。

  2. 這邊也有提到可以去觀察對方的plist檔案來看他們的設定(如url schemes、document types )
  3. Console log:可以到此下載(http://support.apple.com/kb/DL1465)這個軟體。
    剛剛隨意的載下來玩了一下,這邊有使用說明(請按此
    感覺蠻好玩的,可以用它來看到app沒有埋好的log、framework⾃自⼰己帶的log、system notification、memory warming
    螢幕快照 2013-10-29 下午9.16.41
    因此,在用framework時或是寫code時,要注意是不是有丟出什麼log訊息。
    或是播影片時,把影片暫停、改全螢幕等等,有些會吐一些log出來,所以有時如果不知道別人怎麼做的,可以去觀察那個APP的log紀錄,把關鍵字丟到google查,或許可以查到一些端倪。
    另外在這邊也可以看到memory leak,不過只能知道有沒有memory leak的狀況,而無法知道是為什麼造成的。
  4. 接下來是資料儲存的部份,很多時候,我們會將資料儲存在Library>Preferences,但若我們打開資料夾,會可以看到plist檔,並且key和value值都是明碼,這是非常危險的。(例如fb會在裡面有使用者的資料)
    螢幕快照 2013-10-30 上午12.50.31
  5. 把資料放到keychain裡面,某app存的資料,另一個app也可以拿出來,並且有經過加密。(不過講者說可用keychain_dump解出裡面的table來)
  6. 另外可以使用charles來觀察網路狀況,這個工具我在開發flash也時常用到,非常好用。個人推薦map local和一個可以控制流量的功能
    螢幕快照 2013-10-30 上午12.55.33 用本機檔案去替代伺服器上的檔案
    螢幕快照 2013-10-30 上午12.55.51 控制下載流量
    那要如何讓CHARLES可以偵測到IOS上APP的HTTP request呢?
    首先我們要設定proxy,然後在iphone上設定代理伺服器
    2013-10-30_1114272013-10-30_111443
    在這邊講者也列出了其他類似的工具:
    ZAP (Mac Windows) Free:一個open source的工具
    Fiddler (Windows) Free
    Wire Shark (Mac Windows) Free:比較老牌的,講者覺得有點難用
  7. 因此我們在分析一個APP的時候,至少要分析下面幾個項目
    ● device screen
    ● console log
    ● plist、db裡面的狀況,一般會放在document裡面
    ● API request/response(送什麼出去、送什麼回來)
  8. 接下來是這次的講者們都很推薦的class-dump(在此下載)
    這個東西可以dump app的class,看看裡面宣告了什麼東西。
    但首先機子要先jb才可以連進去,用遠端登入的方式連進手機的位置
    螢幕快照 2013-10-30 上午1.16.42
    在手機上將專案抓下來
    螢幕快照 2013-10-30 上午1.18.41
    把它解壓縮
    螢幕快照 2013-10-30 上午1.20.07
    拿取版本,把它copy到
    螢幕快照 2013-10-30 上午1.22.40
    接下來就把app的資料拿出來看
    螢幕快照 2013-10-30 上午1.24.15
    便可以看到一些.h的檔案
    螢幕快照 2013-10-30 上午1.27.24
    如上圖,這時後大多的app都會有保護而導致dump失敗,這時候可以去一些ipa破解網站去下載app,通常從那些地方下載的都是已被破解,沒有保護的。否則就得自己去修改iap。
  9. IAP Free和LocalAppStore
    iGameGardin/八門神器=>搜尋記憶體位置,把該資料鎖定住,像是可以鎖值,像是血量什麼都不會變。
    FLEX:最可怕的一項功能,鎖定function回傳值,例如說-(BOOL)isTransactionSucess 一定回傳YES
  10. 在這邊講者提供了十項資安要注意的議題
    螢幕快照 2013-10-30 上午1.33.32
  11. 應對方法:
    • model的值和view的值不要一樣
    • 當model和server互相傳值時,不要太過相信彼此傳來的值,應還是要再做驗證
    • 加密的話,不要用hash

    範例:首先,不要使用get,如GET http://xxx.yyy/getUserData.php改成POST http://xxx.yyy/public
    讓所有的api有一個共通接口,然後用(string)call_file_name來判別要呼叫那個api,用(string)token來認證使用者的身份(此token會在幾分鐘後失效),然後設定數字編號來代表不同的status
    接下來就是使用ssl來傳遞資料,這樣就會有加密了
    或這樣還不放心,可以把傳的值的結構改成struct

  12. 在買東西時做double check。例:買東西時把剩的錢和數量回傳,用的時候可再確認是否有該產品,較好的時機點是在使用者有做任何互動時,再去檢查資料是否正確,而不要每隔幾分鐘就去檢查一次。
    存回db時做hash(不要直接把值原封不動存進去,因為很容易被搜尋修改)
  13. 加密方式選擇:md5、sha1已被破解
    AES-128和AES-256是最潮的(他加解密是同一個key),現在還無法被破解。
  14. public data可以不用加密,像折價券之類。但是private data一定要加密,例如密碼、交易記錄,就非常需要加密
  15. 不要只顧app端而已,要想到更多有關於server的東西,這樣才不會漏洞百出,更重要的是兩者的交互過程也要去思考,這樣整體的設計才會更完美。

參考資料:

  1. IAP攻防戰
  2. IAP攻防戰影片
  3. iOS app security
  4. 當天的影片
Posted on

Marty Cagan談產品系列影片心得

影片連結在此:  http://v.youku.com/v_show/id_XMzAyNTg0MDEy.html

Marty Cagan是eBey前副總裁,本篇文章截錄部份影片重點,若有興趣者請直接看原始影片喔!
(PS: 右邊有集數可以選擇)

產品的兩周理論

Marty Cagan認為一個產品負責人和設計者,應該在兩周之內,給使用者一個創意原型
但大多數的產品經理不會喜歡這樣做,
原因很簡單,因為他們總是認為此時提出的原型會不夠完善、有缺陷,
會希望將產品做到位之後再公開他們的產品。

但是Marty Cagan提到,只有將產品的設計公開出來給使用者看,才能夠做到心裡有數,
很多設計者或產品負責人很容易愛上自己的產品,
但愛情是盲目的,這很容易讓設計者忽略實際情況和使用者的反饋。

因此他認為應該在兩周之內提出一個產品原型,
他推薦使用high fidelity prototypes、user prototypes、live-data prototypes,
若時間來不及,也可以單就提出產品的設計圖如Balsamiq Mockups之類的,
很多時候,這樣才能夠最快檢驗出產品是否易於被接受。
即使此時的原形與最後產品產出可能會有極大的差異,但是及早搜集使用者意見,對產品的設計與開發是最安全的

克服心理障礙,將產品原型盡早提出給使用者看,
是產品團隊的一項重要技能。

什麼是基本產品

基本產品是所有軟體的基本核心概念,一個基本產品應要滿足下列條件:

  1. 客戶會願意購買該產品:最重要,也最難達成
  2. 使用者能夠很簡單的了解該怎麼使用,而不會一直要去理解”怎麼用”
  3. 有能力把產品開發出來

也就是說,一個基本產品應該要滿足:有價值、可用、可行的基本條件
但是要確定自己的產品是一個基本產品,則需要用prototypes和user testing來做測試。
我們可以用各種不同的原型模式(例如prototypes、live data prototypes、使用者面對面測試、以及sprint testing)去交叉比對、檢驗自己的產品是否符合上面的三項條件。

基本產品和最小化產品是有差異的,一般來說最小化產品指的是只具備基本功能的產品,
缺少可用性及外觀設計。
要記得客戶是不會花錢去購買半成品的,他們可能會試用,但不會購買。

產品探索團隊

這樣的團隊有三個重要角色

  1. 產品經理:定義產品功能
  2. 介面設計師:負責產品的易用性
  3. 程式設計師:最終決定這個構想是否可被實現

上面這三個角色應要一起合作、去定義一個基本產品:一款客戶願意購買、並能明白怎麼使用、也做的出來的產品

尤其是產品經理與介面設計師應該要密切的合作,一般我們會認為一個產品的計畫是由產品經理以及介面設計師一起共同構思。但有一個大秘密是:通常好點子都是程式設計師提出來的。因為程式設計師更了解怎樣的點子是可行的,他可以做到怎樣的功能。因此,雖然這些角色的功能不同,但每一項工作大家都必需參與,共同打造出基本產品。

也建議這三個角色在辦公室的設計上應該要放在一起,即使有職等上的不同,產品經理及介面設計師還是應該要讓他們能夠坐在附近以方便溝通。

用戶測試的類型

用戶測試是產品經理最重要的工作。

用戶測試分為兩部份:

  1. 使用者是否知道如何使用產品(可用性測試):做這個測試時,產品經理、程式設計師、介面設計師都應該在場。這個測試簡單、效果明顯,可以很快了解問題所在。
  2. 若用戶知道怎麼使用產品,那用戶願不願意使用產品,如果不願意,怎樣才能說服他們購買產品(價值測試):一般人會問你是否會願意購買此產品,但因為禮貌上,大部份的人都不會回答真實的想法。
    因此,Marty Cagan通常會問受測者:【你是否願意把這個產品推薦給同事?】,並用0~10的分數去代表非常不願意=>非常願意。除非他們給9~10分,否則都應該只是出於禮貌的敷衍你。在了解為什麼使用者不願意購買產品之前,不能停止用戶測試。
    在做價值測試時,當他們回答的結論是NO時,我們可能會發現這是因為受測者不是我們的目標客戶,還有其他人會需要。
    或者產品解決的問題不是他們需要的,這時就要改進產品,讓這個產品真正的可以解決使用者的問題,這會讓產品更有價值,通常這是解決方案出錯了,需要其他方式去解決問題。
    或者是營利模式錯誤。多留意這些關鍵點,他們往往是成功的關鍵。

測試方式的類型

  1. 使用者原型測試:快速製作prototypes,這個prototypes不能正常使用、也不能顯示正確數據,但只需要一兩天便可出爐。這可以快速的表達產品的想法給使用者並且觀察他們的反應,快速找到價值所在。這個工作由設計師就可以勝任,不需要程式人員。僅管是主觀的測試但效果明顯。
  2. 真實數據原型測試:可以得到真實的數據,會花到大把時間由程式人員撰寫,但是有些地方用戶原型測試是測不出的,因此這個步驟還是必需的。通常會同時採用對比測試,監控使用者瀏覽原型網站和舊有網站的流量,分為兩份數據,去做對比比對。

上述的兩種測試模型可以交叉使用,目的在花小錢辦大事,以避免製作出一個沒人想使用的產品。通常要做出一個完整的產品,會需要真實數據原型測試。但是想要快速的了解使用者感受或想法,使用者原型測試是最快速有效的。

定義產品經理

首先要了解,產品推廣並不是產品經理。定義市場需求、分析商業案例、搜集客戶需求是產品推廣的工作,很多人會認為直接把客戶需求丟給程式設計師開發就是產品經理,但其實這也不是。產品經理應要定義待開發任務,並定義任務優先權,然後開發團隊來完成這個任務。產品探索,就是要定義出基本產品。要做出好產品要有三個條件:

  1. 熟悉技術:只有了解技術、快速學習新技術,才能和技術團隊有良好的溝通。
  2. 熟悉UX(使用者介面設計):UX是好產品的必要條件
  3. 熟悉用戶和客戶:要做到這點,必需花大量的時間與使用者溝通及面對面的交流。
  4. 熟悉行業和市場

做到以上幾點,一個產品經理才有可能規劃出一個好的產品。

Posted on

XSpect簡介(一個AOP觀念實作的框架)

講者資料:小
投影片:XSpect
專案github位置:在此

這是10/17在cocoaHead聚會裡由講者所分享的一個他自己所寫的framework
因為他是在今日議程的最後一個講者,有些部份講的較為快速、簡短
有很多投影片也跳過去未說,在當下聽時只能大略聽到一個概念。

較引起我注意的地方,是他所提到的AOP的觀念與應用
也因為對他所說的AOP的觀念以及相關應對、程式設計方式感到蠻有趣的
這部份在會議結束後也花蠻多時間在研究該講者的code以及相關概念的研究

這是講者對AOP的解釋:

如果我要敘述 AOP 在幹嘛,或是說他的目的的話。我會說 AOP 是在用另一種方式去封裝變化,達到原本 OOP 做不到的事。這個變化就是 crosscutting concerns。
crosscutting concerns 就是為了一個邏輯,而散布在四處的程式碼。
AOP 就是要把他們全部包裝在一起。

下面的是其他網頁對於AOP的解釋

AOP全名Aspect-Oriented Programming,我們先來看看XXX-Oriented的意義,通常翻譯「XXX導向」,也就是以XXX為中心,例如中文中「客戶導向」就是以客 戶為中心,而「物件導向」(OOP:Object-Oriented Programming)就是以物件為中心的程式設計。

自然的,Aspect-Oriented Programming,就是「Aspect導向程式設計」,也就是以Aspect為中心的程式設計,但什麼是Aspect?中文直譯通常是「方面」,但這個名詞容易使人混淆。

牛津字典中的英英解釋對Aspect是:particular part or feature of sth being considerd.

所以Aspect在英文中不只有「方面」的意思,還有部份(part)的意思。中文中稱「就這個方面來說」,通常指的是「就這個角度來說」或 「就這個方向來說」,這個解釋不適用於AOP中的Aspect。如果英文中說from this aspect of sth,除了可以翻譯為上面兩句的意義之外,還可以翻作「就這個部份來說」。

以我們的前一個主題中的記錄(log)動作插入至HelloSpeaker物件的hello()中為例,我們說「就記錄這個部份」是不屬於 HelloSpeaker職責的,它被硬生生切入HelloSpeaker中,英文中我們可以說:The logging aspect of the “hello” method doesn’t belong to the job of HelloSpeaker.

所以以整個方法的執行流程來說,如果執行流程是縱向的,則記錄這個動作硬生生的「橫切」入其中,這個橫切入的部份我們就稱之為Aspect,它 是橫切關注點(crosscutting concern,一個concern可以像是權限檢查、事務等等)的模組化,將那些散落在物件中各處的程式碼聚集起來。

所以Aspect要用中文表達的話,適切一些的名詞該是「橫切面」或「切面」。AOP關注於Aspect,將這些Aspect視作中心進行設 計,使其中從職責被混淆的物件中分離出來,除了使原物件的職責更清楚之外,被分離出來的Aspect也可以設計的通用化,可運用於不同的場合。

然後這個是XSpect框架的架構圖
2013-10-28_135639

簡單來說,使用AOP的框架主要是為了把 crosscutting concerns 封裝在一起,提高程式模組化的程度。
以上圖來看,左邊的部份是原本的程式寫法,假如是一個儲存資料的函數如下,以原本的寫法來看,或許檢查值是否符合格式這部份的程式碼,在許多地方都可以用到,AOP主要便是去關心多個相似的流程的衡切面裡共通的部份,橫著去”跨越”多個程序裡使用的相同的功能。

log是一個標準的crosscutting concern範例,因為log的策略會牽動整個系統的每一個必需記錄的部份。
從橫向去記錄和登記所有classes和methods。

假如今天我們一個送交表單的程式碼,長的像是這樣:

function saveForm(){
...檢查欄位是否為空。
...檢查輸入的值是否符合格式。
[真正的儲存工作]
...後續相關操作(存LOG、紀錄操作等...)
...顯示儲存結果

}

我們可以看到,在這個函數裡面,只有[真正的儲存工作]是函數真正要做的事情,
剩的部份都是要處理商業需求的商業邏輯而寫的功能。這樣的程式碼撰寫方式,會造成寫出的程式只能專門用在單一工作,降低程式碼的重用性以及可維護性。

例如我們今天在程式的多個地方都需要使用LOG來紀錄所有的商務操作,
若今天這一項業務邏輯需要做修改或是移除,
那麼整個專案裡有加入這個LOG功能的部份,都需要同時去更新,這將會增加整個維護的成本。

因此,這個AOP的框架就是為了要將這些和業務相關的程式碼與原本的程式碼分開,
(商務邏輯,稱為Aspect,具體實作這些商務邏輯的程式碼則稱為Advice)
利用程式切入點Joinpoint(在應用程式執行時加入商務流程的點或時機稱之為Joinpoint),
並設定那些Aspect要用在那些Joinpoint裡,這個設定的定義稱為PointCut。

這邊的文章有AOP相關專有名詞的解釋:AOP觀念與術語,下圖則是講者大大的相關說明圖
2013-10-28_143641

這個框架可以讓商業邏輯獨立出物件之外,只需要設定Joinpoint便可以將之插入程式邏輯中。
如果對這個講者個框架有興趣的話,可至他的GITHUB上有更完整的使用手冊及範例: XSpect Tutorial

PS: 在當場講解時,有在場的大大提供了另一個很完整、並且功能與這一套框架相似的框架
叫作ReactiveCocoa,若對AOP有興趣者,也可以到這個網站去看看另一種方式的實作
https://github.com/ReactiveCocoa/ReactiveCocoa

 

相關資料

  1. XSpect, a lightweight library to make your code reusable and maintainable
  2. XSpect Tutorial
  3. AOP入門
  4. AOP觀念與術語