[Realm][Swift4対応 完全保存版] 5.データの更新と削除

はじめに

前回はRealmにおけるクエリについて説明をしました。

第5回目となる今回は、既存データの更新と削除をする方法について説明します。

過去記事は以下を参照ください。

環境

Xcode:9.4.1
Swift:4.1.2
Realm:3.7.4

目次

  1. 前準備
  2. データの更新
  3. データの削除
  4. Realmファイルの削除

“[Realm][Swift4対応 完全保存版] 5.データの更新と削除” の続きを読む

[Realm][Swift4対応 完全保存版] 4.クエリによるデータの取得

はじめに

前回はRealmにおけるモデルオブジェクトの作成方法とデータベースへの書き込み方法について説明しました。

第4回目となる今回は、クエリを使用してデータベースからデータを取得する方法について説明します。

過去記事は以下を参照ください。

環境

Xcode:9.4.1
Swift:4.1.2
Realm:3.7.4

目次

  1. 前準備
  2. 全データの取得
  3. 件数の取得
  4. 各レコードデータの参照
  5. filterによるクエリ
  6. 並べ替え

“[Realm][Swift4対応 完全保存版] 4.クエリによるデータの取得” の続きを読む

[Realm][Swift4対応 完全保存版] 2.モデルの定義

はじめに

第2回目となる今回は、Realmにおけるモデルの定義について説明します。

過去記事は以下を参照ください。

環境

Xcode:9.4.1
Swift:4.1.2
Realm:3.7.4

目次

“[Realm][Swift4対応 完全保存版] 2.モデルの定義” の続きを読む

[Realm][Swift4対応 完全保存版] 1.CocoaPodsによるRealmのインストールとプロジェクトの作成方法

はじめに

本サイトのアクセスログを見ると、Swiftで使用できるデータベースフレームワーク「Realm」の記事への参照が多いようです。

そこで、もっと詳細な説明を加えた、Swif4向けの完全保存版を作成することとしました。

第1回目となる今回は、プロジェクトを作成し、Realmをプロジェクトに組み込むまでを説明します。

なお、過去記事にてCarthageによるRealmの導入方法について説明しましたが、今回はCocoaPodsによるRealmのインストール方法について説明します。

※筆者としては、CocoaPodsによるRealmの組み込みの方が簡単だと感じました。

なお、CocoaPodsのインストール方法については、「CocoaPodsの導入」の記事を参照してください。

環境

Xcode:9.4.1
Swift:4.1.2
Realm:3.7.4

目次

  1. プロジェクトを作成する
  2. podファイルを作成する
  3. podファイルを編集する
  4. Realmをインストールする

“[Realm][Swift4対応 完全保存版] 1.CocoaPodsによるRealmのインストールとプロジェクトの作成方法” の続きを読む

[Realm] モデルを作成してデータを登録する

はじめに

Realmは様々なプラットフォームで使用可能な軽量データベースです。

Realmのインストールについては、過去の記事「CarthageとRealmのインストール」を参照してください。

本記事では、Realm用のモデル作成とデータの登録方法について備忘録として記載します。

環境

Xcode:9.2
Swift:4.0.3
RealmSwift:3.3.2

プロジェクトの作成

新規でSingle View Appのプロジェクトを作成したら、過去記事を参考にSwiftRealmを導入します。

モデルの作成

ここでは、部署と部署に属する社員を管理するモデルを作成します。

部署モデルでは、「部署名」とマネージャーの「氏名」、部に属する「社員」を管理できるようにします。

新規で「Department.swift」というSwift Fileを作成し、Departmentクラスを以下のように作成します。

import Foundation
import RealmSwift

class Department: Object {
    // 部署名
    @objc dynamic var name : String = ""
    // マネージャーの氏名
    @objc dynamic var manager : String = ""
    // 部に属する社員
    let employees = List<Employee>()
    
    // プライマリーキー
    override static func primaryKey() -> String? {
        return "name"
    }
    
    // インデックス
    override static func indexedProperties() -> [String] {
        return ["name"]
    }
}

Realm用のモデルを作成するには、「import RealmSwift」が必要です。また、クラスはObjectを継承する必要があります。

モデルに登録するそれぞれの項目はプロパティとして定義します。このとき「@objc dynamic var」で宣言します。

プロパティで使用できるデータ型にはBool、Int、Int8、Int16、Int32、Int64、Double、Float、String、Date、とDataがあります。

