Help us understand the problem. What is going on with this article?

Macアプリ初心者:Realmの導入(CocoaPods利用)

今回はMacアプリでDBを使いたくてRealmについて調べてみました。
以前に作成したプロジェクトに組み込んでみます。

完成イメージ

完成イメージ

環境

  • macOS Mojave:10.14.6
  • Xcode:10.3
  • CocoaPods:1.7.5

Realm インストール

Podfile の作成

$ pod init
$ ls
NSTableViewSample NSTableViewSample.xcodeproj Podfile

Realm インストール

Podfile に pod 'RealmSwift' を追加

$ vi Podfile
# Uncomment the next line to define a global platform for your project
# platform :osx, '10.14'

target 'NSTableViewSample' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for NSTableViewSample
  pod 'RealmSwift'

end

Realm インストール

$ pod install
Analyzing dependencies
Downloading dependencies
Installing Realm (3.17.3)
Installing RealmSwift (3.17.3)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 2 total pods installed.

[!] Automatically assigning platform `osx` with version `10.14` on target `NSTableViewSample` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.

Realm を使う

pod install で作成された workspace を開く

$ open NSTableViewSample.xcworkspace

株式情報保存用のクラス(StockInfo)を作成

Object クラスを継承して作成します。

StockInfo.swift
import Cocoa
import RealmSwift

class StockInfo: Object {
    @objc dynamic var name = ""
    @objc dynamic var price = -1
    @objc dynamic var status = StockStatus.flat.rawValue
    @objc dynamic var createdAt = Date()
}

extension StockInfo {
    /// 状態をEnum形式で返却
    var stockStatus: StockStatus {
        get {
            return StockStatus(rawValue: self.status) ?? StockStatus.flat
        }
        set {
            self.status = newValue.rawValue
        }
    }

    /// StockInfo オブジェクトを作成
    class func create(realm: Realm, name: String, price: Int, status: StockStatus) -> StockInfo {
        let stockInfo = realm.create(StockInfo.self)
        stockInfo.name = name
        stockInfo.price = price
        stockInfo.stockStatus = status

        return stockInfo
    }

    /// 企業名で部分一致検索(空の場合は全件取得)
    class func objects(searchValue: String = "") -> Results<StockInfo> {
        var result = try! Realm().objects(StockInfo.self)
        let searchValue = searchValue.trimmingCharacters(in: .whitespaces)
        if searchValue != "" {
            result = result.filter("name CONTAINS %@", searchValue)
        }

        return result.sorted(byKeyPath: "createdAt")
    }

    /// デバッグ用
    class func debugInitData() {
        let realm = try! Realm()
        try! realm.write {
            // データクリア
            realm.deleteAll()

            // サンプルデータ作成
            let _ = StockInfo.create(realm: realm, name: "○○株式会社", price: 1000, status: .up)
            let _ = StockInfo.create(realm: realm, name: "○×水産", price: 12345, status: .down)
            let _ = StockInfo.create(realm: realm, name: "株式会社□○", price: 345, status: .flat)
            let _ = StockInfo.create(realm: realm, name: "×△ホールディングス", price: 321, status: .up)
            let _ = StockInfo.create(realm: realm, name: "ABC BANK", price: 20, status: .down)
            let _ = StockInfo.create(realm: realm, name: "▼○重工", price: 98000, status: .up)

            // サンプル用に1,000 件データを作成
            for i in 1...1_000 {
                let status = StockStatus.init(rawValue: Int.random(in: 0..<3))!
                let price = Int.random(in: -1..<10_000_000)
                let _ = StockInfo.create(realm: realm, name: "○△×株式会社 \(i)", price: price, status: status)
            }
        }
    }

}

株価情報の状態を表すEnum(StockStatus)を作成

StockStatus.swift
import Cocoa

enum StockStatus: Int {
    case flat = 0
    case up
    case down

    /// 状態ごとのImageオブジェクト
    var image: NSImage {
        get {
            switch self {
            case .flat:
                return NSImage(named: NSImage.Name("flat"))!
            case .up:
                return NSImage(named: NSImage.Name("up"))!
            case .down:
                return NSImage(named: NSImage.Name("down"))!
            }
        }
    }

    /// 状態ごとのカラーオブジェクト
    var color: NSColor {
        get {
            switch self {
            case .flat:
                return .gray
            case .up:
                return .green
            case .down:
                return .red
            }
        }
    }
}

StockInfo クラスを利用して株価情報を表示

細かい説明は省きますが、リファクタリングして多少見やすくなっているはずです。

ViewController.swift
import Cocoa

class ViewController: NSViewController {

    // MARK: - IBOutlet
    @IBOutlet private weak var tableView: NSTableView! {
        didSet {
            self.tableView.dataSource = self
            self.tableView.delegate = self

            self.tableView.headerView = nil
            self.tableView.rowHeight = 88
        }
    }
    @IBOutlet private weak var countTextField: NSTextField!


    // MARK: - private variables
    private var stockValues = StockInfo.objects()


    // MARK: - override func
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        // デバッグ用にデータ作成
        StockInfo.debugInitData()
        // 株価情報をViewに反映
        self.updateStockValuesCount()
    }

    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }


    // MARK: - private func

    private func updateStockValuesCount() {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        let commaString = formatter.string(from: NSNumber(value: self.stockValues.count))!
        self.countTextField.stringValue = "\(commaString)件"
    }


    // MARK: - actions

    @IBAction func actionSearchField(_ sender: NSSearchField) {
        self.stockValues = StockInfo.objects(searchValue: sender.stringValue)
        self.tableView.reloadData()
        self.updateStockValuesCount()
    }

}

extension ViewController: NSTableViewDataSource, NSTableViewDelegate {

    // MARK: - NSTableViewDataSource
    func numberOfRows(in tableView: NSTableView) -> Int {
        return self.stockValues.count
    }


    // MARK: - NSTableViewDelegate
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let result = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyView"), owner: self) as! CustomNSTableCellView

        // Set the stringValue of the cell's text field to the nameArray value at row
        let stock = self.stockValues[row]
        result.image = stock.stockStatus.image
        result.name = stock.name
        result.color = stock.stockStatus.color
        result.price = stock.price

        // Return the result
        return result
    }
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away