RAC


RAC中類的繼承關(guān)系

1.RACDynamicSignal:RACSignal:RACStream
2.RACSequence:RACStream
3.RACCompoundDisposable : RACDisposable
4.RACSubscriptionScheduler : RACScheduler
5.RACQueueScheduler : RACScheduler


RAC優(yōu)勢(shì)(提高開(kāi)發(fā)效率)

1.把target-Action/代理/通知/KVO統(tǒng)一封裝成信號(hào),即信號(hào)就可以實(shí)現(xiàn)這些功能。
2.監(jiān)聽(tīng)屬性的代碼少
3.代碼直觀,代碼復(fù)雜度減小m3u8
4.通過(guò)block降低代碼間的耦合


訂閱和訂閱者

  • subscribeNext:訂閱
    subscribeNext:^(id x) { }
  • subscriber:訂閱者,例如訂閱者調(diào)用sendNext方法谒出。
    [subscriber sendNext:responseObject];

25個(gè)事例+1個(gè)小項(xiàng)目幫助你解開(kāi)RAC的面紗


1.監(jiān)聽(tīng)UITextField內(nèi)容的輸入信號(hào)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類颤芬,在分類里面給UI控件擴(kuò)充了新的方法卫枝。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self Username];// 監(jiān)聽(tīng)UITextField內(nèi)容的輸入信號(hào)

}
-(void)Username{

    /*  1+2可以寫(xiě)成一行代碼
     [self.usernameField.rac_textSignal subscribeNext:^(id x) {/
     NSLog(@"%@",x);
     }];
     */
    
    // 文本信號(hào):監(jiān)聽(tīng)UITextField內(nèi)容的輸入
    RACSignal *textSignal = self.usernameField.rac_textSignal;// 1
   // 訂閱者block
    [textSignal subscribeNext:^(id x) {// 2
        NSLog(@"%@",x);
        
    }];
    
}

@end

截圖

101.1.gif

2.監(jiān)聽(tīng)按鈕的點(diǎn)擊信號(hào)(信號(hào)理解為事件)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *login;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類鱼辙,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
 
    [self  Login];// 監(jiān)聽(tīng)按鈕的點(diǎn)擊信號(hào)(信號(hào)理解為事件)
}

 -(void)Login{
    /* 1+2可以寫(xiě)成一行代碼
    [[self.login rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:
    ^(id x) {
        NSLog(@"%@",x);
    }];
    */
  RACSignal *clickSignal = [self.login rac_signalForControlEvents:UIControlEventTouchUpInside];// 1
    // 訂閱者block
    [clickSignal subscribeNext:^(id x) { // 2
        NSLog(@"%@",x);
    }];
}

@end

截圖

101.2.gif

3.取消按鈕的點(diǎn)擊信號(hào)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIButton *login;
@property(nonatomic,strong)RACDisposable *btnDisposable;
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類药磺,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self Dispose];// 取消按鈕的點(diǎn)擊信號(hào)煤伟。先點(diǎn)擊屏幕癌佩,然后再點(diǎn)擊按鈕,發(fā)現(xiàn)沒(méi)有打印便锨。因?yàn)辄c(diǎn)擊信號(hào)已經(jīng)取消了围辙,點(diǎn)擊多少次都不會(huì)打印。
}

-(void)Dispose{
    
   self.btnDisposable = [[self.login  rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.btnDisposable dispose];
}
@end

截圖

101.3.gif

4.信號(hào)的map方法

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類放案,在分類里面給UI控件擴(kuò)充了新的方法姚建。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    [self Map];// 信號(hào)的map方法
}

-(void)Map{
    // 文本信號(hào):監(jiān)聽(tīng)UITextField內(nèi)容的輸入
    RACSignal *textSignal = self.usernameField.rac_textSignal;
    // 調(diào)用map方法:更改訂閱者block輸出的參數(shù)的類型
    textSignal = [textSignal map:^id(id value){
    return [NSString stringWithFormat:@"username = %@",value];
    }];
    // 訂閱者block
    [textSignal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
}
@end

截圖

101.4.gif

5.信號(hào)的filter方法

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類,在分類里面給UI控件擴(kuò)充了新的方法吱殉。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    [self filterText];// 信號(hào)的filter方法
}
-(void)filterText{
    // 文本信號(hào):監(jiān)聽(tīng)UITextField內(nèi)容的輸入
    RACSignal *textSignal = self.usernameField.rac_textSignal;
    textSignal = [textSignal filter:^BOOL(NSString *value) {// 將(id value)改為(NSString *value),因?yàn)槲覀円呀?jīng)確定了輸入的內(nèi)容是字符串(即使輸入的是數(shù)字也行)
        NSLog(@"filter %@",value);
        // 當(dāng)輸入的內(nèi)容大于5時(shí)掸冤。才會(huì)調(diào)用訂閱者block
        return value.length > 5;
    }];
    // 訂閱者block
    [textSignal subscribeNext:^(id x) {
        NSLog(@"輸出%@",x);// 只有當(dāng)輸入的個(gè)數(shù)大于5時(shí)才打印這行內(nèi)容
    }];
    
}
@end