部署名やマネージャーの氏名は文字列を登録しますのでString型にしています。

また、部に属する社員は複数登録できるようにList<epmplyee>としています。

次に、社員を管理するEmplyeeクラスを作成します。このクラスは先ほど作成したDepartment.swiftの中に作成しても構いません。

class Employee : Object {
    // 社員の氏名
    @objc dynamic var name: String = ""
    // 社員の年齢
    @objc dynamic var age: String = ""
}

以上でモデルの作成は完了です。

データを登録してみる

それではデータを登録してみましょう。

はじめに部署のみを登録する方法をみてみます。

let realm = try! Realm()  // Realmの初期化

// Engineer型オブジェクトの作成
let dept = Department()
// Realmへのオブジェクトの書き込み
try! realm.write {
    dept.name = "システム部"
    dept.manager = "Bill"
    realm.add(dept)
}

はじめにRealmの初期化を行います。

次に、部署を管理するEngineerのオブジェクト(インスタンス)を作成します(4行目)。

あとは、realm.writeメソッドを使用してデータを登録します(6行目以降)。

Realm Browserで確認すると以下のようにデータが登録できていることが確認できます。参考「[Tips] Realmファイルの保存先を知るには?

この時点ではEmployeesは「0」になっているので登録されていないことがわかります。

子データを登録する

今度は、部署に属する社員を登録してみましょう。

社員を登録するには、まず登録先の部署を検索して取得する必要があります。

検索するにはRealmインスタンスのobjectsが持つfilterメソッドを使用します。以下にコード例を示します。ここでは「nameが’システム部’と等しい」を条件にして抽出しています。

let realm = try! Realm()
let dept = realm.objects(Department.self).filter("name == 'システム部'").first

つづいて、部に追加する社員を作成します。

let emp = Employee()
emp.name = "Oscar"
emp.age = "23"

あとは、writeメソッドを使用して登録をするだけです。部を検索して社員を登録するまでのコードを以下に示します。

let realm = try! Realm()
let dept = realm.objects(Department.self).filter("name == 'システム部'").first
let emp = Employee()
emp.name = "Oscar"
emp.age = "23"
try! realm.write {
    dept?.employees.append(emp)
}

登録が成功すると以下のように社員が登録できていることを確認できます。

子データを削除する

続いて子データを削除してみましょう。

先ほどのfilterメソッドを使用して、システム部を検索し、さらにシステム部に属する「Oscar」を削除する場合は以下のようにします。

// 子データの削除
let realm = try! Realm()
let dept = realm.objects(Department.self).filter("name == 'システム部'").first
let emp = dept?.employees.filter("name == 'Oscar'").first

try! realm.write {
    realm.delete(emp!)
}

削除はrealm.writeメソッドの中で「realm.delete(削除したいオブジェクト)」とします。

親データを削除する

親データも子データ同様にfilterメソッドで特定して削除をします。

// 親データの削除
let realm = try! Realm()
let dept = realm.objects(Department.self).filter("name == 'システム部'").first

try! realm.write {
    realm.delete(dept!)
}

Realmファイルを削除するには

Realmによるデータは、Realmファイルに格納されます。何らかの事情でリセットしたい場合は以下のコードを書くことでまっさらにすることができます。

let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
let realmURLs = [
    realmURL,
    realmURL.appendingPathExtension("lock"),
    realmURL.appendingPathExtension("note"),
    realmURL.appendingPathExtension("management")
]
for URL in realmURLs {
    do {
        try FileManager.default.removeItem(at: URL)
    } catch {
        // handle error
    }
}

[Navigation Controller] NavigationControllerを使用する

今回はNavigation Controllerを使用する方法をみていきます。

Xcode:9.2
Swift:4.0.3

本記事のサンプルは以下に置いておきます。

https://github.com/HIRO-NET/Swift-UI/tree/master/NavigationControllerSample

Navigation Controllerは、画面の上部にナビゲーションを表示して、複数のページを行ったり来たりできるようにします。

例えば、カレンダーアプリを見ると(下図)、画面の上部には「<2018」や検索ボタン、追加ボタンなどがあります。Navigation Controllerを使用するとこのようなナビゲーション付きのアプリを作成することができます。

 

 

Navigation Controllerの例

Navigation Controllerの配置

はじめにSingle Viewのプロジェクトを作ります。

次に、Main.storyboardを開き、View Controllerをクリックして選択しておきます。 

