ReactiveCocoa 코드 실습 - 더 많은 생각

8163 단어
관련 보기:
ReactiveCocoa 코드 실습 - UI 구성 요소의 RAC 신호 조작
ReactiveCocoa 코드 실습-RAC 네트워크 요청 재구성
1. RACObserve () 매크로 참조법의 차이
이전에 코드를 써서 RACObserve(self.timeLabel,text)와 RACObserve(self,timeLabel.text)의 차이를 고려한 적이 있다.왜냐하면 이 두 가지 방법은 모두 관찰self이기 때문이다.timeLabel.text의 속성이며 기능을 실현할 수 있습니다.아마도 작가가 원래 사용했던 것 중 하나가 나중에 다른 것에도 지지를 제공했을 것이다. 도대체 어떤 차이가 있고 어떤 것이 더 좋은가?
눌러서 RACObserve의 원본 코드를 보면 대부분 방법이 호출되고 한 층 한 층 눌러서 마지막에 이 방법에 온다.

- (RACDisposable *)rac_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver block:(void (^)(id, NSDictionary *, BOOL, BOOL))block 

이 방법에서 쉼표 뒤에 있는 키 path를 "."하나의 수조로 나누다.그리고 세 가지 속성을 얻었습니다.

BOOL keyPathHasOneComponent = (keyPathComponents.count == );
NSString *keyPathHead = keyPathComponents[];
NSString *keyPathTail = keyPath.rac_keyPathByDeletingFirstKeyPathComponent; 

키 패치의 머리와 고개를 돌리는 부분을 찾을 수 있으며, 아래 방법 내부에서 자신을 호출할 수 있습니다.

// Adds the callback block to the remaining path components on the value. Also
// adds the logic to clean up the callbacks to the firstComponentDisposable.
void (^addObserverToValue)(NSObject *) = ^(NSObject *value) {
RACDisposable *observerDisposable = [value rac_observeKeyPath:keyPathTail options:(options & ~NSKeyValueObservingOptionInitial) observer:weakObserver block:block];
[firstComponentDisposable() addDisposable:observerDisposable];
};

그리고 키PathTail을 키patch로 전송했습니다. 바로 귀속 호출입니다. 들어올 때마다 첫 번째 요소를 잘라냅니다. BoolkeyPathHasOneComponent 이 값이 yes와 같을 때까지.이런 측면에서 볼 때 RACObserve(self,timeLabel.text)라는 쓰기는 컴파일링을 유발하고 RACObserve(self.timeLabel.text)보다 성능이 떨어진다.
2. 컬렉션 작업
만약에 지금 하나의 수요가 있다면 일련의 암호가 있는 그룹이 있다. 우리는 암호의 길이가 6자리 이하인 것이 너무 짧다고 판단하면 시스템 내부에서 XXX 암호가 너무 짧아서 불합격이라는 메시지를 던진다.RAC 쓰기 방식은 일반적인 쓰기 방식보다 편리하며, 사용자 정의를 필터한 다음 바로 되돌려줍니다.

NSArray *pwds = @[@"",@"",@"",@""];
RACSequence *results = [[pwds.rac_sequence
filter:^ BOOL (NSString *pwd) {
return pwd.length < ;
}]map:^id(NSString *pwd) {
return [[pwd mutableCopy]stringByAppendingString:@"       "];
}];
NSLog(@"%@",results.array); 

중간 Filter 방법의 Block 내 코드는 아래results에 있습니다.array 코드가 실행될 때만 실행되며 구독자가 있어야 실행되는 셈이다.이 점은 RACsignal과 매우 비슷하다. 왜냐하면 signal과 sequence는 모두streams이기 때문이다. 그들은 같은 방법을 많이 공유한다. signal은push구동의stream이고 sequence는pull구동의stream이다.
RACsequence 대상에서 다른 속성을 꺼낼 때 다음과 같은 방법을 사용할 수 있습니다

RACSequence *s = [RACSequence sequenceWithHeadBlock:^id{
return @"     ";
} tailBlock:^RACSequence *{
return [RACSequence new];
}];
NSLog(@"%@",s.head);
NSLog(@"%@",s.tail); 

