ReactiveCocoa 입문 지도
9463 단어 ReactiveCocoaios
이전 글 에서 ReactiveCocoa 개념 을 소 개 했 는데 ReactiveCocoa 는 Objective - C 에서 성명 식 프로 그래 밍 에 사용 되 는 라 이브 러 리 입 니 다.다음은 리 액 티 브 코코아 의 모델 을 소개 하고 가장 좋 은 실천 을 토론 하 며 흔히 볼 수 있 는 함정 을 지적 할 것 이다.Reactive Cocoa 의 공 부 는 시간 이 필요 합 니 다. 천천히 합 시다.
패턴
ReactiveCocoa 에는 세 가지 기본 적 인 모델 이 있 는데 그것 이 바로 책임 체인, 분할 과 조합 모델 (chaining, splitting, and combining) 이다.이전 글 에 서 는 책임 체인 과 조합 모델 을 조금 소 개 했 고 그 다음은 더욱 깊이 있 을 것 이다.
돌 이 켜 보면 ReactiveCocoa 의 핵심 은 signal: (신호) 로 끊임없이 변화 하 는 상 태 를 나타 낸다.우리 가 chain, split, combine 을 사용 할 때, 실제로 우 리 는 이 signal 을 조작 하고 있 습 니 다.
Chaining 은 ReactiveCocoa 에서 가장 자주 사용 하 는 모드 입 니 다. 기 존의 signal 을 새로운 signal 로 변환 합 니 다.자주 사용 하 는 동작 은 새로운 signal 을 만 들 고 filter:, map: 또는 startWith: 등 방법 을 사용 하 는 것 입 니 다.예:
RAC(self.textField.text) = [[[RACSignal interval:1] startWith:[NSDate date]] map:^id(NSDate *value) {
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:value];
return [NSString stringWithFormat:@"%d:%02d", dateComponents.minute, dateComponents.second];
}];
이 예 에서, 우 리 는 textFiled 의 text 속성 을 세 개의 연 결 된 signals 의 결과 로 연결 합 니 다.우선, 우 리 는 간격 신 호 를 만 듭 니 다. 이 신 호 는 1 초 마다 현재 시간 을 보 냅 니 다.간격 신 호 는 시작 되 지 않 았 을 때 값 이 없 기 때문에 startWith: 를 사용 하여 시작 합 니 다.마지막 으로 map: signal 의 NSDate 값 을 NSString 문자열 로 변환 합 니 다. 이 문자열 은 textField 의 text 속성 에 대 입 됩 니 다.
Chaining 은 가장 자주 사용 하 는 작업 이 고 국부 변 수 를 사용 하지 않 고 위 와 같이 연결 되 어 작 동 합 니 다.아래 의 코드 는 위의 코드 와 같다.
RACSignal *intervalSignal = [RACSignal interval:1];
RACSignal *startedIntervalSignal = [intervalSignal startWith:[NSDate date]];
RACSignal *mappedIntervalSignal = [startedIntervalSignal map:^id(NSDate *value) {
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:value];
return [NSString stringWithFormat:@"%d:%02d", dateComponents.minute, dateComponents.second];
}];
RAC(self.textField.text) = mappedIntervalSignal;
Splitting 은 chaining 과 유사 하 며, signal 을 다른 sginal 로 변환 하 는 것 입 니 다. 다른 점 은 Splitting 은 중간 signals 를 반복 적 으로 사용 합 니 다.Splitting 은 좀 복잡 해 보이 지만 사실은 하나의 signals 가 여러 번 사 용 했 을 뿐이다.예:
RACSignal *dateComponentsSignal = [[[RACSignal interval:1] startWith:[NSDate date]] map:^id(NSDate *value) {
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:value];
return dateComponents;
}];
RAC(self.minuteTextField.text) = [dateComponentsSignal map:^id(NSDateComponents *dateComponents) {
return [NSString stringWithFormat:@"%d", dateComponents.minute];
}];
RAC(self.secondTextField.text) = [dateComponentsSignal map:^id(NSDateComponents *dateComponents) {
return [NSString stringWithFormat:@"%d", dateComponents.second];
}];
위의 예 에서 직렬 signal, 즉 부분 변수: dateComponentssignal 을 만 들 었 습 니 다.이 어 dateComponentsSignal 으로 두 개의 새로운 signal 을 만 들 고 각각 두 개의 textfield 의 text 속성 과 연결 합 니 다.
세 번 째 상용 모델 은 combining 이다.combining 은 몇 개의 signal 을 결합 하여 새로운 signal 을 만 드 는 것 입 니 다.예 를 들 어 '로그 인' 단 추 는 '사용자 이름' 과 '비밀번호' 입력 상자 의 텍스트 길이 가 6 을 초과 할 때 만 클릭 할 수 있 습 니 다. 그렇지 않 으 면 사용 할 수 없 는 상태 입 니 다.그러면 우 리 는 '로그 인' 단추 의 enabled 상태 에 signal 을 만 들 수 있 습 니 다. 이 signal 은 '사용자 이름' 과 '비밀번호' 상자 두 개의 signal 을 조합 합 니 다.
RAC(self.submitButton.enabled) = [RACSignal combineLatest:@[self.usernameField.rac_textSignal, self.passwordField.rac_textSignal] reduce:^id(NSString *userName, NSString *password) {
return @(userName.length >= 6 && password.length >= 6);
}];
여기 서 "로그 인" 단추 의 enable 상 태 를 combineLatest: reduce: 방법 으로 만 든 signal 에 연결 합 니 다.이 방법의 두 번 째 매개 변 수 는 block 입 니 다. 이 block 의 매개 변 수 는 combineLatest 의 매개 변수의 최신 값 조합 입 니 다.저 희 는 두 텍스트 상자 의 text signal 을 combineLatest 에 함께 전달 합 니 다. reduce 의 block 에서 이 block 은 두 개의 NSString 인 자 를 받 습 니 다. 이 block 의 작업 은 두 개의 매개 변수 값 을 조합 하여 하나의 값 을 만 들 고 돌아 오 는 것 입 니 다.이 방법의 설명:
// +combineLatest:reduce: takes an array of signals, executes the block with the
// latest value from each signal whenever any of them changes, and returns a new
// RACSignal that sends the return value of that block as values.
Combining 은 항상 두 가지 상황 에 사 용 됩 니 다.
1. 여러 가지 조건 을 동시에 만족 시 켜 야 합 니 다.
2. 여러 signal 에서 선택 합 니 다.
이러한 선형 논리 (linear flow of logic) 의 사고 에 중점 을 두 고 이 signals 를 어떻게 직렬, 분할 또는 조합 하 느 냐 에 있다.이런 기본 적 인 조작 을 보면 너 로 하여 금 이 모델 들 에 대해 더욱 익숙 하 게 할 수 있다.
최선 의 실천
우 리 는 이미 Reactive Cocoa 모델 의 기본 지식 을 소 개 했 으 니, 다음은 최고의 실천 을 살 펴 보 자.
ReactiveCocoa 는 상 태 를 제거 함으로써 프로그램 을 쉽게 쓸 수 있 습 니 다.그러나 '반응 완료 (completely reactive)' 식 응용 프로그램 에서 도 우 리 는 table view 와 같은 delegate 방법 과 같은 비 Reactive Cocoa 코드 를 써 야 한다.RACSubjects 는 비 reactive 와 reactive 코드 의 교량 역할 을 했다.
RACSubject 는 새 값 을 수 동 으로 보 낼 수 있 는 signal 입 니 다.예 를 들 어 gesture recognizers 는 ReactiveCocoa 의 일부분 이 아 닙 니 다. 이때 우 리 는 두 개의 RACSubject 속성 을 사용 할 수 있 습 니 다. 하 나 는 gesture recognizer: 사건 을 받 아들 이 는 데 사 용 됩 니 다. 이 recognizer 가 처리 하고 있 는 지 여 부 를 표시 합 니 다.다른 하 나 는 현재 위 치 를 기록 하 는 데 쓰 인 다.
self.gestureRecognizerIsRunningSubject = [RACSubject subject];
self.gestureRecognizerValueSubject = [RACSubject subject];
RAC(self.someView.frame) = [self.gestureRecognizerValueSubject map:^id(NSValue *value) {
CGPoint location = [value CGPointValue];
CGFloat size = 100.0f;
return [NSValue valueWithCGRect:CGRectMake(location.x - size/2.0f, location.y - size/2.0f, size, size)];
}];
우 리 는 하나의 view 를 gesture recognizer 의 마지막 위치 중심 에 놓 을 것 이다.
이 subjects 이 벤트 를 보 내 는 것 은 매우 간단 합 니 다. gesture recognizer 방법 을 간단하게 실현 하면 됩 니 다. (주: 이 방법 은 에이전트 방법 - gesture Recognizer: shouldReceiveTouch: 에서 호출 할 수 있 습 니 다)
-(void)gestureRecognizerReceivedTouch:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
[self.gestureRecognizerIsRunningSubject sendNext:@(YES)];
}
else if (recognizer.state == UIGestureRecognizerStateChanged) {
[self.gestureRecognizerValueSubject sendNext:[NSValue valueWithCGPoint:[recognizer locationInView:self.view]]];
}
else if (recognizer.state == UIGestureRecognizerStateEnded) {
[self.gestureRecognizerIsRunningSubject sendNext:@(NO)];
}
}
RACSubjects 는 비 reactive 코드 와 Reactive Cocoa 코드 의 교량 이지 만 지나치게 남용 하 는 것 도 위험 하 다.우리 가 chaining signals 를 통 해 임 무 를 완성 할 수 있다 면 RACSubjects 의 값 에 의존 하지 마 세 요.
ReactiveCocoa 의 디자인 은 프로그램 이 가능 한 한 여러 가지 상 태 를 줄 이 는 것 이다. 이러한 상 태 를 줄 이 는 논 리 는 부작용 (perform side - effects) 을 적 게 사용 해 야 한다.예 를 들 어 위의 코드 를 바탕 으로 저 희 는 table view 의 제스처 이벤트 가 완 료 될 때 슬라이더 를 반 짝 여 사용자 에 게 어디 까지 미 끄 러 졌 는 지 알려 주 고 싶 습 니 다.우 리 는 subscription 을 호출 할 수 있 습 니 다.
[[self.gestureRecognizerIsRunningSubject filter:^BOOL(NSNumber *gestureRecognizerIsRunning) {
return !(gestureRecognizerIsRunning.boolValue);
}] subscribeNext:^(id x) {
[self.tableView flashScrollIndicators];
}];
여기 서 우 리 는 제스처 가 실행 중인 이 벤트 를 걸 러 내 고 미끄럼 이 완 료 될 때 만 subcribe 를 걸 러 냅 니 다.이때 subscribe next: bloc 에서 부작용 을 실 행 했 습 니 다.
subscriptions 는 유용 하고 부작용 을 수행 하 는 것 도 필요 하지만 과도 한 사용 은 조심해 야 한다.그것들 이 바로 가 변 적 인 변수, 상태 이다. 이것 이 바로 ReactiveCocoa 가 피 하 는 것 이다.바 인 딩 속성 을 통 해 signals 를 매 핑 하여 작업 을 수행 할 수 있 을 때 RACSubjects 를 사용 하지 마 십시오.
함정.
어떤 새로운 것 이 든 초보 자 에 게 는 함정 이 있 을 것 이다.예 를 들 어 아래 코드 는 하나의 속성 에서 새로운 signal 을 만 들 때 somestring 의 값 이 바 뀌 기 전에 아무것도 일어나 지 않 습 니 다.
RAC(self.label.text) = RACAble(self.someString);
someSting , RACAbleWithStart。 “starts” signal someString 。
RAC(self.label.text) = RACAbleWithStart(self.someString);
이와 유사 합 니 다. interval: 주기 타 이 머 를 설정 할 때 이 타 이 머 는 이 첫 번 째 interval 로 바로 사용 되 지 않 습 니 다. NSTimer 를 사용 하 는 것 같 습 니 다.첫 번 째 예 기억 나 시 죠?저 희 는 text field 의 text 값 을 현재 시간 과 연결 합 니 다. 저 희 는 startWith 를 수 동 으로 사용 하고 현재 시간 을 전송 하여 열 었 습 니 다.만약 우리 가 이렇게 하지 않 는 다 면, text field 는 첫 번 째 간격 1 초 전에 비어 있 습 니 다.
interval: 또 하나의 중점 이 있 을 때 이 방법 은 그 결 과 를 높 은 최적화 등급 의 스케줄 링 에 전달 합 니 다 (GCD 대기 열 과 유사).즉, 이전 코드 는 실제로 1 초 동안 BUG 가 있 었 다 는 것 이다. UI 를 업데이트 하 는 코드 를 직접 실행 할 수 없다.interval: signal 의 결 과 를 주 스 레 드 스케줄 에 전달 할 수 있 습 니 다.RAC(self.textField.text) = [[[[RACSignal interval:1] startWith:[NSDate date]] map:^id(NSDate *value) {
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSMinuteCalendarUnit|NSSecondCalendarUnit) fromDate:value];
return [NSString stringWithFormat:@"%d:%02d", dateComponents.minute, dateComponents.second];
}] deliverOn:[RACScheduler mainThreadScheduler]];
그 랬 으 면 좋 겠 다.
이 글 은 자주 사용 하 는 모델 을 소개 하 였 으 며, 가장 좋 은 실천 에는 또 약간의 함정 이 있다.ReactiveCocoa 를 이용 해 성명 식 애플 리 케 이 션 을 구축 하 는 데 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ReactiveX와 MVVM과 DataBinding의 관계를 그림으로 보았습니다.등등을 여러가지 바라보고 있어 (도쿄 부러워), Reactive Extensions 라든지 MVVM 라든지 여러가지 뜨겁다! 재미! 라고 생각하고 있는 것입니다만, 여러가지 라이브러리가 있어, 그들이 커버하는 범위가...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.