続いて Xcodeのメニューから[Editor]-[Embed In]-[Navigation Controller]を選択します。すると、Main.storyboardにはNavigation Controllerの画面が追加され、既存のView Controllerへと接続されます。追加されたNavigation Controllerの画面は、アプリ起動時に表示されることはありません。あくまでも表示されるのは、既存のView Controllerになります。

次に、もう1つView Controllerを追加して、既存のView Controllerとの行き来をできるようにします。

新しくView Controllerを追加したら、既存のView Controllerにボタンを一つ追加してみます。ここでは、Navigation Controllerの右上に追加をしてみましょう。

Navigation ControllerにはBar Button Itemというボタンを配置します。

続いて、配置したBar Button Itemをアイコンに変更してみましょう。Bar Button Item を選択して、System Itemを「Add」にします。すると、Bar Button Itemが「+」アイコンに変更されます。この他にも使用可能なアイコンがありますので試してみてください。

次に、「+」がタップされた時に、新しく追加されたView Controllerに遷移するように設定をします。「+」ボタンの上を[Control]キーを押しながら、遷移先のViewまでドラッグして離します。するとメニューが表示されるので「Show」を選択します。

新しく追加したView Controllerの上部には、Navigation Barが表示され、既存のView ControllerとSegueで接続されます。

以上でNavigation Controllerの設定は完了です。もう1つView Controllerを追加する場合も同様の手順で作業をします。

あとは実行をして動作を確認してみてください。複数画面で行き来ができるはずです。

 

[ライブラリ] FSCalendarを使用する(2) Tips

前回の記事「FSCalendarを使用する(1) storyboardへの貼り付けと使用準備」で、FSCalendarを利用する準備が整いました。

今回から実際の使用方法について見ていきます。

選択された日付を取得するには?

FSCalendarで選択された日を確認するために、はじめにLabelを1つ配置しておいてください。なお、配置したLabelはアウトレット接続をlabelDateという名前で作成しておいてください。

FSCalendarで日付がタップされた時の処理は以下の関数を使用します。

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    // 処理
}

選択された日付はdate変数に格納されます。このdateをCalendarクラスを使用して年、月、日で分解してからLabelに表示する例を以下に示します。

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    let tmpDate = Calendar(identifier: .gregorian)
    let year = tmpDate.component(.year, from: date)
    let month = tmpDate.component(.month, from: date)
    let day = tmpDate.component(.day, from: date)
    labelDate.text = "\(year)/\(month)/\(day)"
}

2018年2月14日を選択した例を以下に示します。

コードから日付を選択するには?

コードから任意の日付を選択するには、はじめにFSCalendarのアウトレットを準備しておきます。ここではアウトレット名をmyCalendarとしています。

Calendarクラスを使用して選択したい日を作成し、FSCalendarが持つselect関数の引数に渡します。これで指定した日を選択することができます。以下は2018年6月19日を選択する例です。

@IBOutlet weak var myCalendar: FSCalendar!

override func viewDidLoad() {
    super.viewDidLoad()
    
    let calendar = Calendar.current
    let selectDate = calendar.date(from: DateComponents(year: 2018, month: 6, day: 19))
    myCalendar.select(selectDate)
}

実行すると以下のように2018年6月19日が選択されます。

スクロール方向を変更する

スクロール方向を変更するには、scrollDirectionプロパティを使用します。既定値はhorizontal(水平方向)がセットされています。

// 水平方向(既定値)
myCalendar.scrollDirection = .horizontal
// 垂直方向
myCalendar.scrollDirection = .vertical

スクロールを禁止する

スクロールを禁止するには、scrollEnabledプロパティにfalseをセットします。既定はtrueなのでスクロールが可能になっています。

// スクロールの許可(既定値)
myCalendar.scrollEnabled = false
// スクロールの禁止
myCalendar.scrollEnabled = false

週表示にする

既定では1ヶ月分のカレンダーが表示されますが、1週間分だけ表示することが可能です。

scopeプロパティにweekをセットすると週表示になり、monthをセットすると月表示(既定値)になります。

// 週表示にする
myCalendar.scope = .week

 

[ライブラリ] CocoaPodsを使用してFSCalendarを導入する

