2017-04-25 6 views
4

부모 요청에서 가져온 값마다 개의 복수 요청 하위 요청을 처리하는 것이 좋습니다. 나는 여기 같은 논리 (Reactive Cocoa 5 and ReactiveSwift network requests handling)를 사용하려고하지만 몇 가지 문제가있다.ReactiveCocoa 5, ReactiveSwift 네트워크 하위 요청 처리 및 모범 사례

우리가하고 필요로하는 무엇을 : 무한 스크롤 핸들러 (SVPullToRefresh)마다 핸들러가
3. 보내기 "하위라고 오브젝트의
2. 페치 목록

1의 TableView 응답에서 각 개체에 대한 요청 "

주 :
1. 모든 요청 (부모 + 하위 요청)은 viewController가 닫히면 해제되어야합니다. (부 번호가 deinit 인 경우)
2. 언제든지 부모 요청을 취소 할 권한이 있어야합니다. 또한 모든 하위 요청을 취소해야합니다. 그래서 ...

self.tableView.addInfiniteScrollingWithActionHandler { [unowned self] in 
    self.tempMutableProperty.value = true 
} 

self.tempMutableProperty.producer.skipNil().flatMap(.latest) { [unowned self] tempValueThatIDontNeed in 
    return self.producerForParentRequest(offset: self.offset) 
     .take(during: self.reactive.lifetime) 
     .on(
      // handlers for errors, completed, etc 
      value: { [unowned self] items in 
       self.items.append(items) 
       self.tableView.reloadData() 
       self.offset += items.count 
       // SEND REQUEST #2 FOR EACH ITEM 
      } 
    ).flatMapError { error in 
     return SignalProducer.empty 
    } 
}.observe(on: UIScheduler().start() 

내가 현재

은 내가 "무한 핸들러"에 무엇을 알고 무엇을 가지고 좀 "덕트 테이프",하지만 난 ReactiveSwift 새로운 해요 보시다시피 tableView로 페이지 매김을했습니다. 각 페이지에 대한 개체 목록을 가져옵니다. 그런 다음 응답의 각 항목에 대해 요청 # 2를 사용하여 추가 정보를 가져와야합니다.


흐름과 문제 : 내가 tempMutableProperty 제거하고 어떻게 든 좀 2sub-request 프록시
중 일부는 독립적이어야한다 않고 parent request 새로운 시작 취득 할 물론
1., 즉 value/error 처리기를 각각 sub-request에 대해 호출해야하며 10 개의 하위 요청을 모두 기다린 후 10 개의 응답을 모두 수집 한 성공 처리기를 호출하는 것이 아닙니다. 또한 일부 하위 요청에 실패하면 실행중인 다른 하위 요청에 영향을주지 않아야합니다.
3. 사용자는 전체 요청 프로세스가 완료 될 때까지 기다리지 않고 검색 요청을 변경할 수 있습니다. 즉, 사용자가 일부 매개 변수를 변경하면 모든 항목을 지우고 모든 sub-requests 내에서 parent request을 취소하고 다시 시작해야합니다.
4. # 2 이외에도 사용자가 스크롤하여 항목의 새 부분을 가져올 수도 있습니다. 이는 새로운 parent request이 시작되어야 함을 의미하지만, parent request의 이전 응답 sub-requests은 계속 작동해야합니다.
5. 모든 요청은 self.deinit에 취소 될한다, 그래서 이것은 모든 self.lifetime 동안에 만 작동해야하지만 나는이 모든 일회용 저장하지 않고 수 있는지 확실하지 않습니다이 매개 변수를

를 넣어 올바른 위치 무엇인지 확실하지 않다/signals을 self의 속성으로 사용하므로 sub-request이 어떻게 든 속성으로 저장되면 문제가되지 않습니다.


나는 내 문제를 여기에 솔루션을 게시 할 예정입니다,

답변

0

그래서 당신의 도움에 대해 감사합니다. 나는이를했습니다 포인트 # 1를 들어

는 :

let disposable = SerialDisposable() 

self.tableView.addInfiniteScrolling(actionHandler: { [unowned self] in 
    self.disposable.inner = nil // this is needed to force dispose current request before starting new one 
    self.disposable.inner = self.producer().take(during: self.reactive.lifetime) 
     .on(value: { [unowned self] value in 
      // handle as you want 
     }).start() 
}) 

이 날 tempMutableProperty 제거하는 데 도움이. flatMap 대신 SerialDisposable이 사용됩니다. 그래서,이 나를 위해 잘 작동, 그것은 self 내가이를했습니다 다른 점를 들어

을 파괴하기 때 자동으로 요청을 배치 :

아이디어는 내가 테이블의 일부 항목을로드하고있어이었다 , 항목 별 추가 요청을 보내서 세부 정보를 가져와야합니다. 그래서 클래스를 만들었습니다. 속성은 item, itemDetail, requestSent입니다. Details가있다

let (detailsSignal, detailsObserver) = Signal<MutableProperty<Details?>, NoError>.pipe() : 내가 좋아하는 뭔가를 self.items[indexPath.row].details 세부 사항을 나타내는 세포 자체가 MutableProperty<Details?>

입니다 :

다음 willDisplay cell에 나는

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 
    if !self.items[indexPath.row].requestSent { 
     self.items[indexPath.row].details <~ self.detailedProducerForItemID(self.items[indexPath.row].item.id) 
     self.items[indexPath.row].requestSent = true 
    } 
} 

