在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ iOS 中的行為
與四軸無(wú)人機(jī)的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測(cè)試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動(dòng)開發(fā)
Collection View 動(dòng)畫
截圖測(cè)試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個(gè)完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動(dòng)布局工具箱
動(dòng)畫
為 iOS 7 重新設(shè)計(jì) App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動(dòng)畫解釋
響應(yīng)式 Android 應(yīng)用
初識(shí) TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項(xiàng)目介紹
Swift 的強(qiáng)大之處
測(cè)試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計(jì)優(yōu)雅的移動(dòng)游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動(dòng)畫
常見(jiàn)的后臺(tái)實(shí)踐
糟糕的測(cè)試
避免濫用單例
數(shù)據(jù)模型和模型對(duì)象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場(chǎng)
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計(jì)的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計(jì)
置換測(cè)試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無(wú)人機(jī)項(xiàng)目
Mach-O 可執(zhí)行文件
UI 測(cè)試
值對(duì)象
活動(dòng)追蹤
依賴注入
Swift
項(xiàng)目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測(cè)試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場(chǎng)
游戲
調(diào)試核對(duì)清單
View Controller 容器
學(xué)無(wú)止境
XCTest 測(cè)試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動(dòng)畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲(chǔ)
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺(jué)
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫(kù)支持
Fetch 請(qǐng)求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語(yǔ)言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識(shí)別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過(guò)程

iOS 中的行為

作為一個(gè)開發(fā)者,我們致力于編寫簡(jiǎn)潔并且良好架構(gòu)的代碼。很多設(shè)計(jì)模式都可以實(shí)現(xiàn)這一點(diǎn),其中最好的一種是組合模式。組合模式使編寫出的代碼更易于遵循功能單一原則并且可以使我們的類簡(jiǎn)化。

為了替代一個(gè)功能上服務(wù)于不同模塊(就像 data sources 和 delegates )的繁冗的視圖控制器,我們將這些模塊劃分到不同的類中。這個(gè)視圖控制器就可可以僅僅負(fù)責(zé)這些類的配置和協(xié)調(diào)它們工作。畢竟,代碼寫的越少,調(diào)試和維護(hù)代碼的工作量就越少。

那么,行為究竟到底是個(gè)什么東西呢?

行為是一個(gè)負(fù)責(zé)實(shí)現(xiàn)一個(gè)指定功能的對(duì)象,比如你可以有一個(gè)實(shí)現(xiàn)視差動(dòng)畫的行為。

在這篇文章中所描述的各種行為將可以通過(guò)使用 Interface Builder 從而減少大量的代碼書寫,同時(shí)使與非編碼人員的協(xié)同工作更高效。然而,就算你不使用 Interface Builder,你也能從中獲益頗多。

許多行為只需要進(jìn)行設(shè)置,而不再需要寫額外的代碼,而對(duì)這些行為的配置可以通過(guò) Interface Builder 或者(相同設(shè)置方法的)代碼完整地實(shí)現(xiàn)。在大多數(shù)情況下,你不必再去用額外的屬性引用它們。

為何使用行為?

大多數(shù)的 iOS 工程中都有繁冗的視圖控制器類,因?yàn)榇蠹叶剂?xí)慣于將 80% 的應(yīng)用邏輯寫在這里。這卻是一個(gè)很嚴(yán)肅的問(wèn)題,因?yàn)樵谖覀兊拇a中視圖控制器這部分的代碼復(fù)用是最少的,并且很難對(duì)它們(代碼)進(jìn)行測(cè)試與維護(hù)。

這里描述的行為幫助我們避免這種場(chǎng)景,那這樣做可以給我們帶來(lái)什么好處呢?

更輕量級(jí)的視圖控制器

使用行為模式意味著將更多的代碼從視圖控制器中剝離到其他相應(yīng)的類中。如果你堅(jiān)持使用這種行為模式,你將最終實(shí)現(xiàn)一個(gè)非常輕量級(jí)的視圖控制器。舉個(gè)例子,我所寫的視圖控制器一般不超過(guò) 100 行代碼。

代碼復(fù)用

由于行為的職責(zé)單一,所以它可以非常容易地實(shí)現(xiàn)與特定行為和特定應(yīng)用邏輯的解耦。這使你可以在不同的應(yīng)用中使用相同的行為代碼。

可測(cè)試性

行為都是一些功能簡(jiǎn)單的類,其工作原理像一個(gè)黑盒。這意味單元測(cè)試很容易的完整的覆蓋這部分邏輯。你可以不需要?jiǎng)?chuàng)建真實(shí)的視圖,而只需提供模擬對(duì)象就能對(duì)它們進(jìn)行測(cè)試,

使非程序員能夠改變應(yīng)用邏輯

如果我們決定通過(guò) Interface Builder 來(lái)使用行為,我們就可以教會(huì)我們的設(shè)計(jì)師如何去更改應(yīng)用邏輯。設(shè)計(jì)師可以增刪行為并且修改參數(shù),而并不需要理解任何 Objective-C 的相關(guān)內(nèi)容。

這對(duì)工作流程有著巨大的好處,針對(duì)小團(tuán)隊(duì)來(lái)說(shuō)尤為明顯。

如何構(gòu)建一個(gè)復(fù)雜的行為

行為是一些簡(jiǎn)單的對(duì)象并且不需要太多定制的代碼,但是這里有一些概念可以真正的幫助行為更易使用,并且使用起來(lái)更具威力。

運(yùn)行時(shí)屬性

許多開發(fā)者輕視了 Interface Builder 甚至從來(lái)不去學(xué)習(xí)它,正因如此,他們通常不了解 Interface Builder 功能到底有多強(qiáng)大。

運(yùn)行時(shí)屬性是 Interface Builder 使用中最關(guān)鍵的特性之一。它們?yōu)槟闾峁┝艘粋€(gè)構(gòu)建自定義類甚至設(shè)置 iOS 內(nèi)置類的屬性的途徑。舉個(gè)例子,你是否曾為你的層設(shè)置圓角呢?你其實(shí)可以直接在 IB 中進(jìn)行簡(jiǎn)單的運(yùn)行時(shí)屬性配置來(lái)實(shí)現(xiàn)這一點(diǎn)。

http://wiki.jikexueyuan.com/project/objc/images/13-10.png" alt="" />

當(dāng)在 Interface Builder 中創(chuàng)建行為時(shí),你將重度依賴運(yùn)行時(shí)屬性去設(shè)置行為選項(xiàng)。最終將會(huì)帶來(lái)更多的典型運(yùn)行時(shí)屬性:

http://wiki.jikexueyuan.com/project/objc/images/13-11.png" alt="" />

行為的生命周期

如果一個(gè)對(duì)象是被 Interface Builder 所創(chuàng)建出來(lái)的,除非另外的一個(gè)對(duì)象對(duì)其強(qiáng)引用,否則它將會(huì)在被創(chuàng)建后立刻移除。這點(diǎn)對(duì)于需要一直在視圖控制器上工作的行為來(lái)講并不理想,這樣的行為會(huì)希望和視圖控制器擁有同樣的生命周期。

我們可以嘗試在視圖控制器上創(chuàng)建一個(gè)對(duì)行為強(qiáng)引用的屬性,但這同樣也不完美,有如下的理由:

  • 對(duì)于許多行為來(lái)說(shuō),你可能并不需要在創(chuàng)建并配置之后與其進(jìn)行交互。
  • 只是為了保持一個(gè)對(duì)象活躍而創(chuàng)建一個(gè)屬性,怎么說(shuō)都很悲劇。
  • 如果你想要移除一個(gè)指定的行為,你需要去清除那個(gè)無(wú)用了的屬性。

使用 Objective-C 運(yùn)行時(shí)解綁生命周期

不要選擇在視圖控制器上設(shè)置強(qiáng)引用來(lái)手動(dòng)綁定一個(gè)行為,取而代之,如果有需要的話,我們可以在配置過(guò)程中將行為自己賦值為視圖控制器的關(guān)聯(lián)對(duì)象 (associated object) 。

這意味著,如果我們需要移除一個(gè)指定的行為,我們只需要移除對(duì)應(yīng)的配置行為的代碼或者 Interface Builder 對(duì)象就可以了,而無(wú)需任何額外的改變。

實(shí)現(xiàn)如下:

@interface KZBehavior : UIControl

//! object that this controller life will be bound to
@property(nonatomic, weak) IBOutlet id owner;

@end

@implementation KZBehavior

- (void)setOwner:(id)owner
{
    if (_owner != owner) {
        [self releaseLifetimeFromObject:_owner];
        _owner = owner;
        [self bindLifetimeToObject:_owner];
    }
}

- (void)bindLifetimeToObject:(id)object
{
    objc_setAssociatedObject(object, (__bridge void *)self, self,   OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)releaseLifetimeFromObject:(id)object
{
    objc_setAssociatedObject(object, (__bridge void *)self, nil,    OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

在這里我們使得已關(guān)聯(lián)的對(duì)象對(duì)一個(gè)指定所有者的對(duì)象構(gòu)建了一個(gè)強(qiáng)引用。

行為事件

行為可以發(fā)送事件,這個(gè)特性非常有用,比如當(dāng)一個(gè)動(dòng)畫完成時(shí)我們就能收到通知。我們可以在 IB 里面通過(guò)構(gòu)建繼承于 UIControl 的行為類來(lái)啟用這個(gè)特性。一個(gè)特性的行為可以調(diào)用:

[self sendActionsForControlEvents:UIControlEventValueChanged];

這將允許你將行為關(guān)聯(lián)到你的視圖控制器里面的代碼。

基礎(chǔ)行為的例子

那么,什么樣的事情用行為實(shí)現(xiàn)會(huì)最簡(jiǎn)單呢?

這里我們將展示在一個(gè) UIViewController 類(不是自定義的類)中添加一個(gè)視差動(dòng)畫是一件多么容易的事情:

或者需要從你的相冊(cè)或者相機(jī)中獲取一張圖片?

進(jìn)階特性

上述的行為都很簡(jiǎn)單粗暴,但是,你是否也想知道當(dāng)我們需要更多進(jìn)階特性的時(shí)候需要做什么?只要肯做,行為的功能可以非常強(qiáng)大,讓我們來(lái)看看一些更復(fù)雜的例子。

如果你的行為需要一個(gè)代理,如 UIScrollViewDelegate ,你將會(huì)很快陷入一個(gè)困境,你無(wú)法在一個(gè)特定屏幕上擁有多余一個(gè)的行為。但是,我們可以通過(guò)實(shí)現(xiàn)一個(gè)簡(jiǎn)單多路代理(遍歷 NSInvocation 命令數(shù)組進(jìn)行匹配,譯者注)對(duì)象來(lái)解決這個(gè)問(wèn)題。

@interface MultiplexerProxyBehavior : KZBehavior

//! targets to propagate messages to
@property(nonatomic, strong) IBOutletCollection(id) NSArray *targets;

@end

@implementation MultiplexerProxyBehavior

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *sig = [super methodSignatureForSelector:sel];
    if (!sig) {
        for (id obj in self.targets) {
            if ((sig = [obj methodSignatureForSelector:sel])) {
                break;
            }
        }
    }
    return sig;
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    BOOL base = [super respondsToSelector:aSelector];
    if (base) {
        return base;
    }

    return [self.targets.firstObject respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    for (id obj in self.targets) {
        if ([obj respondsToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:obj];
        }
    }
}

@end

通過(guò)創(chuàng)建一個(gè)多路代理的實(shí)例,你可以把它作為一個(gè) scroll view (或者其他有代理的對(duì)象) 的代理,然后將代理的調(diào)用轉(zhuǎn)發(fā)給所有的行為對(duì)象。

總結(jié)

行為是一個(gè)非常有趣的概念,它可以簡(jiǎn)化你的代碼庫(kù),并可以允許在不同的應(yīng)用間實(shí)現(xiàn)許多代碼復(fù)用。它們(行為類)將會(huì)引領(lǐng)你在團(tuán)隊(duì)中與非編碼人員進(jìn)行更有效率的工作,并允許他們對(duì)應(yīng)用的行為進(jìn)行調(diào)整和修改。