두 블록은 각각 지정한 속성이 호출될 때만 실행됩니다. 헤드가 sequence의 첫 번째 요소이고tail은 첫 번째 요소의 나머지 모든 것을 제거하기 때문에 sequence입니다.(동백연 블로그원)
3. 신호 구현 게임 스킬 시전
지금 RAC로 버스에서 폭기 기술을 넣는 방법을 시뮬레이션해야 한다고 가정해 보세요.지정된 버튼을 누르면 앞 주먹과 아래 주먹이 절기를 펼친다.
우선 각 단추를 연결하고 모든 버튼의 단독 신호를 감청하는 신호를 설정하여 각 버튼의 타이틀을 포착해야 한다.

//           
RACSignal *comboSignal = [[RACSignal merge:@[
[self.topBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.bottomBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.leftBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.rightBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.BBtn rac_signalForControlEvents:UIControlEventTouchUpInside],
[self.ABtn rac_signalForControlEvents:UIControlEventTouchUpInside]]]
map:^id(UIButton *btn) {
return btn.currentTitle;
}]; 

그리고 이 신호원에 대해 버퍼 조작을 하여 3초마다 받는 모든 버튼 정보를 포착하고 판단과 후속 조작을 한다

//         
NSString *comboCode = @"     ";
//     
RACSignal *canAction = [[[comboSignal bufferWithTime: onScheduler:[RACScheduler mainThreadScheduler]] map:^id(RACTuple *value) {
return [[value allObjects] componentsJoinedByString:@""];
}] map:^id(NSString *value) {
return @([value containsString:comboCode]);
}];
//   combo:        
[self rac_liftSelector:@selector(combo:) withSignalsFromArray:@[canAction]]; 

위의 코드는 예상된 기능을 실현할 수 있으며, 3초의 버퍼에서 지정한 버튼을 누르면 방출할 수 있다.그러나 이 방법으로 중간에도 문제가 하나 있다. 버퍼를 설치한 후 3초 간격으로 이 블로그에 한 번씩 온다. 즉, 0.5초 안에 스킬을 눌렀다면 2.5초를 더 기다려야 스킬을 내보낼 수 있다. 이것은 실전에서 받아들일 수 없는 것이 분명하다.
그래서 다른 실현 방향을 시도했고takeLast:와takeUntilBlock:과scanWithStart: 등 방법이 모두 적합하지 않았다. 마지막으로aggregateWithStart를 사용하여 수요의 목적을 달성했다.

//         
NSString *comboCode = @"     ";
//     
_time = [[[NSDate alloc] init] timeIntervalSince1970];
[[comboSignal aggregateWithStart:@"" reduce:^id(NSString* running, NSString* next) {
if (([[[NSDate alloc] init] timeIntervalSince1970] - _time) < 3){
NSString *str = [NSString stringWithFormat:@"%@%@",running,next];
return [str containsString:comboCode]?[self combo]:str;
}
_time = [[[NSDate alloc] init] timeIntervalSince1970];
return str.length < combo.length ? str : [str subStringFromIndex:str.length - comboCode.length];
}]subscribeNext:^(id x){
}]; 

