2016年1月25日 星期一

建立CoreData之後,新增修改Model要刪掉重裝?

你是否有遇過新增修改CoreData欄位之後,雖然可以build過,但一執行app就crash的問題?(我有)

其實很簡單,因為你改了原來資料庫的結構,在執行時app找不到對應的欄位做操作,所以直接請你吃一個abort()
那麼要如何來解決這個問題呢?
請使用者刪掉重裝就好了........(誤)

解決方式,就是把你的修改當作一個新的版本的Model,再做新舊的版本之間的對應。
CoreData有提供一套Automatic Migration機制來做這件事。
步驟如下
1. 在NSPersistentStoreCoordinator的設定中開啟Automatic Migration選項(紅色部份)
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
            NSInferMappingModelAutomaticallyOption: true]
        
        do {
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
        } catch {
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason

            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
        
        return coordinator
    }()

2. 點選yourModel.xcdatamodeld,到上方選單Editor -> Add Model Version... 新增一個新版本

3. 點選yourModel.xcdatamodeld,到右側選單中把Model Version的current改為你的新版本,改好你會看到yourModel.xcdatamodeld下面的新版本上有一個小綠勾。

4. 在新版本對你的欄位做新增或修改,注意不要改動到原來的版本!那是拿來做參照的。

5. Run,crash bye bye

2016年1月24日 星期日

Dependency Injection 相依性注入(tw) / 依賴注入(cn)

我們這一行因為不像物理、化學、數學這一類的學科,具有概念上的困難度,
所以你會發現它總是不斷的發明高深的術語,來模糊一些簡單的概念,以便讓人們比較難以理解(這就是一例),其實應該把概念白話到易於理解,讓人們把精力放在實作上,對提升國家競爭力是比較有幫助的。

Dependency Injection的概念就是
把class裡面會與其他class相依的物件,都改從外部傳入。

目的是讓你的class的相依性更乾淨,其他人維護時能夠很明確的了解到你寫的class跟其他class之間的關係,另外,這樣做也能夠輕鬆地使用mockObject來unit test。



2016年1月21日 星期四

.gitignore檔範本

https://github.com/github/gitignore

//swift
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## Build generated
build/
DerivedData

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata

## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md

fastlane/report.xml
fastlane/screenshots

2016年1月20日 星期三

倍精度 DBL_EPSILON

電腦是用浮點數的方式來做小數的運算
既然是浮點數,那就一定有誤差。
倍精度就是表示使用double的時候會出現的誤差值
DBL_EPSILON 大約等於2.2204460492503131e-016 (視compiler而定)

意思是你在做浮點數比較的時候,必須把這個誤差值給考慮進去。
即使c = a + b
但你判斷a + b == c還是可能會錯,
因為 a + b 可能等於 c + "一個很小的數"

2016年1月15日 星期五

swift 2.0 備忘錄

//結構是value類型, 類別是reference類型
所以struct用let宣告之後,裡面的property都不可以再賦值。
String是struct NSString是class

//集合類型(Collection Types)
swift中的Array Dictionary Set資料結構都是值類型,在objective C中都是reference類型。

//檢查API是否可用(#available)
if #available(iOS 9, OSX 10.10, *) {
     //之後的API
} else {
    //其他的
}

//lazy先宣告而不初始化,等到第一次使用時再初始化。

//property observer: willSet & didSet
在初始化時不會被呼叫,被始化化之後才會發生效用。

//靜態property
你可以用static關鍵字加在var之前,就可以宣告靜態的property給所有動態物件共用。

//struct一但宣告出來就不能改動,如果要用func改property值,要加上mutating關鍵字
mutating func changeValue() { ... }

//下標(Subscript)
用subscript關鍵字來宣告下標,下標就是array[0]後面用中刮號的部份
你可用不同類型的參數宣告多組下標,就叫「下標多載」。

//class變成單純的基礎class,不像Objective-C中強制一定要繼承自NSObject。

//防止覆寫(Override)或繼承(Inheritance)
使用final關鍵字
你可以加在你的fun property subscript,那subclass就無法override;
如果你加在class上,那這個class就無法被繼承。

//當你初始化物件時,實際上就是去call類別的init()方法,如果你沒有實作init(),那swift會幫你呼叫一個預設的。

//外部參數名稱(External Parameter Names)
假設你在Test類別中宣告func changeValue(value y: Int) {x = y}方法
則你在呼叫的時候會看到:test.changeValue(value: 1)
其中value就是外部參數名稱
        y就是區域(Local)參數名稱

