RxSwift(五)(Rxswift對比swift,oc用法)

Rxswift(一)函數響應式編程思想php

RxSwift (二)序列核心邏輯分析react

RxSwift (三)Observable的建立,訂閱,銷燬編程

RxSwift(四)高階函數swift

RxSwift(五)(Rxswift對比swift,oc用法)數組

Rxswift (六)銷燬者Dispose源碼分析markdown

RxSwift(七)Rxswift對比swift用法app

RxSwift (十) 基礎使用篇 1- 序列,訂閱,銷燬ide

RxSwift學習之十二 (基礎使用篇 3- UI控件擴展)函數

@TOCoop

Rxswift 經常使用的數據處理

通知

實例1

  • 傳統代碼
複製代碼
  • Rxswift代碼
NotificationCenter.default.rx.notification(UIResponder.keyboardWillShowNotification)
            .subscribe(onNext: { (noti) in
                print(noti)
            })
        .disposed(by: disposeBag)
複製代碼

KVO

實例2

  • 傳統代碼
複製代碼
  • Rxswift代碼
//監聽person對象的name的變化
 self.person.rx.observeWeakly(String.self, "name")
            .subscribe(onNext: { (value) in
                print(value as Any)
            })
            .disposed(by: disposeBag)
複製代碼

手勢

實例3

  • 傳統代碼
複製代碼
  • Rxswift代碼
let disposeBag = DisposeBag()
 let tap = UITapGestureRecognizer()
        self.label.addGestureRecognizer(tap)
        self.label.isUserInteractionEnabled = true
        tap.rx.event.subscribe(onNext: { (tap) in
            print(tap.view)
        })
        .disposed(by: disposeBag)
複製代碼

網路請求

實例4

  • 傳統代碼
複製代碼
  • Rxswift代碼
let url = URL(string: "https://www.baidu.com")
 URLSession.shared.rx.response(request: URLRequest(url:  url!)).subscribe(onNext: { (response,data) in
            print(response)
        }, onError: { (error) in
            print(error)
        }, onCompleted: {
            
        }).disposed(by: disposeBag)
複製代碼

定時器

實例5

  • 傳統代碼
複製代碼
  • Rxswift代碼
let disposeBag = DisposeBag()
var timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        timer.subscribe(onNext: { (num) in
            print(num)
        })
        .disposed(by: disposeBag)
複製代碼

Rxswift UI 用法

UILabel

實例30

  • 傳統代碼
複製代碼
  • Rxswift代碼
  1. Rxswift簡單使用UILabel
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //建立文本標籤
        let label = UILabel(frame:CGRect(x:20, y:40, width:300, height:100))
        self.view.addSubview(label)
         
        //建立一個計時器(每0.1秒發送一個索引數)
        let timer = Observable<Int>.interval(0.1, scheduler: MainScheduler.instance)
         
        //將已過去的時間格式化成想要的字符串,並綁定到label上
        timer.map{ String(format: "%0.2d:%0.2d.%0.1d",
                          arguments: [($0 / 600) % 600, ($0 % 600 ) / 10, $0 % 10]) }
        .bind(to: label.rx.text)
        .disposed(by: disposeBag)
    }
}
複製代碼
  1. UILabel富文本 :將數據綁定到 attributedText 屬性上
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //建立文本標籤
        let label = UILabel(frame:CGRect(x:20, y:40, width:300, height:100))
        self.view.addSubview(label)
         
        //建立一個計時器(每0.1秒發送一個索引數)
        let timer = Observable<Int>.interval(0.1, scheduler: MainScheduler.instance)
         
        //將已過去的時間格式化成想要的字符串,並綁定到label上
        timer.map(formatTimeInterval)
        .bind(to: label.rx.attributedText)
        .disposed(by: disposeBag)
    }
     
    //將數字轉成對應的富文本
    func formatTimeInterval(ms: NSInteger) -> NSMutableAttributedString {
        let string = String(format: "%0.2d:%0.2d.%0.1d",
                         arguments: [(ms / 600) % 600, (ms % 600 ) / 10, ms % 10])
        //富文本設置
        let attributeString = NSMutableAttributedString(string: string)
        //從文本0開始6個字符字體HelveticaNeue-Bold,16號
        attributeString.addAttribute(NSAttributedStringKey.font,
                                     value: UIFont(name: "HelveticaNeue-Bold", size: 16)!,
                                     range: NSMakeRange(0, 5))
        //設置字體顏色
        attributeString.addAttribute(NSAttributedStringKey.foregroundColor,
                                     value: UIColor.white, range: NSMakeRange(0, 5))
        //設置文字背景顏色
        attributeString.addAttribute(NSAttributedStringKey.backgroundColor,
                                     value: UIColor.orange, range: NSMakeRange(0, 5))
        return attributeString
    }
}
複製代碼

