Swift開發iOS應用過程中的問題和解決記錄


虛擬機里安裝OSX+XCode開發環境

用真機的請直接跳過這個部分。

主要是在VitrualBox里安裝mac系統和xcode,參考這篇教程,VirtualBox的版本是4.3.18 r96156,OSX版本是10.11 El Capitan,XCode版本是7.1 (7B91b)。

經過幾天的初步使用,感覺用虛擬機開發iOS基本能夠滿足要求,i5/8g/ssd的配置目測能達到真機70%的開發效率。主要存在的問題是:1)在寬屏上無法滿屏,兩邊會留有黑框,導致鼠標無法順利停靠在兩側 2)鍵盤敲擊頻率過快(約5Hz)時字符亂序出現在編輯器里,例如快速輸入“update”可能會得到“updaet” 3)虛擬機里的時鍾有可能不准,開發過程中偶爾有問題與此相關,需要考慮在內。

調整分辨率

以管理員方式啟動virtualbox和cmd命令行(重要!),執行下面的命令

cd "C:\Program Files\Oracle\VirtualBox"

VBoxManage setextradata "OSXElCapitan" VBoxInternal2/EfiGopMode 3 (注意,參數值 0=640×480, 1=800×600, 2=1024×768, 3=1280×1024, 4=1440×900, 5=1920×1200)

VBoxManage setextradata "OSXElCapitan" "CustomVideoMode1" "1360x768x32" (必須8的整數倍,我這里沒有成功)

參考鏈接:How to Guide for Mavericks VM on Mavericks

通過Virtualbox的遠程桌面連接到虛擬機

如果是NAT方式,目標地址是127.0.0.2,用guest里通過ifconfig查看到的10.0.2.xx是不行的。 遠程桌面的方式比直接使用虛擬機卡不少,作為開發使用並不實用。

修飾鍵

蘋果鍵盤與Windows鍵盤幾個修飾鍵的對應關系如下(在設置里可以改,這里是缺省情況):

Command鍵(花鍵 ⌘):對應windows鍵

Control鍵(⌃):對應ctrl鍵

Shift鍵(⇧):對應shift鍵

Option鍵(⌥):對應alt鍵

兩種鍵盤上這幾個修飾鍵物理布局最大的區別,在於Command鍵與Option鍵位置相反,可以去“偏好設置->鍵盤”里改過來,這樣切換兩種鍵盤時就比較容易適應了。

OSX

常用快捷鍵

官方文檔

跳到行首:“Command+左鍵”(Home鍵是跳到頁首)

結束任務:Command+Option+Esc

XCode7快捷鍵

代碼輔助:control+.

打開/關閉左側Navigator邊欄:Command+0(數字0)

打開/關閉右側Utilities邊欄:Option+Command+0(數字0)

快速打開文件(Open Quickly):Shift+Command+O(字母O)

轉到定義(Go to Definition):Command+鼠標點擊,或Option+Command+J

自動格式化代碼:Control+I(需要先全選,否則只格式化當前行)

調整模擬器大小:Command+3(50%)

Swift2

一些教程

官網:swift.org

官方文檔:The Swift Programming Language, 中文版

斯坦福免費視頻公開課:Developing iOS 8 Apps with Swift中文翻譯

國內視頻教程:精通iOS移動開發(Xcode7&Swift2)(免費,內容比較初級)

cocoachina專題:從今天開始學習Swift(大量資源鏈接)

常量

多數項目里都需要一些常量,java里通常定義在interface里,用swift時可以定義在一個struct里,作為靜態的存儲成員(static let)。

類型轉換

Double轉Int: Int(myDouble)

保留小數點位數

方法1(3.1415926->3.14, 3->3.00):

let i = 3.1415926
let str = NSString(format:"%.2f",i)
print("\(str)")  //will output 3.14

方法2(3.1415926->3.14, 3->3):

let nf = NSNumberFormatter()
nf.numberStyle = NSNumberFormatterStyle.DecimalStyle
nf.maximumFractionDigits = 2
print("\(nf.stringFromNumber(3.1415926))") //will output 3.14