iOSにはCalendarコントロールが提供されていないのですが、MITライセンスのFSCalendar(https://github.com/WenchaoD/FSCalendar/blob/master/README.md)というコントロールがあります。

今回は、CocoaPodsを使用して、このFSCalendarコントロールをプロジェクトに組み込む方法を見ていきます。

※CocoaPodsのインストール方法は「CocoaPodsの導入」を参照してください。

はじめに、新規でプロジェクトを作成しておきます。

次に、ターミナルを起動して、作成したプロジェクトディレクトリに移動して以下のコマンドを実行します。

pod init

成功するとプロジェクトディレクトリにPodfileが作成されます。

作成されたPodfileを開いて以下のように編集します。

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

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

  # Pods for WorkTimeManager
  pod 'FSCalendar', :git=> 'https://github.com/WenchaoD/FSCalendar'

end

Podfileの編集が完了したら、ターミナルに戻りPodfileがあるディレクトリ上で、以下のコマンドを実行してインストールをします。これによりプロジェクトにFSCalendarが取り込まれます。

pod install

ライブラリインストール完了移行は、以下のように「プロジェクト名.xcworkspace」をダブルクリックしてプロジェクトを開きます。

XcodeのProject Navigatorを確認するとFSCalendarが導入されていることを確認できます。

[Tips] CocoaPodsの導入

Swiftでの開発を進めていくにあたり、ライブラリの導入は不可欠です。

CocoaPodsというライブラリ管理ツールがありますので、その導入方法を見ていきます。

はじめにCocoaPodsをインストールします。

ターミナルを開いて以下のようにコマンドを入力してインストールを行います。

sudo gem install cocoapods

続いて、以下のコマンドでセットアップをします。Setup Completedと表示されれば完了です。

pod setup

[Tips] UIImageViewに画像を表示するには?

今回は、UIImageViewに画像を表示する方法を見ていきます。

はじめに、新規でSingle Viewのプロジェクトを作成します。

プロジェクト名称はImageSampleとしました。

プロジェクトの作成が完了したら、Project NavigatorでAssets.xcassetsを選択します。

一般的にプロジェクトで使用する画像はAssets.xcassetsフォルダに格納して使用します。

Assets.xcassetsフォルダを選択すると、以下のような画面が表示されます。プロジェクトで使用したい画像をfinderからドラッグ&ドロップして登録します。

画像を登録すると以下のようになります。イメージは3種類登録しておくことができますが、とりあえず1つでOKです。また、登録した画像の名称は左側で変更することができますので、コードから参照する時の任意の名称にしておきます。ここではsampleという名称にしています。

画像を表示するコードの実装

画像の準備ができたら、あとは画像を表示するコードの実装のみです。

Project NavigatorでViewController.swiftを選択したら、コードを以下のように編集します。

import UIKit

class ViewController: UIViewController {

    // 画像インスタンス用
    let imageSample = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // スクリーンサイズの取得
        let screenW:CGFloat = view.frame.size.width
        let screenH:CGFloat = view.frame.size.height
        
        // 画像を読み込んで、準備しておいたimageSampleに設定
        imageSample.image = UIImage(named: "sample")
        // 画像のフレームを設定
        imageSample.frame = CGRect(x:0, y:0, width:128, height:128)
        
        // 画像を中央に設定
        imageSample.center = CGPoint(x:screenW/2, y:screenH/2)
        
        // 設定した画像をスクリーンに表示する
        self.view.addSubview(imageSample)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

最初に、6行目で画像を入れる器(UIImageView)を準備しておきます。ここで準備したimageSampleに画像を読み込んだり、画像のフレームを設定したり、表示位置を設定したりして、最終的には画面(スクリーン)に表示します。

画像の読み込み〜表示までの処理はviewDidLoadの中で行います。

まずは、使用するデバイスのスクリーンサイズを取得しておきます(12,13行目)。このスクリーンサイズを使用して、後から画面の中央を計算するのに使用します。

続いて、画像を読み込みます(17行目)。画像を読み込む際は、Assets.xcassetsフォルダに登録した画像名を指定します。

画像の読み込みをしたら、表示サイズ(フレーム)を設定します(19行目)。

次に、画像がスクリーンの中央に表示されるようにします(22行目)。imageSample.centerは読み込んだ画像の中心です。この中心を、スクリーンの中央座標に合わせることで、画面中心に表示させます。

ここまでで、画像を中央に表示する準備は完了です。あとは25行目のようにしてassSubViewを実行することにより、画像が画面に表示されるようになります。

上記の実行例を以下に示します。