TableView에서 채팅 스타일 (RxSwift)

18716 단어 RxSwift
RxSwift를 할까라고 생각하고, 채팅풍의 UI를 우선 만들어 보았으므로 메모가 테라 투고

개요


  • 서버 등 두지 않기 때문에, 입력한 문자를 표시해 갈 뿐
  • 보내기 버튼을 누르면 텍스트 입력란에 입력 된 텍스트가 목록에 추가되어 표시됩니다.

    이것만 할 수 있습니다

    Rx 스타일의 사고 방식



    뭔가 Action이 있었을 때, 뭔가 하는 예약을 넣어 두는 것 같은 이미지로 만들었습니다

    수업 설명



    요소 클래스


    struct VoiceItem {
        var user: String
        var message: String
    }
    

    보내기 user 보내기 message 전용 클래스입니다.
    특히 어려운 일도하지 않습니다.

    셀 클래스


    class VoiceCell: UITableViewCell {
    
        @IBOutlet weak var userLabel: UILabel!
        @IBOutlet weak var messageLabel: UILabel!
    
        func item(_ newValue: VoiceItem) {
            userLabel.text = newValue.user
            messageLabel.text = newValue.message        
        }
    }
    
    usermessage 를 표시한다 UILabel 를 설치해 둡니다
    이전 요소 클래스를 받으면 각 라벨에 정보를 반영합니다.

    요소 관리 클래스


    class VoiceModel {
        let itemsEvent = Variable<[VoiceItem]>([])
        var items: Observable<[VoiceItem]> {
            return itemsEvent.asObservable()
        }
    
        var rx_items: AnyObserver<String> {
            return AnyObserver<String>(eventHandler: { (e) in
                self.addItem(item: VoiceItem(user: "A", message: e.element!))
                self.addItem(item: VoiceItem(user: "B", message: e.element! + "ですか!すごーい!"))
            })
        }
    
        init() {
        }
    
        func addItem(item: VoiceItem) {
            itemsEvent.value.append(item)
        }
    }
    

    여기서 RxSwift가 드디어 등장합니다items 가 요소의 배열입니다. 감시되는 대상이므로 Observable 로 정의합니다addItem 는 요소를 추가하는 메서드입니다.rx_items 는 뭔가 있을 때 하는 처리를 써 둡니다. 이것에 의해 감시되는 대상으로부터 이 처리를 호출해 받을 수가 있습니다. (감시되는 대상과 rx_items 의 연결은 ViewController 클래스에서 설명합니다)

    ViewController 클래스


    class ViewController: UIViewController {
    
        @IBOutlet weak var tableView: UITableView!
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var send: UIButton!
    
        let disposeBag = DisposeBag()
        let model = VoiceModel()    
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            // TableViewと要素の配列
            model.items.bindTo(self.tableView.rx.items(cellIdentifier: "Cell", cellType: VoiceCell.self)) { (row, element, cell) in
                cell.item(element)
            }.disposed(by: disposeBag)
    
            // 送信ボタンを押す
            self.send.rx.tap.map{ self.textField.text ?? "" }.bindTo(model.rx_items).disposed(by: disposeBag)
            self.send.rx.tap.subscribe(onNext: { _ in
                self.textField.text = nil
            }).disposed(by: disposeBag)
    
            // text入力された時とボタンの有効
            self.textField.rx.text.map { ($0?.characters.count)! > 0 }.bindTo(self.send.rx.isEnabled).disposed(by: disposeBag)
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    }
    

    여기가 이해하기 어렵다고 생각하기 때문에, 조금 상세한 생각을 ...

    TableView 및 요소 배열



    분해하고 설명합니다.
    model.items.bindTo()
    

    우선, 요소의 배열 items 에 변화가 있을 때에 bindTo() 의 인수에 처리를 하도록(듯이) 예약해 둡니다
    변경이 있었을 때와는 구체적으로는 items 에 요소가 추가되었을 때 등입니다
    self.tableView.rx.items(cellIdentifier: "Cell", cellType: VoiceCell.self)) { (row, element, cell) in
                cell.item(element)
            }
    
    self.tableView.rx.items 에는 이미 처리가 쓰여져 있으므로 그것을 사용합니다.
    보고 알 수 있을까 생각합니다만, Cell 를 만드는 처리( tablleView 에 추가도 해 줍니다)입니다cellIdentifier , cellType 는 평상시 사용하고 있을까 생각합니다
    Closure의 인수는
  • row 하지만 Index
  • element 가 요소 배열의 Index 번째 요소
  • cellcellType 로 지정된 형식의 Cell

  • 입니다
    이번에는, (row: Int, element: VoiceItem, cell: VoiceCell) 라고 하는 형태가 됩니다
    .disposed(by: disposeBag)
    

    마지막으로, disposed 입니다만, 이것은 처리의 예약의 파기를 해 줍니다
    이번은, DisposeBag() 를 인수에 건네주고 있으므로, 이 클래스( ViewController )가 파기될 때에 파기해 줍니다

    보내기 버튼을 누릅니다.


    self.send.rx.tap.map{ self.textField.text ?? "" }.bindTo(model.rx_items).disposed(by: disposeBag)
    

    보내기 버튼을 누르면 self.send.rx.tap로 모니터링 할 수 있습니다.tap 했을 때에 text가 있을까를 map 내에서 판단하고 있습니다 ( filter 하지만 좋을지도...)
    방금 만든 rx_items를 bind하여 rx_items에 쓴 처리를 할 수 있습니다.
    self.send.rx.tap.subscribe(onNext: { _ in
                self.textField.text = nil
        }).disposed(by: disposeBag)
    

    여기는 tap 가 있을 때 입력하던 text를 삭제합니다.

    text 입력되었을 때와 버튼의 유효


    self.textField.rx.text.map { ($0?.characters.count)! > 0 }.bindTo(self.send.rx.isEnabled).disposed(by: disposeBag)
    
    self.textField.rx.text 에서 텍스트 입력을 모니터링 할 수 있습니다.
    text가 1문자 이상 입력되었을 때, mapbool 의 값으로 해, self.send.rx.isEnabled 에 넣는 형태가 됩니다
    이제 텍스트를 입력하면 제출 버튼을 누를 수있는 처리를 예약 할 수있었습니다.





    유저명은 A 고정으로 하고 있습니다

    감상


  • UITableViewDelegate 또는 UITableViewDataSource 등을 설치할 필요가 없습니다.
  • (처음에 처리를 예약하면) 목록의 요소를 관리하지 않아도됩니다.
  • 텍스트 입력을 직접 모니터링하지 않아도됩니다.

    그리고 좋은 것 (간단한 것)이 많았습니다.
    RxSwift는 안쪽이 깊기 때문에 아직 앞으로 해 나가려고 생각합니다.
  • 좋은 웹페이지 즐겨찾기