UIButton

實例40

  • 傳統代碼
self.button.addTarget(self, action:#selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
    @objc func buttonTapped(sender:UIButton?){
        
    }
複製代碼
  • Rxswift代碼
let disposeBag = DisposeBag()
 //因爲tap事件裏點擊事件用的最多,因此RX默認的tap就是點擊事件
 self.button.rx.tap
            .subscribe(onNext: { () in
                print("點擊來了")
            })
            .disposed(by: disposeBag)



   //RXSwift監聽按鈕除了點擊外的事件:
    self.button.rx.controlEvent(.touchUpOutside).subscribe(onNext: { () in

        })
            .disposed(by: disposeBag)
複製代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    @IBOutlet weak var button: UIButton!
     
    override func viewDidLoad() {
        //按鈕點擊響應1
        button.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.showMessage("按鈕被點擊")
            })
            .disposed(by: disposeBag)

        //按鈕點擊響應2
        button.rx.tap
             .bind { [weak self] in
             self?.showMessage("按鈕被點擊")
               }
               .disposed(by: disposeBag)

//
    }

//按鈕標題(title)的綁定
func test1() {
//建立一個計時器(每1秒發送一個索引數)
let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
 
//根據索引數拼接最新的標題,並綁定到button上
timer.map{"計數\($0)"}
    .bind(to: button.rx.title(for: .normal))
    .disposed(by: disposeBag)
}

//按鈕富文本標題(attributedTitle)的綁定
func test2() {
 //建立一個計時器(每1秒發送一個索引數)
        let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
         
        //將已過去的時間格式化成想要的字符串,並綁定到button上
        timer.map(formatTimeInterval)
            .bind(to: button.rx.attributedTitle())
            .disposed(by: disposeBag)
}

//按鈕圖標(image)的綁定
func test3() {
//建立一個計時器(每1秒發送一個索引數)
let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
 
//根據索引數選擇對應的按鈕圖標,並綁定到button上
timer.map({
    let name = $0%2 == 0 ? "back" : "forward"
    return UIImage(named: name)!
})
.bind(to: button.rx.image())
.disposed(by: disposeBag)
}

//按鈕背景圖片(backgroundImage)的綁定
func test4() {
//建立一個計時器(每1秒發送一個索引數)
let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
 
//根據索引數選擇對應的按鈕背景圖,並綁定到button上
timer.map{ UIImage(named: "\($0%2)")! }
    .bind(to: button.rx.backgroundImage())
    .disposed(by: disposeBag)
}



//將數字轉成對應的富文本
    func formatTimeInterval(ms: NSInteger) -> NSMutableAttributedString {
        let string = String(format: "%0.2d:%0.2d.%0.1d",
                            arguments: [(ms / 600) % 600, (ms % 600 ) / 10, ms % 10])
        //富文本設置
        let attributeString = NSMutableAttributedString(string: string)
        //從文本0開始6個字符字體HelveticaNeue-Bold,16號
        attributeString.addAttribute(NSAttributedStringKey.font,
                                     value: UIFont(name: "HelveticaNeue-Bold", size: 16)!,
                                     range: NSMakeRange(0, 5))
        //設置字體顏色
        attributeString.addAttribute(NSAttributedStringKey.foregroundColor,
                                     value: UIColor.white, range: NSMakeRange(0, 5))
        //設置文字背景顏色
        attributeString.addAttribute(NSAttributedStringKey.backgroundColor,
                                     value: UIColor.orange, range: NSMakeRange(0, 5))
        return attributeString
    }
     
    //顯示消息提示框
    func showMessage(_ text: String) {
        let alertController = UIAlertController(title: text, message: nil, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "肯定", style: .cancel, handler: nil)
        alertController.addAction(cancelAction)
        self.present(alertController, animated: true, completion: nil)
    }
}
複製代碼