時間

NSDate:相當於java.util.Date,獲得系統當前時間直接用NSDate()

NSTimeInterval:等同於double,NSDate.timeIntervalSince1970可以得到自1970年的秒數(注意不是java里的毫秒數)

NSDateFormatter:用來幫助在String與NSDate類型之間做轉換 參考

官方文檔頁

嵌套struct

注意一個地方,例如struct A里定義了struct B,實例化A時,必須先執行a.property1 = value1以后再執行b.a=a,否則會發現b.a.property1=nil。

UIView

所有控件的基類。

frame與bound的區別:frame是view的邊界,bound是view可以繪制的區域(bound是可以超出frame范圍的)。參考鏈接1 參考鏈接2

UITableView

基本使用:可以用ViewController里放TableView,也可以直接用TableViewController,參考How to make a simple tableview with iOS 8 and Swift

使用TableViewController時顯示Activity Indicator View(菊花)有問題,不太完美的解決方案見:UITableView Activity Indicator the Apple way,或使用第三方實現,例如下面會提到的SVProgressHUD

處理cell點擊事件,實現tableView:didSelectRowAtIndexPath方法即可,注意看清楚別實現成tableView:didDeselectRowAtIndexPath。 參考鏈接

點擊cell跳轉(假設從A跳到B):在storyboard里,直接從A的cell到B拖拽創建一個show類型的segue並指定此segue的identity,在A代碼里實現forSegue方法將要傳的參數賦值給B即可。

UICollectionView

相當於Android里的GridView,可以顯示多列數據,只是沒有cell的默認實現,也就是必須使用自定義cell。

要讓每個cell的寬度恰好等於collection view的一半,可通過實現下面的方法實現(參考鏈接):

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
  return CGSize(width: CGFloat(self.view.frame.size.width / 2), height: self.view.frame.size.height / 3) 
}

AutoLayout

假設有一個長寬都是150的image view,里面要加載一個網絡圖片(尺寸未知),要求網絡圖片能夠完整顯示在image view里且最長邊與image view的邊長相等,如何實現呢?參考以下鏈接:

被這個問題困擾了一段時間,以上幾個鏈接提供的方法都沒成功。后來發現,在使用autolayout的情況下,控件的width和height應該通過constraint指定(見下圖),配合contentMode=scalefit即可解決。

順便提一句,在storyboard里看到的控件位置並不一定是運行時的位置,因為autolayout情況下只考慮constraint,運行時的位置在storyboard里以橘黃色虛線表示(見下圖)。

