2016年2月19日 星期五

如何在自己的專案中加入其他專案

有時候你想要引用一個第三方專案,但卻發現它沒有整理到Carthage或Cocoapods中,
這時候你要怎麼辦呢?

其實只有一句話:「將它的xcodeproj檔拉到你的專案的navigator之中,再把相關的dependency設定好」就行了。

設定的方式也很簡單,(當下使用版本為Xcode 7.2.1)

  1. 到專案檔的Build Phrases頁籤下的Target Dependencies中按"+"加入你要用的第三方專案的target。
  2. 到專案檔的General頁籤下的Embedded Binaries中,加你的第三方framework,這時候下面的Linked Frameworks and Libraries 應該會順便自動加入,如果沒有的話,你再將它手動加入一次就好。
簡單二個步驟,Build Success!



2016年2月18日 星期四

Carthage好用到回不去了

Carthage跟Cocoapods不同,它是單純的幫你把framework準備好,要用的你再自己拉進去你的project之中,再也不用看到額外的workspace檔案了!

跟Cocoapods 一樣,Carthage也需要一個Cartfile來告訴它你想生成那些framework。
不過因為Carthage目前只支援git,所以格式也相對簡單
github "ReactiveCocoa/ReactiveCocoa"
這樣就可以抓到最近版的framework,但你也可以指定你要的版本或是branch:
# Require version 2.3.1 or later
github "ReactiveCocoa/ReactiveCocoa" >= 2.3.1

# Require version 1.x
github "Mantle/Mantle" ~> 1.0    # (1.0 or later, but less than 2.0)

# Require exactly version 0.4.1
github "jspahrsummers/libextobjc" == 0.4.1

# Use the latest version
github "jspahrsummers/xcconfigs"

# Use the branch
github "jspahrsummers/xcconfigs" "branch"

# Use a project from GitHub Enterprise
github "https://enterprise.local/ghe/desktop/git-error-translations"

# Use a project from any arbitrary server, on the "development" branch
git "https://enterprise.local/desktop/git-error-translations2.git" "development"

# Use a local project
git "file:///directory/to/project" "branch"
等你準備好Cartfile之後,用terminal在你的專案資料夾鍵入
carthage update --platform iOS
它就會幫你把framework建好放在./Carthage/Build的資料夾中(framework的source code會在./Carthage/Checkouts中)。
你將Build資料夾中的framework拉進你的Xcode的Linked Frameworks and Libraries之中就可以用了。

最後,雖然這樣就可以使用,但如果你想要Run在Simulator時會發現出現如下的錯誤
Command /bin/sh failed with exit code 1

所以如果你想要用Simulator做測試的話,要多做下列的步驟:
  1. 到你的application的target頁面選Build Phrases頁籤。
  2. 按下"+"選"New Run Script Phase"新增一個Run Script。
  3. 在shell下的黑色區域,輸入下列指令/usr/local/bin/carthage copy-frameworks
  4. 最後在input files把你的frameworks的部份加進去
$(SRCROOT)/Carthage/Build/iOS/YourFramework1.framework
$(SRCROOT)/Carthage/Build/iOS/YourFramework2.framework

大功告成,現在你可以看到Simulator彈出來嘍!

P.S.你也可以在update時使用下列參數
carthage update --platform iOS --use-submodules --no-use-binaries

第一個參數說明你只要建立iOS平台的資料夾。
第二個參數讓這個專案以git submodules的型態加入。
第三個參數確保你的framework是在本機Build出來的。

P.S.你也可以用bootstrap指令來抓frameworks
bootstrap和update的差別在於:
update是從你寫的Cartfile中抓取你想到的framework之後,才建立Cartfile.resolved檔案。
而bootstrap是不管你的Cartfile,直接去讀上次建立的Cartfile.resolved檔案,來抓frameworks。

2016年2月17日 星期三

NSLog出所在的function名稱

//在obj-c的NSLog中可以用c++的__PRETTY_FUNCTION__
NSLog(@"%s", __PRETTY_FUNCTION__);
//show
-[YourCurrentClassName yourCurrentFunctionName:]

//在swift中還不行用,stackOverFlow上有人提出這個方式來解決
func pretty_function(file:String = __FILE__, function:String = __FUNCTION__, line:Int = __LINE__) {
    print("file:\(file.lastPathComponent) function:\(function) line:\(line)")
}
P.S. 現在swift的String已經把lastPathComponent拿掉,所以要改為下面的方式
func pretty_function(file:String = __FILE__, function:String = __FUNCTION__, line:Int = __LINE__) {
    print("file:\((file as NSString).lastPathComponent) function:\(function) line:\(line)")
}

#import V.S. @import

在c++中只有#include,這個預處理指定可以幫你把另一個.h的內容都複製一份過來你的檔案中,但這會有一個問題,你可以重覆複製了多份相同的.h過來。
於是obj-c中新增了#import來解決這個問題,#import會在複製過來.h之前先判斷是否已經複製過了,這樣一來可以保證你的檔案中只會有一份其他的.h。

但是這樣一來還是有個問題沒有解決:相同的.h引用到太多不同的檔案,造成編譯上的時間浪費,也會增加檔案的容量。

既然如此,那為什麼不找一個地方,先把這些要引用的.h先編譯好,放過去直接給你的檔案呼叫呢?
.pch檔就是在做這種事,你可以把你要預編譯的.h都放在這裡,在你的每一個檔案中都可以直接使用,這樣就可以加快編譯的速度。
但這裡又有一個問題,如果你的每一個.h都可以被你的任一檔案給呼叫,那你引入的module間的關係不就大亂了嗎?
於是Apple加入了Modules機制,LLVM5.0中加入了@import這個新語法,讓你可以像用#import一樣引入不同的.h,但這些.h的module都是被預編譯好的等著你來呼叫,如此一來既加快了編譯的速度,又可以保持引用.h的安全性。

P.S. 目前這個Modules機制僅適用於Apple原生的module(不適用第三方或是你自己編寫的module)。
P.S. 在iOS 7 SDK以上,預設使用Modules機制並且會將你的#import轉成@import

固定圖型邊框,拉伸中間部份:resizableImageWithCapInsets

這個方法最適合用於IM的對話框,

// Set resizeable image
        _balloonView.image = [self.balloonImageRight resizableImageWithCapInsets:_balloonInsetsRight];

其中_balloonInsetsRight就是你想要保留的inset部份,你可以將四個邊改為自己想要的數字。
_balloonInsetsRight = UIEdgeInsetsMake(BALLOON_INSET_TOP, BALLOON_INSET_LEFT, BALLOON_INSET_BOTTOM, BALLOON_INSET_RIGHT);

設定好之後,不論_balloonView這個imageView的尺寸怎麼變化,就只會影響到image中間,而不會影響到四周你設好的inset。

當然你也可以設定拉伸中間的方式是採用「重覆貼圖」或是「影像延伸」,這都可以在resizableImageWithCapInsets的其他參數中找到。

2016年2月8日 星期一

protocol oriented programming

他的功能就是abstract class可以達成,
而extension protocol也可以用base class達成。
但這些只有在class上可以用,
swift主打pop就是因為它可以用在struct跟enum上。