//指定建構器(designated initializer)與 便利建構器(convenience initializer)
指定建構器:init(params)
便利建構器:convenience init(params)
其中
init一定要呼叫到superclass的init。(rootClass不用)
convenience init可以呼叫其他的convenience init但最後一定要呼叫到init

//容錯建構器(Failable Initializer)
init?()會在無法正確初始化後,回傳nil給你。

//必要建構器(Required Initializer)
required init是用來表示你有某個init是在subclass實作init時,不可被忽略的。
如果你的subclass有修動或新增init,那required init是必需被實作的。

//解構器deinit {}
一個物件被Swift釋放之前,會先呼叫解構器deinit。deinit只被使用在class上。
當物件被設為nil的時候,會由subclass deinit 往superclass deinit的順序執行。

//weak reference/ unowned reference
如果兩個物件互相用stroong reference的property指著對方,就會產生reference cycle而造成memory leak,為了解決這個問題,swift提出兩種解法:
weak reference是用在optional的物件上,當一方被指為nil時,ARC機制會自動幫你把weak ref的物件指向nil,因此原物件會正常被釋放,程式也不會crash。
unowned ref是用在nonoptional的物件上,這種物件是你已知不會變nil的,所以當一方被釋放掉,memory不會leak,但你如果仍使用這個unowned reference,ARC不會幫你設為nil,蘋果文件上說保證你會crash,所以要自行避免這種情況。

//Type Casting for Any and AnyObject
swift提供兩個特殊的實體型態
AnyObject: 可以代表任意Class的實體
Any: 可以代表任何實體,例如func、Struct、Enum、Class。

//巢狀型態(Nested Types)
swift允許在Type當中再定義另一個Type,意思是說你可以在Class、struct、enum中再定義別的
Class、Struct、Enum。
用點運算來讀取,例如:Car.Door.Window.rawValue

//擴充(Extension)的作用就像是Objective-C中的類目(Category)
你只能幫原類別新增convenience init建構器,不能新增init
你可以新增實體方法與類別方法,但不能override原有方法。

//Protocol等於告訴型別說:你一定要實作ooxx東西!

//Class-Only Protocol
你可以限定你的Protocol只能讓Class使用,Struct跟Enum都不可以使用。
protocol ClassOnlyProtocal: class {
    //define protocol here
}

//Protocol Composition
用來指定多個protocol所組成的合成protocol
protocol <Protocol1, Protocol2>

//泛型(Generic)
用<>宣告,中間可以放任何名稱來當作"預留類型",一般慣用T,所以你會看到<T>來表示T是等下要用來換成你想到的類型。
struct Queue<T> {
    var items = [T]()

    mutating func enqueue(item: T) {
        items.append(item)
    }

    mutating func dequeue() -> T {
        return items.removeAtIndex(0)
    }
}

//Access Control
swift中只有三種Access Control
Public: 可以跨模組存取。
Internal: 為預設值,只可供模組內部的任意成員存取。
Private: 只能在該.swift中的成員存取,模組內部的其他file中的成員皆不可存取。

//不同進制的表示法
//二進制0b
let binaryInt = 0b1001
//八進制0o
let octalInt = 0o21
//十進制
let decimalInt = 17
//十六進制0x
let hexadecimalInt = 0x11

//位元運算子(Bitwise Operator)
NOT: ~
AND: &
OR: |
XOR: ^
左移(left shift): << 右移(right shift): >>

//運算如果發生溢位會出錯,但可以在運算子前加上&,來忽略溢位的部份,例如n = n &+ 1。

//運算子重載(Operator Overloading)
不同於C或Objective-C,C++或swift都可以做Operator Overloading,也就是你可以把+ - * / 做成你自己想要的功能。(但指派運算子(=)跟三元條件運算子(a ? b : c)不適用於Operator Overlading)。

//不只是可以重載既有的運算子,你也可以自定自己的運算子(Custom Operator)
prefix func ∑ {}
infix func + {}
postfix func π {}

//Error Handling
do {
    try 呼叫函式A
} catch 錯誤類型 {
    // 錯誤處理
}

func A(id: String) throw {
    guard var _ = id else {
        throw YourErrorType.errorN
    }
}

enum YourErrorType: ErrorType {
    case errorN
    case errorG(errorMsg: String)
}

Safari中暫存的flv影片在哪?

FlashTmp.dpciTl

會在./private/var/folders/這個路徑下的某一個T資料夾中
用FlashTmp.去找應該可以找到,再把副檔名改成flv即可。