截圖

101.5.gif

6.組合信號(hào)combineLatest:reduce:

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UIButton *login;
@property (weak, nonatomic) IBOutlet UITextField *pwd;

@property(nonatomic,strong)RACDisposable *btnDisposable;
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類,在分類里面給UI控件擴(kuò)充了新的方法友雳。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self combine]; // 組合信號(hào)combineLatest:reduce:
    
}

-(void)combine{
    NSArray *signals = @[self.usernameField.rac_textSignal,self.pwd.rac_textSignal];
    
    // 組合信號(hào)
    RACSignal *combineSignal = [RACSignal combineLatest:signals reduce:^id(NSString *username,NSString *password){
        // 無(wú)論用戶名和密碼有沒(méi)有值稿湿,都會(huì)執(zhí)行訂閱block,只是返回的值有0和1押赊,讓登錄按鈕變?yōu)辄c(diǎn)擊狀態(tài)的話,x必須為1.
        return @(username.length > 0 && password.length >0);
        
    }];
    // 訂閱者block
    [combineSignal subscribeNext:^(id x) {
        NSLog(@"%@",x);
        // x為1時(shí),登錄按鈕才可以點(diǎn)擊
        self.login.enabled = [x boolValue];
    }];
}
@end

截圖

101.6.gif

7.創(chuàng)建一個(gè)用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求的信號(hào)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類饺藤,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self net];// 創(chuàng)建信號(hào)流礁,用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求
    
}

-(void)net{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求涕俗。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
    RACSignal *ipSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];

                // 調(diào)用sendNext,底層就會(huì)調(diào)用subscribeNext.只有調(diào)用了subscribeNext,才會(huì)調(diào)用訂閱者block,才會(huì)執(zhí)行block中的內(nèi)容,從而打印responseStr中的內(nèi)容崇棠,然后接著會(huì)打印x中的內(nèi)容咽袜。沒(méi)有這句代碼,什么也不會(huì)打印
                [subscriber sendNext:responseStr];//A:調(diào)用subscribeNext的block
                [subscriber sendNext:@"CoderZb"];// B:調(diào)用subscribeNext的block
                
                // 注意:調(diào)用sendCompleted或者sendError,程序會(huì)終止向下執(zhí)行枕稀,所以當(dāng)C出現(xiàn)询刹,D不執(zhí)行谜嫉。反之亦然。
                [subscriber sendCompleted];// C:調(diào)用sendCompleted的block
                // 模擬錯(cuò)誤信息
                 NSError *ErrorInfo = [NSError errorWithDomain:@"服務(wù)未啟動(dòng)" code:2016 userInfo:nil];                [subscriber sendError:ErrorInfo];//D:調(diào)用error的block
            }else{
                NSLog(@"+++++%@",error);
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
        return nil;
        
    }];
    
        // 訂閱者block
        [ipSignal subscribeNext:^(id x) {// sendNext:調(diào)用的凹联。
             NSLog(@"網(wǎng)絡(luò)請(qǐng)求成功,內(nèi)容為%@",x);// 打印responseStr中的內(nèi)容沐兰。驗(yàn)證:將responseStr替換為@"CoderZb"
        } error:^(NSError *errorInfo){
            NSLog(@"%@",errorInfo);
        }
        completed:^{// sendCompleted調(diào)用的。
            NSLog(@"終止了訂閱");
        }];
}

@end

截圖

101.7.gif

8.信號(hào)嵌套

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;

@property (weak, nonatomic) IBOutlet UILabel *ipLabel;
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類蔽挠,在分類里面給UI控件擴(kuò)充了新的方法住闯。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self flatterMap];//信號(hào)嵌套

}