이 코드를 사용하면 이전 조건을 충족시키는 전제에서 버튼을 누르면 즉시 기술을 터치할 수 있다.
aggregate With Start: Reduce: 첫 번째 파라미터는 초기 값이고 두 번째 파라미터는 Block입니다. 이 Block의 되돌아오는 값은 바로 다음에 이 Block에 오는running 파라미터입니다.내가 이 Block의 순환에서 하는 동작은 다음과 같다.
1. 시간을델타로 계산한다. 만약에 지난번 시간 노드가 3초 이상이면 갱신 시간 노드가 다시 시간을 계산한다.str가 5보다 작으면 되돌아오고 5보다 크면 캡처한 후 5위가 되돌아옵니다.
2. 3초 미만이면 매번 키 정보를 하나의 문자열로 집합하여 기술 트리거 코드가 포함되어 있는지 판단한다.
3. 만족하면 스킬을 터치하고 스킬 방법의 내부도 시간 노드를 갱신하며 런닝(마지막 4위를 보류하고 이전 순환이 끝나고 다음 순환이 만족하는 조건을 방지한다)을 캡처한다.만족하지 않으면 이 문자열을 계속 되돌려줍니다.
코드를 잘 쓰지는 못했지만 기능이 이루어져서 어색했다. 함수식 프로그래밍은 투명하고 부작용이 없는 인용을 제창하기 때문에 위에서 값을 기록하고 구성원 변수를 기록해야 하는 방법은 RAC로 적합하지 않다. 더 좋은 방법이 있을 것이다.
4. 기타 RAC 작업
1) 매핑: flattenMap, 소스 신호 컨텐트를 새 컨텐트로 매핑
2) 조합:concat: 일정한 순서에 따라 신호를 연결하고 여러 신호가 발송될 때 순서대로 신호를 수신한다
3) `then`: 두 개의 신호를 연결하는 데 사용되며, 첫 번째 신호가 완성되어야만 then이 되돌아오는 신호를 연결할 수 있다
4) `merge`: 여러 개의 신호를 하나의 신호로 합치면 어떤 신호가 새로운 값이 있을 때 호출된다
5) `combineLatest`: 여러 신호를 합쳐서 각 신호의 최신 값을 얻으려면 합쳐진 signal마다 최소한 한 번의sendNext가 있어야 합쳐진 신호를 터치할 수 있다.
6)`reduce`집합: 신호가 보내는 내용은 원조이며, 신호가 보내는 원조의 값을 하나의 값으로 집합한다
7) Filter: 신호를 필터하여 조건에 맞는 신호를 얻을 수 있습니다.
8) ignore: 일부 값의 신호를 무시합니다.
9) distinctUntilChanged: 이전 값과 현재 값이 뚜렷하게 변하면 신호를 보냅니다. 그렇지 않으면 무시됩니다
10) take: 처음부터 모두 N회 신호를 취한다
11)takeLast: 마지막 N번의 신호를 취한다. 전제조건, 구독자는 반드시 호출을 완료해야 한다. 왜냐하면 완성만 하면 총 몇 개의 신호가 있는지 알 수 있기 때문이다.
12)takeUntil:(RACsignal*): 신호가 실행될 때까지 신호를 받습니다.
13) skip: (NSUInteger): 몇 개의 신호를 건너뛰고 받지 않음
14) switchTo Latest: signal OfSignals(신호의 신호)에 사용되며, 때로는 신호도 신호를 보내고, signal OfSignals에서 signal OfSignals가 보낸 최신 신호를 받습니다.
15)doNext:Next를 실행하기 전에 이 Block을 실행합니다
16)doCompleted:sendCompleted를 실행하기 전에 이 Block을 실행합니다
17) deliverOn: 내용 전달이 정해진 라인으로 전환되고 부작용은 원래 라인에서 발생하며 신호를 만들 때 Block에 있는 코드를 부작용이라고 한다
18)subscribeOn: 콘텐츠 전달과 부작용이 정해진 라인으로 전환됨
19) interval 정시: 일정 시간마다 신호를 보낸다
20) delay 는 next 발송을 지연시킵니다.
21) 프록시 대체:
•rac_signalForSelector: 에이전트를 대체하는 데 사용됩니다.
22) KVO 대신:
•rac_valuesAndChangesForKeyPath: 객체의 속성 변경을 수신합니다.
23) 이벤트 수신:
•rac_signalForControlEvents: 이벤트를 수신합니다.
24) 알림 대신:
•rac_addObserverForName: 알림을 수신하는 데 사용됩니다.
25) 텍스트 상자 텍스트 변경 내용을 수신합니다.
•rac_textSignal: 텍스트 상자가 바뀌면 이 신호를 보냅니다.
26) 인터페이스에 여러 번의 요청이 있을 때 데이터를 모두 가져와야 인터페이스를 보여줄 수 있다
•rac_lift Selector: with Signals From Array: Signals: 전송된 Signals (신호 그룹) 는 모든signal이 최소한sendNext를 한 번 지나면 첫 번째 selector 파라미터를 터치하는 방법을 터치합니다.
• 사용 주의: 몇 개의 신호, 매개 변수 1의 방법은 몇 개의 매개 변수, 매개 변수가 신호에 대응하는 데이터
RAC는 학습 원가, 가독성 저하, debug의 악몽 등 불량 평가를 받았지만 최근 몇 년 동안 기업급 프로젝트에 의해 받아들여지고 함수 응답식 프로그래밍의 주류 구조가 되었다.RAC 이용자가 늘고 에세이와 블로그도 많아지면서 학습의 문턱이 크게 낮아졌다.그리고 초보자는 처음부터 모든 조작과 개념을 이해할 필요가 없고 간단한 용법부터 단계별로 고급 문법을 접하면 더욱 쉽게 받아들일 수 있다고 생각합니다.
위에서 설명한 것은 편집자가 여러분에게 소개한 ReactiveCocoa 코드 실천의 - 더 많은 사고, 여러분에게 도움이 되었으면 좋겠습니다!

좋은 웹페이지 즐겨찾기