R.swift-優雅地引用專案資源

Doliant發表於2019-05-02

R.swift是一個高效引入iOS資源的框架,避免了使用字串引入資原始檔導致程式崩潰的尷尬。 目前R.swift支援到Swift4.0版本

優勢

使用程式碼的方式來引入資源:

  • 型別完整: 減少推斷和轉換方法返回值的型別
  • 編譯時檢查: 不會再因為不正確的字串導致App產生執行時崩潰
  • 自動補全: 不再需要輸入圖片名稱

示例:

之前:

let image = UIImage(named: "imageName")
複製程式碼

R.swift:

let image = R.image.imageName()
複製程式碼

功能

使用R.swift之後,可以使用R結構體來獲取資原始檔。如若資原始檔發生改變,R.swift會正確的清除\改變\增加資源。

R.swift目前支援如下幾種資源:

  • Images
  • Fonts
  • Resource files
  • Colors
  • Localized String
  • StoryBoard
  • Segues
  • Nibs
  • Reuseable cells

接入方式

CocoaPods

  1. 新增pod R.swiftPodfile檔案中之後終端執行pod install
  2. Xcode配置:在當前專案的targets中選擇Build phrase,點選+號選擇新增New Run Script Phase,
  3. Run Script移動至Compile sources之上,Check Pods Manifest.lock之下。在Run Script中新增:"$PODS_ROOT/R.swift/rswift" "$SRCROOT",
  4. 編譯你的專案,在Finder中你會看到R.generated.swiftPod檔案中,將該檔案拖動至專案中,切記千萬不要勾選Copy items if needed,
  5. 新增\刪除\修改資原始檔之後都需要重新command+B編譯專案,保證正確引用。

使用方式

1、Images

之前:

let png = UIImage(named: "png")
let jpg = UIImage(named: "jpg.jpg")
複製程式碼

R.swift:

let png = R.image.png()
let jpg = R.imgae.jpgJpg()
複製程式碼

2、Custom fonts

之前:

let customFont = UIFont(name: "Acme-Light", size: 22)
複製程式碼

R.swift:

let customFont = R.font.acmeLight(size: 22)
複製程式碼

3、Resource files

之前 :

let jsonURL = Bundle.main.url(forResource: "seed-data", withExtension: "json")
let jsonPath = Bundle.main.path(forResource: "seed-data", ofType: "json")
複製程式碼

R.swift:

let jsonURL = R.file.seedDataJson()
let jsonPath = R.file.seedDataJson.path()
複製程式碼

4、Localized Strings

之前:

let welcomeMessage = NSLocalizedString("welcome.message", comment: "")
let settingsTitle = NSLocalizedString("title", tableName: "Settings", comment: "")
let welcomeName = String(format: NSLocalizedString("welcome.withName", comment: ""), locale: NSLocale.current, "Alice")
let progress = String(format: NSLocalizedString("copy.progress", comment: ""), locale: NSLocale.current, 4, 23)
複製程式碼

R.swift:

let welcomeMessage = R.string.localizable.welcomeMessage()
let settingsTitle = R.string.settings.title()
let welcomeName = R.string.localizable.welcomeWithName("Alice")
let progress = R.string.localizable.copyProgress(completed: 4, total: 23)
複製程式碼

5、Segues

之前:

performSegue(withIdentifier: "openSettings", sender: self)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let settingsController = segue.destination as? SettingsController,
       let segue = segue as? CustomSettingsSegue, segue.identifier == "openSettings" {
      segue.animationType = .LockAnimation
      settingsController.lockSettings = true
    }
  }
複製程式碼

R.swift:

performSegue(withIdentifier: R.segue.overviewController.openSettings, sender: self)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if let typedInfo = R.segue.overviewController.openSettings(segue: segue) {
    typedInfo.segue.animationType = .LockAnimation
    typedInfo.destinationViewController.lockSettings = true
  }
複製程式碼

6、Nibs

之前:

let nameOfNib = "CustomView"
let customViewNib = UINib(nibName: "CustomView", bundle: nil)
let rootViews = customViewNib.instantiate(withOwner: nil, options: nil)
let customView = rootViews[0] as? CustomView

let viewControllerWithNib = CustomViewController(nibName: "CustomView", bundle: nil)
複製程式碼

R.swift:

let nameOfNib = R.nib.customView.name
let customViewNib = R.nib.customView()
let rootViews = R.nib.customView.instantiate(withOwner: nil)
let customView = R.nib.customView.firstView(owner: nil)

let viewControllerWithNib = CustomViewController(nib: R.nib.customView)
複製程式碼

7、Reusable table view cells

UITableView

之前:

class FaqAnswerController: UITableViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let textCellNib = UINib(nibName: "TextCell", bundle: nil)
    tableView.register(textCellNib, forCellReuseIdentifier: "TextCellIdentifier")
  }

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let textCell = tableView.dequeueReusableCell(withIdentifier: "TextCellIdentifier", for: indexPath) as! TextCell
    textCell.mainLabel.text = "Hello World"
    return textCell
  }
}
複製程式碼

R.swift:

class FaqAnswerController: UITableViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(R.nib.textCell)
  }

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let textCell = tableView.dequeueReusableCell(withIdentifier: R.nib.textCell.identifier, for: indexPath)!
    textCell.mainLabel.text = "Hello World"
    return textCell
  }
}
複製程式碼

UICollectionView

之前:

class RecentsController: UICollectionViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let talkCellNib = UINib(nibName: "TalkCell", bundle: nil)
    collectionView?.register(talkCellNib, forCellWithReuseIdentifier: "TalkCellIdentifier")
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TalkCellIdentifier", for: indexPath) as! TalkCell
    cell.configureCell("Item \(indexPath.item)")
    return cell
  }
}
複製程式碼

R.swift:

class RecentsController: UICollectionViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    collectionView?.register(R.nib.talkCell)
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.talkCell, for: indexPath)! // 此處跟tableView的使用方式還是有很大區別
    cell.configureCell("Item \(indexPath.item)")
    return cell
  }
}
複製程式碼

相關連結

github.com/mac-cain13/…

相關文章