-(void)flatterMap{
    // 按鈕信號(hào)
    RACSignal *btnSignal = [self.ipAddressBtn rac_signalForControlEvents:UIControlEventTouchUpInside];
    [[btnSignal flattenMap:^RACStream *(id value) {
        return [self ipSignal];// 又嵌套了一個(gè)封裝網(wǎng)絡(luò)請(qǐng)求的信號(hào)
    }] subscribeNext:^(id x) {
          NSLog(@"%@",x);
        self.ipLabel.text = x;
    }];
}

-(RACSignal *)ipSignal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
   return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//            NSLog(@"---%@",[NSThread currentThread]); // 通過(guò)打印可知,block代碼塊所在的線程為子線程澳淑,所以應(yīng)將x比原,y處的代碼寫(xiě)在主線程中,否則ipLabel上顯示不出來(lái)內(nèi)容.因?yàn)轱@示UI要在主線程(主隊(duì)列)執(zhí)行
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                
               [[NSOperationQueue mainQueue] addOperationWithBlock:^{// 主隊(duì)列即主線程杠巡。驗(yàn)證:打印下面的注釋
//                   NSLog(@"+++%@",[NSThread currentThread]);
                 [subscriber sendNext:responseStr];//x:調(diào)用subscribeNext的block
               }];
                
                
            }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                  NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
       return [RACDisposable disposableWithBlock:^{
           // 取消網(wǎng)絡(luò)請(qǐng)求
           [dataTask cancel];
       }];
    }];
}
@end

截圖

101.8.gif

9.信號(hào)注入

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;

@property (weak, nonatomic) IBOutlet UILabel *ipLabel;

// 可視化創(chuàng)建UIActivityIndicatorView控件并勾選面板右側(cè)的Hides When Stopped量窘,即靜態(tài)(停止)的時(shí)候隱藏該控件。
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *Indicator;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類氢拥,在分類里面給UI控件擴(kuò)充了新的方法蚌铜。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self doNext];// 信號(hào)注入:doNext在網(wǎng)絡(luò)請(qǐng)求之前可以提前做一些操作,例如提前開(kāi)始Indicator的動(dòng)畫(huà)
}

-(void)doNext{

    RACSignal *btnSignal = [self.ipAddressBtn rac_signalForControlEvents:UIControlEventTouchUpInside ];
    [btnSignal doNext:^(id x) {
        // 開(kāi)始Indicator的動(dòng)畫(huà),此時(shí)Indicator會(huì)顯示,因?yàn)樵诳梢暬姘逵覀?cè)勾選了Hides When Stopped
                [self.Indicator startAnimating];
    }];
    [[btnSignal flattenMap:^RACStream *(id value) {
        // 開(kāi)始Indicator的動(dòng)畫(huà),此時(shí)Indicator會(huì)顯示,因?yàn)樵诳梢暬姘逵覀?cè)勾選了Hides When Stopped
                [self.Indicator startAnimating];
                // 執(zhí)行網(wǎng)絡(luò)請(qǐng)求的信號(hào)
                return [self ipSignal];// 當(dāng)有ruturn操作時(shí)嫩海,后面的內(nèi)容不能再用btnSignal對(duì)象調(diào)用,否則最終的結(jié)果不是自己想要的冬殃。
    }] subscribeNext:^(id x) {
        self.ipLabel.text = x;
                // 停止Indicator的動(dòng)畫(huà).此時(shí)Indicator會(huì)隱藏,因?yàn)樵诳梢暬姘逵覀?cè)勾選了Hides When Stopped
                [self.Indicator stopAnimating];
    }];
    
}

-(void)flatterMap{
    RACSignal *btnSignal = [self.ipAddressBtn rac_signalForControlEvents:UIControlEventTouchUpInside];
    [[btnSignal flattenMap:^RACStream *(id value) {
        return [self ipSignal];
    }] subscribeNext:^(id x) {
          NSLog(@"%@",x);
        self.ipLabel.text = x;
    }];
}

-(RACSignal *)ipSignal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
   return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//            NSLog(@"---%@",[NSThread currentThread]); // 通過(guò)打印可知,block代碼塊所在的線程為子線程叁怪,所以應(yīng)將x审葬,y處的代碼寫(xiě)在主線程中,否則ipLabel上顯示不出來(lái)內(nèi)容.因?yàn)轱@示UI要在主線程(主隊(duì)列)執(zhí)行
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                
               [[NSOperationQueue mainQueue] addOperationWithBlock:^{// 主隊(duì)列即主線程骂束。驗(yàn)證:打印下面的注釋
//                   NSLog(@"+++%@",[NSThread currentThread]);
                 [subscriber sendNext:responseStr];//x:調(diào)用subscribeNext的block
               }];
                
                
            }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                  NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
       return [RACDisposable disposableWithBlock:^{
           // 取消網(wǎng)絡(luò)請(qǐng)求
           [dataTask cancel];
       }];
    }];
}

@end

截圖

101.9.gif

10.信號(hào)延遲

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類耳璧,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    [self throttle];// 信號(hào)延遲:訂閱block中的內(nèi)容延時(shí)輸出
}

-(void)throttle{
  
    
     RACSignal *btnSignal = [self.ipAddressBtn rac_signalForControlEvents:UIControlEventTouchUpInside ];
    // 延遲5秒輸出block中的內(nèi)容
    [[btnSignal throttle:5] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
}
@end

截圖

101.10.gif

11.信號(hào)串聯(lián)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類展箱,在分類里面給UI控件擴(kuò)充了新的方法旨枯。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self concat];// 信號(hào)串聯(lián)(一條線程),任務(wù)依次執(zhí)行.需要執(zhí)行sendCompleted操作
}

-(void)concat{
    //調(diào)用sendCompleted,表示信號(hào)的完成。只有信號(hào)完成了混驰,才能執(zhí)行串聯(lián)操作攀隔。就比如串行隊(duì)列,只有前一個(gè)任務(wù)執(zhí)行完成了栖榨,后面的任務(wù)才能執(zhí)行昆汹。如何判斷任務(wù)完成了,類比Rac中的sendCompleted操作婴栽。
    // 起床信號(hào)
    RACSignal *getup =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在穿衣服"];
        [subscriber sendNext:@"起床"];
        [subscriber sendCompleted];// 信號(hào)串聯(lián)满粗,必須在兩個(gè)信號(hào)之間執(zhí)行sendCompleted操作
        return nil;
    }];
    
    // 吃飯信號(hào)
    RACSignal *eat  =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在吃飯"];
        [subscriber sendNext:@"吃完飯了"];
        return nil;
    }];
    
    // 信號(hào)串聯(lián)
    [[getup concat:eat] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
}

@end

截圖

101.11.gif

12.信號(hào)并聯(lián)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類,在分類里面給UI控件擴(kuò)充了新的方法愚争。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    [self merge];// 信號(hào)并聯(lián)(多條線程),任務(wù)同時(shí)執(zhí)行.不用執(zhí)行sendCompleted操作
}

-(void)merge{
    
    // 起床信號(hào)
    RACSignal *getup =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在穿衣服"];
        [subscriber sendNext:@"起床"];
        return nil;
    }];
    
    // 吃飯信號(hào)
    RACSignal *eat  =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在吃飯"];
        [subscriber sendNext:@"吃完飯了"];
        return nil;
    }];
    
    // 信號(hào)并聯(lián)
    [[getup merge:eat] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

}

@end

截圖

101.12.gif

13.信號(hào)忽略

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類映皆,在分類里面給UI控件擴(kuò)充了新的方法挤聘。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self then];// 信號(hào)忽略(一條線程),任務(wù)依次執(zhí)行.忽略的是then:前面的信號(hào),執(zhí)行then后面的信號(hào),所以then前面的信號(hào)不執(zhí)行捅彻,then后面的信號(hào)依次執(zhí)行.需要執(zhí)行sendCompleted操作
}

-(void)then{
    // 起床信號(hào)
    RACSignal *getup =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在穿衣服"];
        [subscriber sendNext:@"起床"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    // 吃飯信號(hào)
    RACSignal *eat  =[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"正在吃飯"];
        [subscriber sendNext:@"吃完飯了"];
        return nil;
    }];
    
    // 信號(hào)忽略.忽略了getup信號(hào)
    [[getup then:^RACSignal *{
        return eat;
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

}

@end

截圖

101.13.gif

14.信號(hào)延遲

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類组去,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self delay];// 信號(hào)延遲:等同throttle
}

-(void)delay{
    RACSignal *btnSignal = [self.ipAddressBtn rac_signalForControlEvents:UIControlEventTouchUpInside ];
    // 點(diǎn)擊按鈕步淹,延遲5秒執(zhí)行
    [[btnSignal delay:5] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

    
}
@end

截圖

101.14.gif

15.信號(hào)超時(shí)

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類从隆,在分類里面給UI控件擴(kuò)充了新的方法。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];

    [self timeout];//信號(hào)超時(shí).用于網(wǎng)絡(luò)請(qǐng)求的信號(hào)

}

-(void)timeout{
    // 過(guò)了7秒就超時(shí)缭裆,就不再執(zhí)行訂閱者block.因?yàn)镾ignal方法中線程休眠了5秒键闺,5秒<7秒,所以沒(méi)有超過(guò)超時(shí)的時(shí)間,所以會(huì)執(zhí)行訂閱者block.如果線程休眠10秒,那么就不會(huì)執(zhí)行訂閱者block
    [[[self Signal] timeout:7 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
}

-(RACSignal *)Signal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求澈驼。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //            NSLog(@"---%@",[NSThread currentThread]); // 通過(guò)打印可知,block代碼塊所在的線程為子線程艾杏,所以應(yīng)將x,y處的代碼寫(xiě)在主線程中盅藻,否則ipLabel上顯示不出來(lái)內(nèi)容.因?yàn)轱@示UI要在主線程(主隊(duì)列)執(zhí)行
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                #warning 線程休眠5秒
                [NSThread sleepForTimeInterval:10];
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{// 主隊(duì)列即主線程。驗(yàn)證:打印下面的注釋
                    // NSLog(@"+++%@",[NSThread currentThread]);
                    [subscriber sendNext:responseStr];//x:調(diào)用subscribeNext的block
                }];
                
                
            }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
        return [RACDisposable disposableWithBlock:^{
            // 取消網(wǎng)絡(luò)請(qǐng)求
            [dataTask cancel];
        }];
    }];
}
@end

截圖

101.15.gif

16.監(jiān)聽(tīng)選中的圖片,監(jiān)聽(tīng)選中圖片的手勢(shì)


#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property(nonatomic,strong)RACDisposable *btnDisposable;
@end

@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    static dispatch_once_t onceToken;
    // 一次性代碼畅铭,保證只執(zhí)行一次.這樣第二次點(diǎn)擊屏幕時(shí)候不會(huì)執(zhí)行這段代碼氏淑,但是3處的代碼會(huì)執(zhí)行
    dispatch_once(&onceToken,^{        // 功能1:監(jiān)聽(tīng)選中的圖片
        UIImagePickerController *pickVC = [[UIImagePickerController alloc] init];
        pickVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        // 通過(guò)信號(hào)獲取用戶選中的圖片
        [pickVC.rac_imageSelectedSignal subscribeNext:^(NSDictionary *Info) {
            //        NSLog(@"%@",x);
            // key根據(jù)上面的打印內(nèi)容粘貼
            UIImage *selectImage = Info[@"UIImagePickerControllerOriginalImage"];
            self.imageView.image = selectImage;
            // 選中完圖片,直接到返回之前的控制器
            [self dismissViewControllerAnimated:YES completion:nil];
        }];
        [self presentViewController:pickVC animated:YES completion:nil];

    });
   
    // 功能2:監(jiān)聽(tīng)點(diǎn)擊圖片的手勢(shì)
    self.imageView.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]init];
    [self.imageView addGestureRecognizer:tap];
    [tap.rac_gestureSignal subscribeNext:^(id x) {
        NSLog(@"圖片被點(diǎn)擊");
    }];
}
@end

截圖

101.16.gif

17.監(jiān)聽(tīng)鍵盤的彈出

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@end

@implementation ViewController
// rac給每一個(gè)UI控件都增加了分類硕噩,在分類里面給UI控件擴(kuò)充了新的方法假残。利用rac編程時(shí)用到的就是這個(gè)方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    // 功能3:監(jiān)聽(tīng)鍵盤的彈出
    NSNotificationCenter *notification = [NSNotificationCenter defaultCenter];
    [[notification rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(id x) {
        NSLog(@"鍵盤彈出,鍵盤信息如下----%@",x);
    }];

}

@end

截圖

101.17.gif

18.監(jiān)聽(tīng)屬性值的改變

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
#import "Person.h"
@interface ViewController ()
@property(nonatomic,strong)Person *person;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self kvo];// kvo監(jiān)聽(tīng)屬性的改變
    
   }

-(void)kvo{
    self.person = [[Person alloc] init];
    // kvo監(jiān)聽(tīng)屬性的改變,一旦屬性發(fā)生改變就會(huì)調(diào)用訂閱block.所以點(diǎn)擊一下屏幕炉擅,就會(huì)調(diào)用訂閱block一次辉懒。
    [RACObserve(self.person, name) subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    

}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.person.name = @"CoderZb";// 修改name屬性
}
@end

截圖

101.18.gif

19.綁定屬性

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *ipLabel;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self Bundle];// 綁定屬性.將修改的內(nèi)容顯示到屬性上
}

-(void)Bundle{
    // 綁定ipLabel對(duì)象的text屬性,將[self ipSignal]返回的結(jié)果賦值給text屬性谍失。相當(dāng)于給系統(tǒng)的屬性賦值眶俩。
    RAC(self.ipLabel,text) = [self ipSignal];
}
-(RACSignal *)ipSignal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //            NSLog(@"---%@",[NSThread currentThread]); // 通過(guò)打印可知,block代碼塊所在的線程為子線程快鱼,所以應(yīng)將x颠印,y處的代碼寫(xiě)在主線程中,否則ipLabel上顯示不出來(lái)內(nèi)容.因?yàn)轱@示UI要在主線程(主隊(duì)列)執(zhí)行
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                
                #warning 線程休眠5秒
                [NSThread sleepForTimeInterval:5];
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{// 主隊(duì)列即主線程抹竹。驗(yàn)證:打印下面的注釋
                    //                   NSLog(@"+++%@",[NSThread currentThread]);
                    [subscriber sendNext:responseStr];//x:調(diào)用subscribeNext的block
                }];
                
                
            }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
        return [RACDisposable disposableWithBlock:^{
            // 取消網(wǎng)絡(luò)請(qǐng)求
            [dataTask cancel];
        }];
    }];
}

@end

截圖

101.19.gif

20.監(jiān)聽(tīng)UITextField文本信號(hào)的改變

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UILabel *ipLabel;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    [self Change]; // 監(jiān)聽(tīng)UITextField文本信號(hào)的改變线罕,只要文本發(fā)生改變,就會(huì)將改變的內(nèi)容顯示在UILabel上
    
}

-(void)Change{
    // 監(jiān)聽(tīng)UITextField文本信號(hào)的改變窃判,只要文本發(fā)生改變钞楼,就會(huì)將改變的內(nèi)容添加到UILabel上
    RAC(self.ipLabel,text) = self.usernameField.rac_textSignal;
}
@end

截圖

101.20.gif

21.RAC中,解決block造成的循環(huán)引用的兩種做法

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
#import "Person.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UIButton *login;
@property (weak, nonatomic) IBOutlet UITextField *pwd;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 解決block造成的循環(huán)引用的兩種做法
    // 做法1:
    /*
    __weak typeof(self) weakSelf = self;
    [[RACSignal combineLatest:@[self.usernameField.rac_textSignal,self.pwd.rac_textSignal] reduce:^id(NSString *username,NSString *pwd){
        return @(username.length > 0 && pwd.length > 0);
    }] subscribeNext:^(id x) {
        weakSelf.login.enabled = [x boolValue];
    }];
     */
    // 做法2:
    
    @weakify(self)
    [[RACSignal combineLatest:@[self.usernameField.rac_textSignal,self.pwd.rac_textSignal] reduce:^id(NSString *username,NSString *pwd){
        return @(username.length > 0 && pwd.length > 0);
    }] subscribeNext:^(id x) {
        @strongify(self)
        self.login.enabled = [x boolValue];
    }];
    

}
-(void)dealloc{
    NSLog(@"%s",__func__);
}
@end

截圖

101.21.gif

22.(一)rac_command

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
     [self btnClick];//rac_command
  
   }
-(void)btnClick{
    //  RACCommand:點(diǎn)擊按鈕,執(zhí)行訂閱者block
    self.ipAddressBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        return [self ipSignal];
    }];

}
-(RACSignal *)ipSignal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                NSLog(@"%@",responseStr);
               }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
        return nil;

    }];
   }

@end

截圖

101.22.gif

23.(二)rac_command

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;

@property (weak, nonatomic) IBOutlet UITextField *pwd;
@property (weak, nonatomic) IBOutlet UIButton *ipAddressBtn;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
  
     [self EnabledSingle];// rac_command
   
   }
-(void)EnabledSingle{
    // 按鈕的可用信號(hào)
    RACSignal *btnEnabledSingle = [RACSignal combineLatest:@[self.usernameField.rac_textSignal,self.pwd.rac_textSignal] reduce:^id(NSString *username,NSString *pwd){
        // 只有用戶名和密碼不為空時(shí)袄琳,ipAddressBtn按鈕才會(huì)變?yōu)榭梢渣c(diǎn)擊的狀態(tài)询件。
        return @(username.length > 0 && pwd.length > 0);
    }];

    // 按鈕點(diǎn)擊后觸發(fā)信號(hào)燃乍,從而會(huì)打印出ip地址。如果按鈕不可點(diǎn)擊,是無(wú)法觸發(fā)信號(hào)的雳殊。
    self.ipAddressBtn.rac_command = [[RACCommand alloc]initWithEnabled:btnEnabledSingle signalBlock:^RACSignal *(id input) {
        return [self ipSignal];
    }];

}

-(RACSignal *)ipSignal{
    // 創(chuàng)建信號(hào),用于封裝自定義的網(wǎng)絡(luò)請(qǐng)求橘沥。即:把網(wǎng)絡(luò)請(qǐng)求的代碼封裝在createSignal的代碼塊中
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 1.創(chuàng)建請(qǐng)求對(duì)象
        NSURLRequest *  request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pv.sohu.com/cityjson"]];
        // 2.創(chuàng)建下載任務(wù)
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //            NSLog(@"---%@",[NSThread currentThread]); // 通過(guò)打印可知,block代碼塊所在的線程為子線程,所以應(yīng)將x夯秃,y處的代碼寫(xiě)在主線程中座咆,否則ipLabel上顯示不出來(lái)內(nèi)容.因?yàn)轱@示UI要在主線程(主隊(duì)列)執(zhí)行
            // data不是UTF-8編碼,而是GBK編碼
            if (error == nil) {// 沒(méi)錯(cuò)誤就執(zhí)行
                //將data對(duì)象轉(zhuǎn)換成字符串
                NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
                NSString *responseStr = [[NSString alloc] initWithData:data encoding:enc];
                NSLog(@"%@",responseStr);
            }else{
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    NSLog(@"+++++%@",error);// y
                }];
                
            }
        }];
        // 3.執(zhí)行下載任務(wù)
        [dataTask resume];
        return nil;
    }];
}

@end

截圖

101.23.gif

24.RACSequence

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
      [self racSequence];// RACSequence:主要用于遍歷
   }
-(void)racSequence{
    NSArray *names = @[@"Tom",@"Mary",@"Jack"];
    // 獲取RACSequence里面的信號(hào)進(jìn)行遍歷
    [names.rac_sequence.signal subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    
}

@end

截圖

101.24.gif

25.RACSequence和filter結(jié)合使用

#import "ViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
     [self racSequenceAndfilter];// RACSequence和filter結(jié)合使用
}

-(void)racSequenceAndfilter{
    // RACSequence與filter(過(guò)濾)的結(jié)合使用
    NSString *text = @"19293842456647";
    [[text.rac_sequence.signal filter:^BOOL(id value) {
        return [value intValue] >5;// 只打印大于5的數(shù)字
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

}
@end

截圖

101.25.gif

登錄小項(xiàng)目


  • 查看隱藏的Apache的安裝目錄:/etc/apache2/
  • 做法1:dock下右鍵Finder,選擇"前往文件夾"仓洼,輸入"/etc"
  • 做法2:finder下->前往->前往文件夾->輸入/etc
  • 做法3:Terminal 輸入 "open /etc"

  • apache相關(guān)指令:

  • 開(kāi)啟apache服務(wù) sudo apachectl start

  • 停止apache服務(wù) sudo apachectl stop

  • 重啟服務(wù) sudo apachectl restart

  • 查看版本 httpd -v

  • 注意點(diǎn):

端口沖突的問(wèn)題.png

Apache+Mysql+PHP的集成環(huán)境的配置(一介陶、二、三)


(一)Apache服務(wù)器的開(kāi)啟和配置色建、php的配置

httpd.conf配置錯(cuò)誤的話,重新下載未修改的httpd.conf文件 密碼


具體步驟推薦這個(gè)參考鏈接

參考鏈接1
參考鏈接2
參考鏈接3
參考鏈接4

  • 1.在自己的用戶目錄(zhangbin)里新建一個(gè)Sites文件夾
111.1.png

  • 2.進(jìn)到cd /etc/apache2/users/目錄下哺呜,sudo vim zhangbin.conf,增加內(nèi)容為:
<Directory "/Users/zhangbin/Sites/">
AllowOverride All
Options Indexes MultiViews FollowSymLinks
Require all granted
</Directory>
111.2.gif

  • 3.修改zhangbin.conf這個(gè)文件的權(quán)限
sudo chmod 644 zhangbin.conf

111.3.gif

  • 4.cd到/etc/apache2/目錄箕戳,sudo vim httpd.conf 將下面五句話的注釋去掉
LoadModule authz_core_module libexec/apache2/mod_authz_core.so 
LoadModule authz_host_module libexec/apache2/mod_authz_host.so 
LoadModule userdir_module libexec/apache2/mod_userdir.so 
Include /private/etc/apache2/extra/httpd-userdir.conf
LoadModule php5_module libexec/apache2/libphp5.so
  • 5.進(jìn)到/etc/apache2/extra/目錄某残,sudo vim httpd-userdir.conf ,將這句話的注釋去掉
Include /private/etc/apache2/users/*.conf
  • 6.sudo apachectl restart 重啟服務(wù)器
  • 7.將php后臺(tái)代碼放到Sites文件夾下
111.7.png

  • 8.瀏覽器輸入: loacal/~zhangbin/
111.8.png

拓展知識(shí)點(diǎn)修改apache默認(rèn)頁(yè)面的內(nèi)容

cd /Library/WebServer/Documents/
sudo vim index.html.en

(二)開(kāi)啟MySQL服務(wù)器(必不可少),安裝Navicat數(shù)據(jù)庫(kù)管理工具


  • 1.只安裝MySQL.prefPane陵吸,用于開(kāi)啟MySQL服務(wù)器


    102.1gif.gif
  • 2.終端輸入(必須)
    mysqladmin -u root password "123456"

  • 3.安裝Navicat數(shù)據(jù)庫(kù)管理工具. 目的:創(chuàng)建表玻墅,創(chuàng)建數(shù)據(jù)庫(kù)等等。


    102.2.gif
  • 4.創(chuàng)建數(shù)據(jù)庫(kù)壮虫,創(chuàng)建表

102.3.gif

(三)效果展示


注冊(cè)
101.26.gif
登錄
101.27.gif
發(fā)表日志
101.28.gif

細(xì)節(jié)問(wèn)題
  • 1.開(kāi)啟和關(guān)閉MySQL的影響


    101.29.gif
  • 2.1.Apache系統(tǒng)級(jí)的根目錄及對(duì)應(yīng)網(wǎng)址是:
    /Library/WebServer/Documents/

         http://localhost
    
  • 2.2.用戶級(jí)的根目錄及對(duì)應(yīng)網(wǎng)址是:
    ~/Sites

        http://localhost/~zhangbin/
    

由2.1和2.2可知關(guān)閉和開(kāi)啟apache服務(wù)器對(duì)訪問(wèn)網(wǎng)址的影響如下截圖


101.30.gif

[軟件+項(xiàng)目LS](https://pan.baidu.com/s/1gffo8IB 密碼 43kp )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末澳厢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子囚似,更是在濱河造成了極大的恐慌剩拢,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饶唤,死亡現(xiàn)場(chǎng)離奇詭異徐伐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)募狂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門呵晨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人熬尺,你說(shuō)我怎么就攤上這事摸屠。” “怎么了粱哼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵季二,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)胯舷,這世上最難降的妖魔是什么刻蚯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桑嘶,結(jié)果婚禮上炊汹,老公的妹妹穿的比我還像新娘。我一直安慰自己逃顶,他們只是感情好讨便,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著以政,像睡著了一般霸褒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盈蛮,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天废菱,我揣著相機(jī)與錄音,去河邊找鬼抖誉。 笑死殊轴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的袒炉。 我是一名探鬼主播梳凛,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梳杏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淹接,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤十性,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后塑悼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體劲适,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年厢蒜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了霞势。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斑鸦,死狀恐怖愕贡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情巷屿,我是刑警寧澤固以,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響憨琳,放射性物質(zhì)發(fā)生泄漏诫钓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一篙螟、第九天 我趴在偏房一處隱蔽的房頂上張望菌湃。 院中可真熱鬧,春花似錦遍略、人聲如沸惧所。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纯路。三九已至,卻和暖如春寞忿,著一層夾襖步出監(jiān)牢的瞬間驰唬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工腔彰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叫编,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓霹抛,卻偏偏與公主長(zhǎng)得像搓逾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杯拐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容