Storyboard還提供了多設備預覽功能,使用方法是“打開 Main.storyboard ,然后選擇 View\Assistant Editor\Show Assistant Editor ,這時編輯區會分隔為兩部分。再點擊頂部導航欄中的 Automatic ,在彈出菜單中選擇 Preview ,最后選擇 Main.storyboard (Preview) ... 點擊預覽界面左下角的 + 按鈕,會彈出當前storyboard文件支持的各種尺寸的設備”(來源

關於"Relative to margins"選項,在xcode7里這個選項是默認勾選的,每個view默認有寬度為8的margin,可以通過“Editor->Canvas->Show Layout Rectangles”菜單項打開,margin位置顯示為藍色細線。舉例來說,當勾選了“Relative to margins”選項后,如果一個子view的leading space to 父view是0,運行時會看到子view距離父view的邊界還有8的空白區域(效果相當於android里給父view設置了8的padding)。這個缺省margin值可以通過下面的方法設置:

self.rootView.layoutMargins = UIEdgeInsetsMake(0, 50, 0, 0);

參考鏈接:

從此愛上iOS Autolayout 

Layout Margin Comes With iOS8

第三方依賴包

依賴包管理/Carthage

先安裝Homebrew(osx的包管理工具),然后通過Homebrew安裝Carthage(比cocoapods靈活,去中心,只支持ios8和以上版本)。

在工程目錄下新建“Cartfile”文件,並填寫要依賴的包,然后執行carthage update命令,此時如果提示“unable to find utility "xcodebuild", not a developer tool”,可使用"sudo xcode-select --switch"命令解決,這樣就下載了依賴包。為了讓xcode能用到carthage編譯的framework,先從Finder把剛才生成的.framework文件拖到工程的General -> Linked Frameworks and Libraries區域(在Navigator里點擊工程根目錄即可看到)里,然后在Build Phases里添加一個新內容是“/usr/local/bin/carthage copy-frameworks”的Run Script,並在Input Files里增加所需的編譯后的依賴包如“$(SRCROOT)/Carthage/Build/iOS/SwiftyJSON.framework”。 參考Carthage的Getting Start 

經測試還需要在工程的Build Setting -> Framework Search Path里添加“$(SRCROOT)/Carthage/Build/iOS”,否則build會失敗。參考資料

依賴包管理/CocoaPods

有些第三方依賴只支持cocoapods,所以也要裝一個cocoapods。cocoapods的資料比較多,例如這篇,也比較容易安裝使用。一個需要注意的問題是,執行pod setup命令后提示Setting up CocoaPods master repo要等很久,大約1小時。

在swift文件里使用object-c開發的庫,需要借助一個bridging文件,通常名稱是“項目名-Bridging-Header.h”。可以讓xcode生成這個文件,方法是在工程里創建一個空的Objective-C文件,最后一步時xcode會提示是否創建bridging文件,點YES然后再刪掉這個空文件即可。在bridging文件里使用類似#import <AFNetworking/AFNetworking.h>的方式包含依賴包。

如果pod install執行很慢,可能是pod更新spec時被牆,可以加--no-repo-update參數。參考鏈接

pod install --verbose --no-repo-update

還可以改用國內鏡像,例如:

pod repo remove master 
pod repo add master https://git.oschina.net/6david9/Specs.git 
pod reap list

無法安裝Realm:ios-charts依賴Realm,安裝時很慢(有時等待數小時無果,有時提示SSL Handshake錯誤),其實真正原因是Realm/core所在服務器被牆。可以通過1)使用VPN解決,或2)手工下載安裝core(參考Download core 0.96.0 failed),或3)使用國內鏡像(如果已經下載core失敗過需要清除緩存,參考Core occasionally cannot be downloaded from China)。

HTTP請求/遠程圖片

據說SwiftHTTP是個坑,暫時繞開,使用系統提供的NSURLSession簡單封裝一下。使用方法參考鏈接

iOS9里默認要求所有http請求都使用https,如果一定要用http,在工程的info.plist里修改“App Transport Security Settings -> Allow Arbitrary Loads”為true。

AFNetworking功能強大且被廣泛使用的Http庫,還帶有異步加載/緩存遠程圖片的功能;對應Swift版本的名稱是Alamofire

JSON

暫時使用SwiftyJSON,感覺還好,使用舉例:let json1 = JSON(["param1":1])。

下拉刷新/上拉翻頁

下拉刷新:iOS8起內置了UIRefreshControl可以方便的實現下拉刷新功能 用法

上拉翻頁/加載更多:暫時沒有發現原生的簡便方法實現,第三方庫倒是比較多,例如SVPullToRefreshMJRefresh

進度條

由於TableViewController顯示Activity Indicator有問題,目前在用SVProgressHUD作為替代方案。

折線圖/餅圖

ios-chart,項目主頁的Usage里說了一堆步驟其實都是針對手動安裝的,如果用cocoapods直接編輯Podfile添加pod 'Charts'再執行pod install即可,bridge都不用改,在自己的.swift文件里import Charts就可以使用了。不過我遇到一個編譯問題,ChartPlatform.swift這個文件編譯不過去,自己在文件結尾加了個空行解決。使用方面,一個比較好的教程見這個鏈接

經過試用,發現ios-charts畫時序圖(timeseries)比較麻煩,要自己做一些計算(參考)。

替代方案:Core Plot(側重科學繪圖),ios-linechart(使用簡單),JBChartView(來自Jawbone),BEMSimpleLineGraph(使用簡單)。

 

(未完,持續補充中)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM