[iOS] 響應式編程開發-ReactiveCocoa(二)


RAC實現圖片下載功能

在實現異步RAC下載圖片的過程中,需要注意以下幾點:

  •  通過 NSURLConnection 對象的 +(RACSignal *)rac_sendAsynchronousRequest:(NSURLRequest*)r 可以創建網絡異步下載的信號量對象;

  •  在執行完成異步下載過程后,需要通過 [x deliverOn:[RACScheduler mainThreadScheduler]] 操作將方法返回到主線程進行執行;

@implementation ViewController
{
    RACCommand  *loginCommand;
    RACSignal   *loginSignal;
}


- (void)awakeFromNib
{
    //創建網絡圖片下載的URL對象
    NSURL *url = [NSURL URLWithString:@"http://pica.nipic.com/2007-11-09/2007119124513598_2.jpg"];
    
    //創建網絡圖片請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //實例化命令操作對象
    loginCommand = [[RACCommand alloc] initWithSignalBlock:^(id sender) {
        
        //通過NSURLConnection的+方法,創建異步返回信號量
        return [NSURLConnection rac_sendAsynchronousRequest:request];
    }];
    
    
    //信號量完成后的插座操作
    [loginCommand.executionSignals subscribeNext:^(RACSignal *x)
    {
        //將下載完成的圖片數據轉換成圖片對象后,在主線程賦值給imageView屬性
        [[x deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(RACTuple *tuple)
         {
             NSData *imageData = tuple.last;
             
             //imageView - UIImageView
             self.imageView.image = [UIImage imageWithData:imageData];

         }];
    }];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    //指定觸發命令操作
    //btn - UIButton
    self.btn.rac_command = loginCommand;
}
@end

 

如何使用ReactiveCocoa

目前大量的ios應用程序在開發的過程中,是通過用戶響應來改變應用程序狀態的。我們在這樣處理事件時,代碼往往會變得非常復雜,需要用到大量的回調和狀態變量來完成回調函數的功能。

其實像 UI回調 、 網絡響應 、 KVO通知 等等,會有很多的共同之處,都需要回調函數進行處理功能。

那么RACSingal統一了這些不同的API,方便他們能夠組合在一起完成復雜的功能。

我們先看一下下邊的代碼:

@implementation ViewController
{
    MethodManager *manager;
}

- (void)awakeFromNib
{
    manager = [MethodManager sharedManager];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(loggedOut:) name:@"loggedOut" object:manager];
    
    [self.usernameTextField addTarget:self action:@selector(textDelegate) forControlEvents:UIControlEventEditingChanged];
    [self.passwordTextField addTarget:self action:@selector(textDelegate) forControlEvents:UIControlEventEditingChanged];
    [self.logInButton addTarget:self action:@selector(didClickLogin:) forControlEvents:UIControlEventTouchUpInside];
}

- (void)dealloc {
    [NSNotificationCenter.defaultCenter removeObserver:self];
}

- (void)textDelegate {
    BOOL textFieldsNonEmpty = self.usernameTextField.text.length > 0 && self.passwordTextField.text.length > 0;
    BOOL readyToLogIn = !LoginManager.sharedManager.isLoggingIn && !self.loggedIn;
    self.logInButton.enabled = textFieldsNonEmpty && readyToLogIn;
}

- (IBAction)didClickLogin:(UIButton *)sender {
    [manager logInWithUsername:self.usernameTextField.text password:self.passwordTextField.text
     success:^{
         self.loggedIn = YES;
     } failure:^(NSError *error) {
         [self presentError:error];
     }];
}

- (void)loggedOut:(NSNotification *)notification {
    self.loggedIn = NO;
}

@end

  如果是RAC代碼的話,我們就可以使用如下代碼:

@implementation ViewController
{
    MethodManager *manager;
}

- (void)awakeFromNib
{
    manager = [MethodManager sharedManager];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    RAC(self.signButton, enabled) = [RACSignal
                                      combineLatest:@[
                                                      self.password.rac_textSignal,
                                                      self.confirm.rac_textSignal,
                                                      RACObserve(manager, signing),
                                                      RACObserve(self, signing)
                                                      ] reduce:^(NSString *username, NSString *password, NSNumber *loggingIn, NSNumber *loggedIn) {
                                                          return @(username.length > 0 && password.length > 0 && !signing.boolValue && !signing.boolValue);
                                                      }];
    
    [[self.signButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *sender) {
        
        RACSignal *signingSignal = [manager logInWithUsername:self.usernameTextField.text password:self.passwordTextField.text];
        
        [signingSignal subscribeError:^(NSError *error) {
            [self presentError:error];
        } completed:^{
            self.signing = YES;
        }];
    }];
    
    RAC(self, signing) = [[NSNotificationCenter.defaultCenter rac_addObserverForName:@"LOSignNotification" object:nil] mapReplace:@NO];
}

@end

 

導入ReactiveCocoa框架

打開 終端(Terminal) 工具。進入到自己的工程目錄文件夾下:

haohao:TomRAC lewis$ vi Podfile

其中 TomRAC 是公司項目文件夾名稱

創建完成 Podfile 文件后,要在該文件內輸入如下內容:

platform :ios, '6.0'
source 'https://github.com/CocoaPods/Specs.git'
target 'TomRAC' do
pod 'ReactiveCocoa', '~> 2.3.1'
end

通過命令保存 Podfile 文件后,在 終端(Terminal) 輸入如下命令進行下載配置 ReactiveCocoa 框架:

pod install

然后就會看到熟悉的下載提示:

Analyzing dependencies
Downloading dependencies
Installing ReactiveCocoa (2.3.1)
Generating Pods project
Integrating client project
 
[!] From now on use `TomRAC.xcworkspace`.

打開工程后就能夠使用ReactiveCocoa框架了。

現有個空工程,需要跳過配置步驟想先使用的同學可以先進行下載使用。

 


免責聲明!

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



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