이 항목의 세부 사항에 대한 클래스 이름.

세포의 awakeFromNib에서

:

let details = self.detailsSignal.flatMap(.latest) { $0.producer } 

self.detailsLabel.reactive.text <~ details.map { value -> String? in 
    // handling `Details` 
} 

그리고 cellForRow에 내가 VC의 deinit를 호출 cell.detailsObserver.send(value: self.items[indexPath.row].details)

과 전화, 또는 나는 새로운 main 요청을 수행, 모든 요청은 자동으로 언제부터, 취소 얻고있다 나는 self.items.removeAll()을 사용하여 모든 요청을 처리합니다.

이것은 거친 흐름입니다. 누군가 자세한 내용에 관심이 있다면 주저하지 말고 물어보십시오.

0

1 부, 나는 무한 스크롤 액션이 신호로 처리집니다 확장 추가합니다 :

extension Reactive where Base: UITableView { 
    public func infiniteScrollingSignal() -> Signal<Void, NoError> 
    { 
     return Signal { [unowned base = self.base] observer in 
      base.addInfiniteScrollingWithActionHandler { 
       observer.send(value:()) 
      } 

      return ActionDisposable { 
       // Unsubscribe the infinite scrolling action handler here if necessary 
      } 
     } 
     .take(during: self.lifetime) 
    } 
} 

그런 다음 self.tableView.reactive.infiniteScrollingSignal()

+0

음에 모든 논리를 연결 할 수 있습니다 ...이를 일회용 속성을 저장하지 않아도되기 때문에 제 솔루션보다 조금 낫습니다.그러나 그것은'flatMap' 클로저를 호출하기 위해서 여전히 거짓 부울 값인'true'를 보내는 것처럼 "외관상의 문제"를 가지고 있습니다. 어쨌든 viewController의 코드를 명확하게 만들 수있는 좋은 제안입니다. –

+1

'Signal '에서'Signal '로 타입을 변경하고 빈 튜플 값을 보낼 수 있다고 생각합니다 :'observer .send (값 :())'. 나는 내 머리 꼭대기에서 잘 모르겠다. 그래서 나는 Bool을 사용했다. – jjoelson

+1

또한 매개 변수를 처리하는 방법은 'flatMap (.latest) {_ in ...}'과 같이 밑줄을 사용하는 것만 큼 신경 쓰지 않아도됩니다. – jjoelson