UIBarButtonItem

實例50

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UISwitch

實例60

  • 傳統代碼
複製代碼
  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    //分段選擇控件
    @IBOutlet weak var segmented: UISegmentedControl!
    //圖片顯示控件
    @IBOutlet weak var imageView: UIImageView!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        //建立一個當前須要顯示的圖片的可觀察序列
        let showImageObservable: Observable<UIImage> =
            segmented.rx.selectedSegmentIndex.asObservable().map {
                let images = ["js.png", "php.png", "react.png"]
                return UIImage(named: images[$0])!
        }
         
        //把須要顯示的圖片綁定到 imageView 上
        showImageObservable.bind(to: imageView.rx.image)
            .disposed(by: disposeBag)
    }

func test1() {
switch1.rx.isOn.asObservable()
    .subscribe(onNext: {
        print("當前開關狀態:\($0)")
    })
    .disposed(by: disposeBag)
}

func test2() {
switch1.rx.isOn
    .bind(to: button1.rx.isEnabled)
    .disposed(by: disposeBag)
}
}
複製代碼

UISegmentedControl

實例70

  • 傳統代碼
複製代碼
  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    //分段選擇控件
    @IBOutlet weak var segmented: UISegmentedControl!
    //圖片顯示控件
    @IBOutlet weak var imageView: UIImageView!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        //建立一個當前須要顯示的圖片的可觀察序列
        let showImageObservable: Observable<UIImage> =
            segmented.rx.selectedSegmentIndex.asObservable().map {
                let images = ["js.png", "php.png", "react.png"]
                return UIImage(named: images[$0])!
        }
         
        //把須要顯示的圖片綁定到 imageView 上
        showImageObservable.bind(to: imageView.rx.image)
            .disposed(by: disposeBag)
    }

func test1() {
segmented.rx.selectedSegmentIndex.asObservable()
    .subscribe(onNext: {
        print("當前項:\($0)")
    })
    .disposed(by: disposeBag)
}
}

複製代碼

UIActivityIndicatorView

實例80

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UITextField

實例90:UITextField使用Rxswift的基本用法

  • 傳統代碼
複製代碼
  • Rxswift代碼
self.textFiled.rx.text.orEmpty
            .subscribe(onNext: { (text) in
               print(text)
            })
            .disposed(by: disposeBag)
// textfiled綁定Button的文字
self.textFiled.rx.text
            .bind(to: self.button.rx.title())
            .disposed(by: disposeBag)
複製代碼

實例91:Rxswift監聽單個 textField 內容的變化

  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //建立文本輸入框
        let textField = UITextField(frame: CGRect(x:10, y:80, width:200, height:30))
        textField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(textField)
         
        //當文本框內容改變時,將內容輸出到控制檯上
        textField.rx.text.orEmpty.asObservable()
            .subscribe(onNext: {
                print("您輸入的是:\($0)")
            })
            .disposed(by: disposeBag)

//當文本框內容改變時,將內容輸出到控制檯上
textField.rx.text.orEmpty.changed
    .subscribe(onNext: {
        print("您輸入的是:\($0)")
    })
    .disposed(by: disposeBag)
    
    }
}
複製代碼

實例92:Rxswift將textField的內容綁定到其餘控件上

  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
         
        //建立文本輸入框
        let inputField = UITextField(frame: CGRect(x:10, y:80, width:200, height:30))
        inputField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(inputField)
         
        //建立文本輸出框
        let outputField = UITextField(frame: CGRect(x:10, y:150, width:200, height:30))
        outputField.borderStyle = UITextBorderStyle.roundedRect
        self.view.addSubview(outputField)
         
        //建立文本標籤
        let label = UILabel(frame:CGRect(x:20, y:190, width:300, height:30))
        self.view.addSubview(label)
         
        //建立按鈕
        let button:UIButton = UIButton(type:.system)
        button.frame = CGRect(x:20, y:230, width:40, height:30)
        button.setTitle("提交", for:.normal)
        self.view.addSubview(button)
         
         
        //當文本框內容改變
        let input = inputField.rx.text.orEmpty.asDriver() // 將普通序列轉換爲 Driver
            .throttle(0.3) //在主線程中操做,0.3秒內值若屢次改變,取最後一次
         
        //內容綁定到另外一個輸入框中
        input.drive(outputField.rx.text)
            .disposed(by: disposeBag)
         
        //內容綁定到文本標籤中
        input.map{ "當前字數:\($0.count)" }
            .drive(label.rx.text)
            .disposed(by: disposeBag)
         
        //根據內容字數決定按鈕是否可用
        input.map{ $0.count > 5 }
            .drive(button.rx.isEnabled)
            .disposed(by: disposeBag)
    }
}
複製代碼

實例93:Rxswift同時監聽多個 textField 內容的變化

  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    @IBOutlet weak var textField1: UITextField!
    @IBOutlet weak var textField2: UITextField!
    @IBOutlet weak var label: UILabel!
     
    override func viewDidLoad() {
         
        Observable.combineLatest(textField1.rx.text.orEmpty, textField2.rx.text.orEmpty) {
            textValue1, textValue2 -> String in
            return "你輸入的號碼是:\(textValue1)-\(textValue2)"
            }
            .map { $0 }
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
    }
}
複製代碼

實例94:Rxswift實現textField事件監聽 經過 rx.controlEvent 能夠監聽輸入框的各類事件,且多個事件狀態能夠自由組合。除了各類 UI 控件都有的 touch 事件外,輸入框還有以下幾個獨有的事件:

  • editingDidBegin:開始編輯(開始輸入內容)

  • editingChanged:輸入內容發生改變

  • editingDidEnd:結束編輯

  • editingDidEndOnExit:按下 return 鍵結束編輯

  • allEditingEvents:包含前面的全部編輯相關事件

  • Rxswift代碼

textField.rx.controlEvent([.editingDidBegin]) //狀態能夠組合
    .asObservable()
    .subscribe(onNext: { _ in
        print("開始編輯內容!")
    }).disposed(by: disposeBag)
複製代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
 
    //用戶名輸入框
    @IBOutlet weak var username: UITextField!
     
    //密碼輸入框
    @IBOutlet weak var password: UITextField!
     
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //在用戶名輸入框中按下 return 鍵
        username.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] (_) in
            self?.password.becomeFirstResponder()
        }).disposed(by: disposeBag)
         
         //在密碼輸入框中按下 return 鍵
        password.rx.controlEvent(.editingDidEndOnExit).subscribe(onNext: {
            [weak self] (_) in
            self?.password.resignFirstResponder()
        }).disposed(by: disposeBag)
    }
}
複製代碼

實例95:Rxswift實現textField事件監聽

  • Rxswift代碼
複製代碼

UITextView

實例100

  • 傳統代碼
複製代碼
  • Rxswift代碼
import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
     
    let disposeBag = DisposeBag()
     
    @IBOutlet weak var textView: UITextView!
     
    override func viewDidLoad() {
         
        //開始編輯響應
        textView.rx.didBeginEditing
            .subscribe(onNext: {
                print("開始編輯")
            })
            .disposed(by: disposeBag)
         
        //結束編輯響應
        textView.rx.didEndEditing
            .subscribe(onNext: {
                print("結束編輯")
            })
            .disposed(by: disposeBag)
         
        //內容發生變化響應
        textView.rx.didChange
            .subscribe(onNext: {
                print("內容發生改變")
            })
            .disposed(by: disposeBag)
         
        //選中部分變化響應
        textView.rx.didChangeSelection
            .subscribe(onNext: {
                print("選中部分發生變化")
            })
            .disposed(by: disposeBag)
    }
}
複製代碼

UITableView

  • 傳統Swift使用UITableView 實例110
//歌曲結構體
struct Music {
    let name: String //歌名
    let singer: String //演唱者
     
    init(name: String, singer: String) {
        self.name = name
        self.singer = singer
    }
}

//歌曲列表數據源
struct MusicListViewModel {
    let data = [
        Music(name: "無條件", singer: "陳奕迅"),
        Music(name: "你曾是少年", singer: "S.H.E"),
        Music(name: "從前的我", singer: "陳潔儀"),
        Music(name: "在木星", singer: "朴樹"),
    ]
}


class ViewController: UIViewController {
 
    //tableView對象
    @IBOutlet weak var tableView: UITableView!
     
    //歌曲列表數據源
    let musicListViewModel = MusicListViewModel()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //設置代理
        tableView.dataSource = self
        tableView.delegate = self
    }
}
 
extension ViewController: UITableViewDataSource {
    //返回單元格數量
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return musicListViewModel.data.count
    }
     
    //返回對應的單元格
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
        -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "musicCell")!
        let music = musicListViewModel.data[indexPath.row]
        cell.textLabel?.text = music.name
        cell.detailTextLabel?.text = music.singer
        return cell
    }
}
 
extension ViewController: UITableViewDelegate {
    //單元格點擊
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("你選中的歌曲信息【\(musicListViewModel.data[indexPath.row])】")
    }
}
複製代碼
  • Rxswift 的UITableView

實例111

/*這裏咱們將 data 屬性變成一個可觀察序列對象(Observable Squence), 而對象當中的內容和咱們以前在數組當中所包含的內容是徹底同樣的。 */
//歌曲列表數據源
struct MusicListViewModel {
    let data = Observable.just([
        Music(name: "無條件", singer: "陳奕迅"),
        Music(name: "你曾是少年", singer: "S.H.E"),
        Music(name: "從前的我", singer: "陳潔儀"),
        Music(name: "在木星", singer: "朴樹"),
    ])
}

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
 
    //tableView對象
    @IBOutlet weak var tableView: UITableView!
     
    //歌曲列表數據源
    let musicListViewModel = MusicListViewModel()
     
    //負責對象銷燬
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //將數據源數據綁定到tableView上
        musicListViewModel.data
            .bind(to: 
            /* rx.items(cellIdentifier:):這是 Rx 基於 cellForRowAt 數據源方法的一個封裝。 傳統方式中咱們還要有個 numberOfRowsInSection 方法, 使用 Rx 後就再也不須要了(Rx 已經幫咱們完成了相關工做)。 */ 
       tableView.rx.items(cellIdentifier:"musicCell")) { _, music, cell in
                cell.textLabel?.text = music.name
                cell.detailTextLabel?.text = music.singer
            }.disposed(by: disposeBag)
         
        //tableView點擊響應
       /* rx.modelSelected: 這是 Rx 基於 UITableView委託回調方法 didSelectRowAt 的一個封裝。 */ tableView.rx.modelSelected(Music.self).subscribe(onNext: { music in
            print("你選中的歌曲信息【\(music)】")
        }).disposed(by: disposeBag)
        /*DisposeBag:做用是 Rx 在視圖控制器或者其持有者將要銷燬的時候, 自動釋法掉綁定在它上面的資源。 它是經過相似「訂閱處置機制」方式實現(相似於 NotificationCenter 的 removeObserver)。*/
    }
}

複製代碼

UICollectionView

實例120

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UIPickerView

實例130

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UIDatePicker

實例140

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UISlider

實例150

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼

UIStepper

實例160

  • 傳統代碼
複製代碼
  • Rxswift代碼
複製代碼
相關文章
相關標籤/搜索