Last active
August 29, 2015 14:15
-
-
Save laiso/ade3bcae8592f87c1f5f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Cocoa Docs — Realm: a mobile database that replaces Core Data & SQLite</title> | |
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700,900,200italic,300italic,400italic,600italic,700italic,900italic' rel='stylesheet' type='text/css'> | |
<link href="/css/realm.css" rel="stylesheet" media="all"> | |
<meta property="og:image" content="http://realm.io/assets/realmDark.jpg" /> | |
<meta property="og:type" content="Website" /> | |
<meta property="og:title" content="Cocoa Docs - Realm: a mobile database that replaces Core Data & SQLite" /> | |
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | |
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> | |
<!--[if lt IE 9]> | |
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> | |
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> | |
<![endif]--> | |
<!-- jQuery (necessary for Presentz and Bootstrap's JavaScript plugins) --> | |
<script src="/js/jquery-1.11.0.min.js"></script> | |
<!-- Include all compiled plugins (below), or include individual files as needed --> | |
<script src="/js/bootstrap.min.js"></script> | |
<!-- Include MediaElement player --> | |
<script src="/mediaelement/mediaelement.min.js"></script> | |
<script src="/js/realm.js"></script> | |
<link rel="shortcut icon" href="/img/favicon.ico"> | |
<link rel="shortcut icon" href="/img/favicon.png" sizes="32x32"> | |
<link rel="alternate" type="application/rss+xml" title="Realm News" href="http://feeds.feedburner.com/realmio" /> | |
</head> | |
<body data-spy="scroll" data-target=".navbar-docs" class="docs"> | |
<header> | |
<!-- Static navbar --> | |
<div class="navtop navbar navbar-default" role="navigation"> | |
<div class="container-fluid"> | |
<div class="row"> | |
<div class="col-sm-8 col-sm-offset-2"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</button> | |
<a class="navbar-brand hidden-sm hidden-md hidden-lg" href="/">Realm</a> | |
</div> | |
<div class="navbar-collapse collapse"> | |
<ul class="nav nav-pills nav-justified"> | |
<li id="nav-home"><a href="/">Home</a></li> | |
<li id="nav-users"><a href="/users">Users</a></li> | |
<li id="nav-news"><a href="/news/">News</a></li> | |
<li id="nav-docs"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Docs<span class="caret"></span></a> | |
<ul class="dropdown-menu" role="menu"> | |
<li><a href="/docs/java/0.78.0/">Java</a></li> | |
<li><a href="/docs/cocoa/0.90.5/">Cocoa</a></li> | |
</ul> | |
</li> | |
<li id="nav-download" class="hidden-xs"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Download<span class="caret"></span></a> | |
<ul class="dropdown-menu" role="menu"> | |
<li><a href="http://static.realm.io/downloads/java/realm-java-0.78.0.zip">Java</a></li> | |
<li><a href="http://static.realm.io/downloads/cocoa/realm-cocoa-0.90.5.zip">Cocoa</a></li> | |
</ul> | |
</li> | |
<li id="nav-source"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Source<span class="caret"></span></a> | |
<ul class="dropdown-menu" role="menu"> | |
<li><a href="https://github.com/realm/realm-java">Java</a></li> | |
<li><a href="https://github.com/realm/realm-cocoa">Cocoa</a></li> | |
</ul> | |
</li> | |
<li id="nav-pricing"><a href="/pricing">Pricing</a></li> | |
<li id="nav-jobs"><a href="/jobs">Jobs</a></li> | |
<li id="nav-kr"><a href="/kr">한국어</a></li> | |
</ul> | |
</div><!--/.nav-collapse --> | |
</div> | |
</div> | |
</div><!--/.container-fluid --> | |
</div> | |
<!-- | |
<a class="when-link" href="http://j.mp/realm-office-hours"><div class="when">Do you have questions about Realm? Come chat with us during <strong><a class="when-link" href="http://j.mp/realm-office-hours">online office hours</a></strong>!</div></a> | |
--> | |
<div class="container"> | |
<div class="branding"> | |
<div class="tagline"> | |
Realm is a mobile database: a replacement for SQLite & Core Data. This is our documentation. | |
</div> | |
</div> | |
</div><!-- /container --> | |
</header> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-8"> | |
<div class="docs-wrapper"> | |
<!-- | |
DO NOT TRANSLATE THIS FILE | |
WE WILL KEEP THIS IN ENGLISH | |
AT THE TOP OF EVERY TRANSLATION | |
THANKS :) | |
--> | |
<div class="row"> | |
<div class="col-md-12"> | |
<p><small> | |
Documentation available in the following languages — want to help us with another language? Email <a href="mailto:[email protected]">Arwa</a>! | |
</small></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/docs/cocoa/0.90.5/">English</a></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/cn/docs/cocoa/0.87.1/">中文</a></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/es/docs/cocoa/0.90.4/">Español</a></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/fr/docs/cocoa/0.86.3/">Français</a></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/jp/docs/cocoa/0.90.5/">日本語</a></p> | |
</div> | |
<div class="col-md-2"> | |
<p><a href="/kr/docs/cocoa/0.90.4/">한국어</a></p> | |
</div> | |
</div> | |
<h2 id="section">はじめに</h2> | |
<h3 id="section-1">インストール</h3> | |
<div class="flex-video widescreen install-video-container"> | |
<iframe width="420" height="315" style="margin-top: 0; margin-bottom:0px;" src="//www.youtube.com/embed/J5eN8MyLVvc" frameborder="0" allowfullscreen=""></iframe> | |
</div> | |
<!-- Nav tabs --> | |
<ul class="nav nav-tabs getting-started" role="tablist"> | |
<li class="active"><a href="#manual-install" role="tab" data-toggle="tab">Manual Installation</a></li> | |
<li><a href="#cocoapods-install" role="tab" data-toggle="tab">CocoaPods</a></li> | |
<li><a href="#dynamic-framework-install" role="tab" data-toggle="tab">iOS 8 Dynamic Framework</a></li> | |
<li><a href="#carthage-install" role="tab" data-toggle="tab">Carthage</a></li> | |
</ul> | |
<!-- Tab panes --> | |
<div class="tab-content getting-started"> | |
<div class="tab-pane active" id="manual-install"> | |
<ol> | |
<li>ここから <a href="http://static.realm.io/downloads/cocoa/latest">最新のRealm</a> をダウンロードしてください。</li> | |
<li>この中にある <code>ios/</code> または <code>osx/</code> フォルダから <code>Realm.framework</code> をXcodeのナビゲータエリアにドラッグ&ドロップしてください。この時、 <strong>Copy items if needed</strong> にチェックが入ってることを確認してから <strong>Finish</strong> をクリックしてください。</li> | |
<li>ナビゲータエリアでプロジェクトをクリックし、アプリのTargetを選択します。<br /> | |
<strong>Build Phases</strong> タブの <strong>Link Binary with Libraries</strong> から、 <strong>libc++.dylib</strong> を追加してください。</li> | |
<li>Swiftの場合は、 さらに <code>Swift/RLMSupport.swift</code> も同様にドラッグ&ドロップし、 <strong>Copy items if needed</strong> にチェックが入った状態で、ナビゲータエリアに追加してください。 </li> | |
<li>OSXプロジェクトの場合は、<strong>Build Phase</strong> タブのパネルの左上にある <code>+</code> ボタンをクリックし、<code>New Copy Files Phase</code> を選択して新しくビルドフェーズを追加してください。<br /> | |
そして名前を <code>Copy Frameworks</code> に変更し、 <code>Destination</code> を <code>Frameworks</code> に変え、 <code>Realm.framework</code> を追加してください。</li> | |
</ol> | |
</div> | |
<div class="tab-pane" id="cocoapods-install"> | |
<ol> | |
<li>Podfileに <code>pod "Realm"</code> を追加してください。</li> | |
<li>コマンドラインで <code>pod install</code> を実行してください。</li> | |
<li>CocoaPodsによって作成された <code>.xcworkspace</code> をXcodeで開いてください。</li> | |
<li>Swiftの場合は以下もご覧ください | |
<ul> | |
<li>ここから <a href="http://static.realm.io/downloads/cocoa/latest">最新のRealm</a> をダウンロードしてください。</li> | |
<li><code>Swift/RLMSupport.swift</code> をXcodeのナビゲータエリアにドラッグ&ドロップしてください。この時、 <strong>Copy items if needed</strong> にチェックが入ってることを確認してから <strong>Finish</strong> をクリックしてください。</li> | |
</ul> | |
</li> | |
</ol> | |
<p>詳しくは、<a href="http://cocoapods.org">CocoaPods website</a> をご覧ください。</p> | |
</div> | |
<div class="tab-pane" id="dynamic-framework-install"> | |
<ol> | |
<li>ここから <a href="http://static.realm.io/downloads/cocoa/latest">最新のRealm</a> をダウンロードしてください。</li> | |
<li><code>ios/</code> フォルダから <code>Realm-dynamic.framework</code> と <code>Realm-dynamic-simulator.framework</code> をXcodeのナビゲータエリアにドラッグ&ドロップしてください。この時、 <strong>Copy items if needed</strong> にチェックが入ってることを確認してから <strong>Finish</strong> をクリックしてください。</li> | |
<li><strong>Build Phase</strong> タブのパネルの左上にある <code>+</code> ボタンをクリックし、<code>New Copy Files Phase</code> を選択して新しくビルドフェーズを追加してください。<br /> | |
そして名前を <code>Copy Frameworks</code> に変更し、 <code>Destination</code> を <code>Frameworks</code> に変え、 <code>Realm-dynamic.framework</code> を追加してください。</li> | |
</ol> | |
<p>注意: Dynamic Frameworkは、iOS8でのみ使用可能です。</p> | |
</div> | |
<div class="tab-pane" id="carthage-install"> | |
<ol> | |
<li><code>github "realm/realm-cocoa"</code> をCartfileに追加してください。</li> | |
<li><code>carthage update</code> を実行してください。<br /> | |
詳しくは、<a href="https://github.com/Carthage/Carthage">Carthage project</a> をご覧ください。</li> | |
</ol> | |
</div> | |
</div> | |
<h3 id="realm-browser">Realm Browser</h3> | |
<p><img class="img-responsive img-rounded" src="/assets/docs/browser.png" /></p> | |
<p><strong>RealmBrowser</strong> は、Realmの中で使われるている <code>.realm</code> ファイルを閲覧、編集するMacアプリです。<a href="http://static.realm.io/downloads/cocoa/latest">最新のRealm</a> の <code>browser/</code> フォルダの中に入っています。 | |
また、<strong>Tools > Generate demo database</strong> を選択することでサンプルデータを含んだ、テスト用のRealmデータベースを作ることもできます。</p> | |
<h3 id="xcode-plugin">Xcode Plugin</h3> | |
<div class="alert alert-warning"> | |
<p>RealmPluginは、現在、一時的に使用できません。修正中ですので、しばらくお待ち下さい。</p> | |
</div> | |
<!-- | |
Our Xcode plugin makes it easy to generate new Realm models. | |
<img class="img-responsive img-rounded" src="/assets/docs/plugin.png" /> | |
The easiest way to install the Realm Xcode plugin is through [Alcatraz](http://alcatraz.io) under the name "RealmPlugin". You can also install the plugin manually by opening `plugin/RealmPlugin.xcodeproj` contained in the [release zip](http://static.realm.io/downloads/cocoa/latest) and clicking build. You will need to quit and relaunch Xcode to see our plugin. If you use the Xcode menu to create a new file (File > New > File… — or ⌘N) you should see a new option to create a new Realm model. | |
--> | |
<h3 id="api-reference">API Reference</h3> | |
<p>Realmで使用できるClass, Methodに関しては、<a href="api/">API Reference</a> をご覧ください。</p> | |
<h3 id="section-2">サンプル</h3> | |
<p><a href="http://static.realm.io/downloads/cocoa/latest">最新のRealm</a> の<code>examples/</code>ファルダにObjective-C, Swift, RubyMotionそれぞれのiOS/Macのサンプルコードがあります。RealmのMigration, UITableViewControllerとの使い方、Encryption, コマンドラインツールなど、様々な機能が紹介されていますので是非、ご参考にしてください。</p> | |
<h3 id="section-3">ヘルプ</h3> | |
<ul> | |
<li><a href="http://eepurl.com/VEKCn">community newsletter</a> に参加することで定期的にRealmに関するのTipsやUseCase, ブログポストやチュートリアルなど、Realmの最新情報がGetできます。</li> | |
<li><strong>StackOverflow</strong>: 以前の質問はStackOverflowで <a href="https://stackoverflow.com/questions/tagged/realm?sort=newest">#realm</a> をご覧ください。</li> | |
<li><strong>Twitter</strong>: お気軽に <a href="http://twitter.com/realm">@realm</a> かハッシュタグ <a href="https://twitter.com/search?q=%23realm&src=typd&f=realtime">#realm</a> でツイートしてください。</li> | |
<li><strong>Email</strong>: <a href="https://groups.google.com/d/forum/realm-cocoa">[email protected]</a></li> | |
</ul> | |
<h2 id="section-4">モデル</h2> | |
<p>Realmで使うモデルクラスは、一般的なObjective-Cのインターフェイスで、@propertyを使って定義できます。 | |
RealmObjectクラスまたは、自分で作ったRealmモデルクラスのサブクラスを作ることで、簡単に作ることができます。 | |
また、他のObjective-Cクラスのように、メソッドやプロトコルを追加することもできます。</p> | |
<p>注意することは、Realmモデルクラスのインスタンスは、他のスレッドに渡して使うことができません。また、Realmモデルクラスのプロパティのインスタンス変数に直接、アクセスすることはできません。</p> | |
<p><a href="#xcode-plugin">XcodePlugin</a> をお使いの場合は、 “Nex File…” からテンプレートを選択することでRealmモデルクラスを簡単に作れます。</p> | |
<p>リレーションシップやネストしたデータ構造も、他のRLMObjectのサブクラスやRLMArrayを使って作れます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="cp">#import <Realm/Realm.h></span> | |
<span class="k">@class</span> <span class="nc">Person</span>; | |
<span class="c1">// Dog model</span> | |
<span class="k">@interface</span> <span class="nc">Dog</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="n">Person</span> <span class="o">*</span><span class="n">owner</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Dog</span><span class="p">)</span> <span class="c1">// define RLMArray<Dog></span> | |
<span class="c1">// Person model</span> | |
<span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSDate</span> <span class="o">*</span><span class="n">birthdate</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="n">RLMArray</span><span class="o"><</span><span class="n">Dog</span><span class="o">></span> <span class="o">*</span><span class="n">dogs</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Person</span><span class="p">)</span> <span class="c1">// define RLMArray<Person></span> | |
<span class="c1">// Implementations</span> | |
<span class="k">@implementation</span> <span class="nc">Dog</span> | |
<span class="k">@end</span> <span class="c1">// none needed</span> | |
<span class="k">@implementation</span> <span class="nc">Person</span> | |
<span class="k">@end</span> <span class="c1">// none needed</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">import</span> <span class="n">Realm</span> | |
<span class="c1">// Dog model</span> | |
<span class="k">class</span> <span class="nl">Dog</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="nl">owner</span><span class="p">:</span> <span class="n">Person</span><span class="o">?</span> <span class="c1">// Can be optional</span> | |
<span class="p">}</span> | |
<span class="c1">// Person model</span> | |
<span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">birthdate</span> <span class="o">=</span> <span class="bp">NSDate</span><span class="p">(</span><span class="nl">timeIntervalSince1970</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">dogs</span> <span class="o">=</span> <span class="n">RLMArray</span><span class="p">(</span><span class="nl">objectClassName</span><span class="p">:</span> <span class="n">Dog</span><span class="p">.</span><span class="n">className</span><span class="p">())</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>Realmは、開発者が定義するRealmモデルクラスをアプリ起動時に、パースし読み込んでいます。Realmモデルクラスは、正しく定義してください。</p> | |
<p>詳しくは <a href="api/Classes/RLMObject.html#">RLMObject</a> をご覧ください。</p> | |
<h3 id="section-5">プロパティの型</h3> | |
<p>Realmでは、以下のプロパティが使えます。<br /> | |
<code>BOOL</code>, <code>bool</code>, <code>int</code>, <code>NSInteger</code>, <code>long</code>, <code>long long</code>, <code>float</code>, <code>double</code>, <code>CGFloat</code>, <code>NSString</code>, <code>NSDate</code>, <code>NSData</code> </p> | |
<p>一対一や一対多のようなリレーションシップのために、<code>RLMArray\<_Object_\></code>, <code>RLMObject</code> のプロパティも定義できます。</p> | |
<h3 id="section-6">プロパティ属性</h3> | |
<p>Realmでは、 <code>nonatomic</code>, <code>atomic</code>, <code>strong</code>, <code>copy</code>, <code>weak</code> のようなObjective-Cのプロパティ属性が無視されます。 | |
Realmの中では、独自の最適化された属性が使われます。 | |
そのため、混乱を避けるために、Realmモデルクラスを宣言するとき、プロパティ属性を付けないことを推奨しています。 | |
しかし、プロパティ属性を付けた場合、<code>RLMObject</code> がRealmに保存されるまで有効になります。 | |
<code>setter</code>, <code>getter</code> 属性でセッター/ゲッターの名前を変えた場合、RLMObjectがRealmに追加される前かどうかに関わらず使うことができます。</p> | |
<h3 id="realm">Realmモデルクラスのカスタマイズ</h3> | |
<p>クラスメソッドをオーバーライドすることで、さらに機能を追加することもできます:</p> | |
<ul> | |
<li><a href="api/Classes/RLMObject.html#//api/name/attributesForProperty:"><code>+attributesForProperty:</code></a>:インデックスを作成するなど、プロパティの属性が設定できます。</li> | |
<li><a href="api/Classes/RLMObject.html#//api/name/defaultPropertyValues"><code>+defaultPropertyValues</code></a>: プロパティのデフォルト値を設定することができます。</li> | |
<li><a href="api/Classes/RLMObject.html#//api/name/primaryKey"><code>+primaryKey</code></a>: PrimaryKeyが指定できます。</li> | |
</ul> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSInteger</span> <span class="kt">id</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="k">@implementation</span> <span class="nc">Person</span> | |
<span class="p">+</span> <span class="p">(</span><span class="bp">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nf">primaryKey</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">@"id"</span><span class="p">;</span> | |
<span class="p">}</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="kt">id</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="kr">override</span> <span class="k">class</span> <span class="k">func</span> <span class="n">primaryKey</span><span class="p">()</span> <span class="o">-></span> <span class="n">String</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">"id"</span> | |
<span class="p">}</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<ul> | |
<li><a href="api/Classes/RLMObject.html#//api/name/ignoredProperties"><code>+ignoredProperties</code></a>: 指定されたプロパティは、Realmに保存されません。</li> | |
</ul> | |
<h2 id="section-7">書き込み</h2> | |
<div class="alert alert-warning"> | |
<p>Realmへのオブジェクトの追加、変更、削除は、必ずトランザクションを使って行ってください。</p> | |
</div> | |
<p>Realmモデルクラスは、インスタンス化し、他のオブジェクトと同じように使います。スレッド間やアプリの再起動時にRealmオブジェクトのデータを共有するときは、Realmにデータを一度保存しなければいけません。 | |
これらの操作は、トランザクションの中で行ってください。以下のようにオブジェクトを追加します。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Create object</span> | |
<span class="n">Person</span> <span class="o">*</span><span class="n">author</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Person</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span> | |
<span class="n">author</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">@"David Foster Wallace"</span><span class="p">;</span> | |
<span class="c1">// Get the default Realm</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">realm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">];</span> | |
<span class="c1">// You only need to do this once (per thread)</span> | |
<span class="c1">// Add to Realm with transaction</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">beginWriteTransaction</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="nl">addObject</span><span class="p">:</span><span class="n">author</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">commitWriteTransaction</span><span class="p">];</span> | |
<span class="c1">// Update an object with a transaction</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">beginWriteTransaction</span><span class="p">];</span> | |
<span class="n">author</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">@"Thomas Pynchon"</span><span class="p">;</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">commitWriteTransaction</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Create a Person object</span> | |
<span class="k">let</span> <span class="n">author</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span> | |
<span class="n">author</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"David Foster Wallace"</span> | |
<span class="c1">// Get the default Realm</span> | |
<span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealm</span><span class="p">()</span> | |
<span class="c1">// You only need to do this once (per thread)</span> | |
<span class="c1">// Add to the Realm inside a transaction</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">beginWriteTransaction</span><span class="p">()</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">addObject</span><span class="p">(</span><span class="n">author</span><span class="p">)</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">commitWriteTransaction</span><span class="p">()</span> | |
<span class="c1">// Update an object with a transaction</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">beginWriteTransaction</span><span class="p">()</span> | |
<span class="n">author</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"Thomas Pynchon"</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">commitWriteTransaction</span><span class="p">()</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>オブジェクトをRealmに追加した後は、ずっと使うことができ、全ての変更が記録されていきます。(ただし、変更時は、トランザクションを使わなければいけません) もし、同じRealmを複数のスレッドで共有している場合、トランザクションがコミットされた時点で、別のスレッドにもその変更が適用されます。</p> | |
<p>書き込み処理が行われている間は、他の処理をブロックしていることになります。これは、他のPersistenceシステムでも同じことが起こり、一般的なベストプラクティスを使うことをオススメします。 | |
<a href="#background-operations">バックグランド処理</a> をご覧ください。</p> | |
<p>RealmはMVCCアーキテクチャーであるため、Writeトランザクションが開始されている状態でも、読み込み処理は正しくできます。同時に複数のスレッドから書き込みする場合でない限り、長めのWriteトランザクションを使うことをオススメします。</p> | |
<p>詳しくは、<a href="api/Classes/RLMRealm.html#">RLMRealm</a> と <a href="api/Classes/RLMObject.html#">RLMObject</a> をご覧ください。</p> | |
<h2 id="section-8">クエリ</h2> | |
<p>クエリを実行するとRLMObjectオブジェクトを含んだ、RLMResultsオブジェクトが結果として返ってきます。 | |
RLMResultは、NSArrayと似たようなインターフェイスを持ち、添え字アクセスでオブジェクトにアクセスすることもできます。<br /> | |
NSArrayと違う点は、RLMResultは、RLMObjectのみを含むことができるという点です。<br /> | |
詳しくは、<a href="api/Classes/RLMResults.html#">RLMResults</a> をご覧ください。</p> | |
<p>Realm上での、プロパティアクセスを含む、全てのクエリは遅延評価されてます。プロパティにアクセスした時に、初めてデータが読み込まれます。</p> | |
<p>クエリを実行したときに返ってくる結果は、データのコピーではありません。トランザクションを使ってそのデータを変更した場合、ディスクのデータを変更したことになります。 | |
また、RLMResultに含まれるRLMObjectから、 <a href="#relationships">関連</a> のあるオブジェクトをフェッチすることもできます。</p> | |
<h3 id="section-9">オブジェクトの取得</h3> | |
<p>最も、基本的なオブジェクトのフェッチ方法は、<a href="api/Classes/RLMObject.html#//api/name/allObjects"><code>[RLMObject allObjects]</code></a> です。 | |
これは、指定したクラスのインスタンスをdefaultRealm内から全てフェッチしてきます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Query the default Realm</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">dogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="n">allObjects</span><span class="p">];</span> <span class="c1">// retrieves all Dogs from the default Realm</span> | |
<span class="c1">// Query a specific Realm</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">petsRealm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">realmWithPath</span><span class="p">:</span><span class="s">@"pets.realm"</span><span class="p">];</span> <span class="c1">// get a specific Realm</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">otherDogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="nl">allObjectsInRealm</span><span class="p">:</span><span class="n">petsRealm</span><span class="p">];</span> <span class="c1">// retrieve all Dogs from that Realm</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Query the default Realm</span> | |
<span class="k">let</span> <span class="n">dogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">allObjects</span><span class="p">()</span> | |
<span class="c1">// Query a specific Realm</span> | |
<span class="k">let</span> <span class="n">petsRealm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">realmWithPath</span><span class="p">(</span><span class="s">"pets.realm"</span><span class="p">)</span> | |
<span class="k">let</span> <span class="n">otherDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">allObjectsInRealm</span><span class="p">(</span><span class="n">petsRealm</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h3 id="predicate">Predicateを使ったフェッチ</h3> | |
<p>普段から<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html">NSPredicate</a>の扱いに慣れているなら、Realmでのオブジェクトの取得はすでに知っているも当然です。 | |
RLMObject, RLMRealm, RLMArray, RLMResultは全て、NSPredicateインスタンスまたは、Predicateの構文を使ってのオブジェクトのフェッチをサポートしています。</p> | |
<p>例えば、以下のように <code>[RLMObject objectsWhere:]</code> は、Dogクラスの <code>color = tan</code> で、nameの値が <code>B</code> からはじまるDogクラスのインスタンスをdefaultRealm内から全てフェッチしてきます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Query using a predicate string</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">tanDogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"color = 'tan' AND name BEGINSWITH 'B'"</span><span class="p">];</span> | |
<span class="c1">// Query using an NSPredicate object</span> | |
<span class="bp">NSPredicate</span> <span class="o">*</span><span class="n">pred</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSPredicate</span> <span class="nl">predicateWithFormat</span><span class="p">:</span><span class="s">@"color = %@ AND name BEGINSWITH %@"</span><span class="p">,</span> | |
<span class="s">@"tan"</span><span class="p">,</span> <span class="s">@"B"</span><span class="p">];</span> | |
<span class="n">tanDogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="nl">objectsWithPredicate</span><span class="p">:</span><span class="n">pred</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Query using a predicate string</span> | |
<span class="k">var</span> <span class="n">tanDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsWhere</span><span class="p">(</span><span class="s">"color = 'tan' AND name BEGINSWITH 'B'"</span><span class="p">)</span> | |
<span class="c1">// Query using an NSPredicate object</span> | |
<span class="k">let</span> <span class="n">predicate</span> <span class="o">=</span> <span class="bp">NSPredicate</span><span class="p">(</span><span class="nl">format</span><span class="p">:</span> <span class="s">"color = %@ AND name BEGINSWITH %@"</span><span class="p">,</span> <span class="s">"tan"</span><span class="p">,</span> <span class="s">"B"</span><span class="p">)</span> | |
<span class="n">tanDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsWithPredicate</span><span class="p">(</span><span class="n">predicate</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>詳しくは、<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/predicates.html">Apple’s Predicates Programming Guide</a> をご覧ください。Realmでは、たくさんのPredicate構文をサポートしています。</p> | |
<ul> | |
<li>比較が、プロパティ名と定数で使えます。少なくとも一つのオペランドは、プロパティ名でないといけません。</li> | |
<li>比較演算子 <strong>==</strong>, <strong><=</strong>, <strong><</strong>, <strong>>=</strong>, <strong>></strong>, <strong>!=</strong>, <strong>BETWEEN</strong> が、int, long, long long, float, double, NSDate で使えます。<br /> | |
Ex.) <code>age == 45</code></li> | |
<li>オブジェクトの同一性 <strong>==</strong>, <strong>!=</strong><br /> | |
Ex.) <code>[Employee objectsWhere:@"company == %@", company]</code></li> | |
<li>bool型では、<strong>==</strong>, <strong>!=</strong> が使えます。</li> | |
<li>NSString型、NSData型では、<strong>==</strong>, <strong>!=</strong>, <strong>BEGINSWITH</strong>, <strong>CONTAINS</strong>, <strong>ENDSWITH</strong> が使えます。<br /> | |
Ex.) <code>name CONTAINS 'Ja'</code></li> | |
<li>文字列の比較<br /> | |
Ex.) <code>name CONTAINS[c] 'Ja'</code></li> | |
<li>論理演算: <strong>“AND”</strong>, <strong>“OR”</strong>, <strong>“NOT”</strong> が使えます。<br /> | |
Ex.) <code>name BEGINSWITH 'J' AND age >= 32</code></li> | |
<li>いずれかの条件と一致するかどうかの <strong>IN</strong><br /> | |
Ex.) <code>name IN {'Lisa', 'Spike', 'Hachi'}</code></li> | |
<li><strong>nil</strong> との比較<br /> | |
Ex.) <code>[Company objectsWhere:@"ceo == nil"]</code></li> | |
<li>いずれかの要素が条件と一致するかどうかの <strong>ANY</strong><br /> | |
Ex.) <code>ANY student.age < 21</code></li> | |
<li>範囲が指定できる <strong>BETWEEN</strong><br /> | |
Ex. <code>RLMResults *results = [Person objectsWhere:@"age BETWEEN %@", @[42, 43]];</code></li> | |
</ul> | |
<p>詳しくは、<a href="api/Classes/RLMObject.html#//api/name/objectsWhere:"><code>[RLMObject objectsWhere:]</code></a> をご覧ください。</p> | |
<h3 id="section-10">ソート</h3> | |
<p>RLMResultは、プロパティの値でソートすることができます。 | |
たとえば、以下の例では、<code>[RLMResults sortedResultsUsingProperty:ascending:]</code> によって、特定のDogオブジェクトをnameの値をアルファベット順でソートしてから取り出しています。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Sort tan dogs with names starting with "B" by name</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">sortedDogs</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Dog</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"color = 'tan' AND name BEGINSWITH 'B'"</span><span class="p">]</span> | |
<span class="nl">sortedResultsUsingProperty</span><span class="p">:</span><span class="s">@"name"</span> <span class="nl">ascending</span><span class="p">:</span><span class="nb">YES</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Sort tan dogs with names starting with "B" by name</span> | |
<span class="k">var</span> <span class="n">sortedDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsWhere</span><span class="p">(</span><span class="s">"color = 'tan' AND name BEGINSWITH 'B'"</span><span class="p">).</span><span class="n">arraySortedByProperty</span><span class="p">(</span><span class="s">"name"</span><span class="p">,</span> <span class="nl">ascending</span><span class="p">:</span> <span class="nb">true</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>詳しくは、<a href="api/Classes/RLMObject.html#//api/name/objectsWhere:"><code>[RLMObject objectsWhere:]</code></a> <a href="api/Classes/RLMResults.html#//api/name/sortedResultsUsingProperty:ascending:"><code>[RLMResults sortedResultsUsingProperty:ascending:]</code></a> をご覧ください。</p> | |
<h3 id="section-11">連続したクエリの実行</h3> | |
<p>他のデータベースと比較した時に、Realmを使う利点として、小さなオーバーヘッドで、連続してクエリが実行できる点が挙げられます。 | |
たとえば、<code>color = tan</code> で、 <code>name</code> が <code>B</code> からはじまる Dogオブジェクトをフェッチしたい場合、以下のように連鎖的にメソッドを呼び出すことができます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="n">RLMResults</span> <span class="o">*</span><span class="n">tanDogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"color = 'tan'"</span><span class="p">];</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">tanDogsWithBNames</span> <span class="o">=</span> <span class="p">[</span><span class="n">tanDogs</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"name BEGINSWITH 'B'"</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="n">tanDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsWhere</span><span class="p">(</span><span class="s">"color = 'tan'"</span><span class="p">)</span> | |
<span class="k">let</span> <span class="n">tanDogsWithBNames</span> <span class="o">=</span> <span class="n">tanDogs</span><span class="p">.</span><span class="n">objectsWhere</span><span class="p">(</span><span class="s">"name BEGINSWITH 'B'"</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h2 id="realms">Realms</h2> | |
<h3 id="realm-1">デフォルトRealm</h3> | |
<p>すでにお気付きだと思いますが、これまで <a href="api/Classes/RLMRealm.html#//api/name/defaultRealm"><code>[RLMRealm defaultRealm]</code></a> を呼ぶことで、変数 <code>realm</code> を初期化してきました。 | |
このメソッドは、アプリのDocumentsフォルダにある、“default.realm” ファイルのRLMRealmオブジェクトを返します。</p> | |
<p><a href="api/Classes/RLMRealm.html#//api/name/setDefaultRealmPath:"><code>+[RLMRealm setDefaultRealmPath:]</code></a> を使うことで、デフォルトRealmへのパスを変更できます。この機能は、特にテスト時やiOS8で利用可能の <a href="https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW6">Shared Container</a> で役立ちます。</p> | |
<p>RealmのAPIにあるたくさんのメソッドで、Realmインスンタスを引数としてとるものと、自動でデフォルトRealmが使われる両方があります。例えば、<a href="api/Classes/RLMObject.html#//api/name/allObjects"><code>[RLMObject allObjects]</code></a> は、<a href="api/Classes/RLMObject.html#//api/name/allObjectsInRealm:"><code>[RLMObject allObjectsInRealm:[RLMRealm defaultRealm]]</code></a> と同じ意味になります。</p> | |
<h3 id="realm-2">その他のRealm</h3> | |
<p>場合によっては、複数のRealmが必要な時があります。<br /> | |
詳しくは、 <a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:"><code>[RLMRealm realmWithPath:]</code></a>, <a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:readOnly:error:"><code>[RLMRealm realmWithPath:readOnly:error:]</code></a> をご覧ください。</p> | |
<p><a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:"><code>[RLMRealm realmWithPath:]</code></a> で引数として渡すパスは、書き込み可能である必要があります。 | |
Realmファイルの基本的な保存場所は、iOSでは、”Documents” フォルダ、OSXでは、”Application Support” フォルダです。 | |
Appleの iOS Data Storage Guidelines に沿って設計してください。</p> | |
<h3 id="in-memory-realms">In-Memory Realms</h3> | |
<p>基本的には、Realmは、ディスクにデータを保存しますが、<a href="api/Classes/RLMRealm.html#//api/name/inMemoryRealmWithIdentifier:"><code>[RLMRealm inMemoryRealmWithIdentifier:]</code></a> を呼ぶことで、データをメモリーに保存するIn-MemoryなRealmオブジェクトを作ることができます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="n">RLMRealm</span> <span class="o">*</span><span class="n">realm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">inMemoryRealmWithIdentifier</span><span class="p">:</span><span class="s">@"MyInMemoryRealm"</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">inMemoryRealmWithIdentifier</span><span class="p">(</span><span class="s">"MyInMemoryRealm"</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>In-memoryなRealmでは、データをディスクに保存しません。それによりアプリの再起動時には以前に保存したデータを使用することができませんが、Query, Relationship, thread-safety は使用することができます。<br /> | |
これは、ディスクへの読み書きに伴うオーバーヘッドがない分、柔軟なデータアクセス機能が必要なとき有効な機能です。</p> | |
<div class="alert alert-danger"> | |
<p><strong>注意:</strong> | |
スコープを外れ、In-MemoryなRealmインスタンスへの参照がなくなると、そのRealm内に保存されている、全てのデータは解放されます。アプリの起動中は、In-MemoryなRealmインスタンスへの強参照を常に保持しておく必要があります。</p> | |
</div> | |
<!-- This is to enable previous redirects to the section below--> | |
<p><span id="background-operations"></span></p> | |
<h3 id="section-12">スレッド間での実行</h3> | |
<p>複数のスレッドで、同じRealmを使う場合は、各スレッドで<a href="api/Classes/RLMRealm.html#//api/name/defaultRealm"><code>[RLMRealm defaultRealm]</code></a>, <a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:"><code>[RLMRealm realmWithPath:]</code></a> または <a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:readOnly:error:"><code>[RLMRealm realmWithPath:readOnly:error:]</code></a> でインスタンスをそれぞれ生成する必要があります。 | |
Realmファイルへのパスさえ同じであれば、RLMRealmオブジェクトはディスク上で同じものを指します。</p> | |
<p><strong>複数のスレッド間での、RLMRealmインスタンスの共有はサポートされていません。 | |
同じRealmファイルを指すRLMRealmのインスタンスのrealdOnly属性は、統一しないといけません。(全てreadwriteにするか全てreadonlyにするかしないといけません)</strong></p> | |
<p>Realmは、膨大なデータを追加するとき、すごく効率よく動作します。 | |
メインスレッドのブロッキングを避けるためGrand Central Dispatchを使い、その中にトランザクションを書きます。 | |
RLMRealmオブジェクトは、スレッドセーフではないため、複数のスレッド間では共有することことができません。それぞれ、これから読み書きしたいthread/dispatch_queue内でRLMRealmオブジェクトを生成する必要があります。<br /> | |
以下は、バックグランド処理で100万個のオブジェクトを追加する例です。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="n">dispatch_async</span><span class="p">(</span><span class="n">queue</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span> | |
<span class="c1">// Get realm and table instances for this thread</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">realm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">];</span> | |
<span class="c1">// Break up the writing blocks into smaller portions</span> | |
<span class="c1">// by starting a new transaction</span> | |
<span class="k">for</span> <span class="p">(</span><span class="bp">NSInteger</span> <span class="n">idx1</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">idx1</span> <span class="o"><</span> <span class="mi">1000</span><span class="p">;</span> <span class="n">idx1</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">beginWriteTransaction</span><span class="p">];</span> | |
<span class="c1">// Add row via dictionary. Property order is ignored.</span> | |
<span class="k">for</span> <span class="p">(</span><span class="bp">NSInteger</span> <span class="n">idx2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">idx2</span> <span class="o"><</span> <span class="mi">1000</span><span class="p">;</span> <span class="n">idx2</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> | |
<span class="p">[</span><span class="n">Person</span> <span class="nl">createInRealm</span><span class="p">:</span><span class="n">realm</span> | |
<span class="nl">withObject</span><span class="p">:</span><span class="l">@{</span><span class="s">@"name"</span> <span class="o">:</span> <span class="p">[</span><span class="nb">self</span> <span class="n">randomString</span><span class="p">],</span> | |
<span class="s">@"birthdate"</span> <span class="o">:</span> <span class="p">[</span><span class="nb">self</span> <span class="n">randomDate</span><span class="p">]</span><span class="l">}</span><span class="p">];</span> | |
<span class="p">}</span> | |
<span class="c1">// Commit the write transaction</span> | |
<span class="c1">// to make this data available to other threads</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">commitWriteTransaction</span><span class="p">];</span> | |
<span class="p">}</span> | |
<span class="p">});</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="n">dispatch_async</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// Get realm and table instances for this thread</span> | |
<span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealm</span><span class="p">()</span> | |
<span class="c1">// Break up the writing blocks into smaller portions</span> | |
<span class="c1">// by starting a new transaction</span> | |
<span class="k">for</span> <span class="n">idx1</span> <span class="k">in</span> <span class="mf">0.</span><span class="p">.</span><span class="o"><</span><span class="mi">1000</span> <span class="p">{</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">beginWriteTransaction</span><span class="p">()</span> | |
<span class="c1">// Add row via dictionary. Property order is ignored.</span> | |
<span class="k">for</span> <span class="n">idx2</span> <span class="k">in</span> <span class="mf">0.</span><span class="p">.</span><span class="o"><</span><span class="mi">1000</span> <span class="p">{</span> | |
<span class="n">Person</span><span class="p">.</span><span class="n">createInDefaultRealmWithObject</span><span class="p">([</span> | |
<span class="s">"name"</span><span class="o">:</span> <span class="s">"\(idx1)"</span><span class="p">,</span> | |
<span class="s">"birthdate"</span><span class="o">:</span> <span class="bp">NSDate</span><span class="p">(</span><span class="nl">timeIntervalSince1970</span><span class="p">:</span> <span class="n">idx2</span><span class="p">)</span> | |
<span class="p">])</span> | |
<span class="p">}</span> | |
<span class="c1">// Commit the write transaction</span> | |
<span class="c1">// to make this data available to other threads</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">commitWriteTransaction</span><span class="p">()</span> | |
<span class="p">}</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h3 id="realm-3">Realm間でのオブジェクトのコピー</h3> | |
<p>Realmのオブジェクトを他のRealmへコピーするには、<a href="api/Classes/RLMObject.html#//api/name/createInRealm:withObject:"><code>+[RLMObject createInRealm:withObject:]</code></a> へ元のオブジェクトを引数として渡すことでできます。 | |
例えば、<br /> | |
<code>[MyRLMObjectSubclass createInRealm:otherRealm withObject:originalObjectInstance]</code> のように使います。 </p> | |
<h3 id="realm-4">初期データとしてのRealm</h3> | |
<p>アプリをインストールした時からすぐに使えるような初期データをアプリに入れておくことは、とても一般的な方法です。以下が、Realmでのやり方です。</p> | |
<ol> | |
<li>はじめに、初期データの入ったRealmを用意します。最終的にリリースする時と同じデータモデルを定義し、データを入れます。Realmファイルは、クロスプラットフォームですので、OSXアプリや、シュミレータで動くiOSアプリでも問題ありません。(<a href="https://github.com/realm/realm-cocoa/tree/master/examples/osx/objc/JSONImport">JSONImport</a>をご覧ください)</li> | |
<li>初期データを入れるコードの終わりに、ファイルの圧縮コピーをするメソッドを使用し、Realmファイルを圧縮してください。(<a href="api/Classes/RLMRealm.html#//api/name/writeCopyToPath:error:"><code>-[RLMRealm writeCopyToPath:error:]</code></a> をご覧ください)このメソッドを使ってRealmファイルをコピーすると、Realmのファイルサイズを軽減でき、ユーザーがアプリをダウンロードするときに軽くなります。</li> | |
<li>新しく圧縮したRealmファイルを、アプリのXcodeのプロジェクトナビゲーターにDrag&Dropします。</li> | |
<li>XcodeのBuild Phaseタブで、”Copy Bundle Resources” に圧縮したRealmファイルを追加します。</li> | |
<li>アプリから、追加したRealmファイルがアクセスできるようになります。 <a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/#//apple_ref/occ/instm/NSBundle/pathForResource:ofType:"><code>[[NSBundle mainBundle] pathForResource:ofType:]</code></a> を使って、パスを見つけることができます。</li> | |
<li>これで、<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/#//apple_ref/occ/instm/NSBundle/pathForResource:ofType:"><code>[RLMRealm realmWithPath:readOnly:error:]</code></a> でreadOnlyなRealmを作ることもできるし、その初期データを含んだRealmに書き込みたい場合は、<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/occ/instm/NSFileManager/copyItemAtPath:toPath:error:"><code>[[NSFileManager defaultManager]</code></a>を使い、アプリの <code>Documents</code> ディレクトリにRealmファイルをコピーしてから、<a href="api/Classes/RLMRealm.html#//api/name/realmWithPath:"><code>[RLMRealm realmWithPath:]</code></a> にパスを渡し、Realmインスタンスを作るようにしてください。</li> | |
</ol> | |
<p>Realmファイルを使っての初期データの組み込みは、<a href="https://github.com/realm/realm-cocoa/tree/master/examples/ios/objc/Migration">migration sample app</a>をご参照ください。</p> | |
<h2 id="section-13">リレーションシップ</h2> | |
<p>RLMObjectは、プロパティに <code>RLMObject</code>, <code>RLMArray\<_Object_\></code>を宣言することで、他のオブジェクトと関連付けを定義することができます。 | |
RLMArrayは、NSArrayと似たようなインターフェイスを持ち、添え字アクセスでオブジェクトにアクセスすることもできます。NSArrayと違う点は、RLMArrayは、RLMObjectのみを含むことができるという点です。 | |
詳しくは、<a href="api/Classes/RLMArray.html#">RLMArray</a> をご覧ください。</p> | |
<p>以前に<a href="#models">Personモデル</a>を作成したと思います。ここでは、Dogモデルを作成し関連付けを行ってみましょう。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Dog.h</span> | |
<span class="k">@interface</span> <span class="nc">Dog</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Dog</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h3 id="to-one">To-One</h3> | |
<p>モデル間で多対一や一対一の関連性を持たせたい場合は、RLMObjectモデルクラスのプロパティを宣言します:</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Dog.h</span> | |
<span class="k">@interface</span> <span class="nc">Dog</span> : <span class="nc">RLMObject</span> | |
<span class="p">...</span> <span class="c1">// other property declarations</span> | |
<span class="k">@property</span> <span class="n">Person</span> <span class="o">*</span><span class="n">owner</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Dog</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="p">...</span> <span class="c1">// other property declarations</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="nl">owner</span><span class="p">:</span> <span class="n">Person</span><span class="o">?</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>以下のようにこのプロパティを使えます:</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="n">Person</span> <span class="o">*</span><span class="n">jim</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Person</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span> | |
<span class="n">Dog</span> <span class="o">*</span><span class="n">rex</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Dog</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span> | |
<span class="n">rex</span><span class="p">.</span><span class="n">owner</span> <span class="o">=</span> <span class="n">jim</span><span class="p">;</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="n">jim</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span> | |
<span class="k">let</span> <span class="n">rex</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">()</span> | |
<span class="n">rex</span><span class="p">.</span><span class="n">owner</span> <span class="o">=</span> <span class="n">jim</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>RLMObjectをプロパティで使うと、ネストされたプロパティにシンプルなシンタックスでアクセスができます。 | |
たとえば、上記の例で <code>rex.owner.address.country</code> とようにすると、自動的に必要なプロパティの値をフェッチされます。</p> | |
<h3 id="to-many">To-Many</h3> | |
<p>プロパティに <code>RLMArray\<_Object_\></code> を宣言することで、対多の関連性を定義できます。RLMArrayは、RLMObjectを含み、NSMutableArrayと似たようなインターフェイスを持ちます。</p> | |
<p>PersonクラスにDogクラスの対多関連を持たせるとします。まず、<code>RLMArray<Dog></code> を定義します。 | |
これは、以下のように関連するモデルの@interfeceの下にマクロを書きます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">//Dog.h</span> | |
<span class="k">@interface</span> <span class="nc">Dog</span> : <span class="nc">RLMObject</span> | |
<span class="p">...</span> <span class="c1">// property declarations</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Dog</span><span class="p">)</span> <span class="c1">// Defines an RLMArray<Dog> type</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Not needed in Swift</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p><code>RLMArray<Dog></code> 型を宣言できるようになりました。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Person.h</span> | |
<span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="p">...</span> <span class="c1">// other property declarations</span> | |
<span class="k">@property</span> <span class="n">RLMArray</span><span class="o"><</span><span class="n">Dog</span><span class="o">></span> <span class="o">*</span><span class="n">dogs</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="p">...</span> <span class="c1">// other property declarations</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">dogs</span> <span class="o">=</span> <span class="n">RLMArray</span><span class="p">(</span><span class="nl">objectClassName</span><span class="p">:</span> <span class="n">Dog</span><span class="p">.</span><span class="n">className</span><span class="p">())</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>これで、RLMArrayプロパティに対してアクセス、オブジェクトを追加したりできるようになりました。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Jim is owner of Rex and all dogs named "Fido"</span> | |
<span class="n">RLMArray</span> <span class="o">*</span><span class="n">someDogs</span> <span class="o">=</span> <span class="p">[</span><span class="n">Dog</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"name contains 'Fido'"</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">jim</span><span class="p">.</span><span class="n">dogs</span> <span class="nl">addObjects</span><span class="p">:</span><span class="n">someDogs</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">jim</span><span class="p">.</span><span class="n">dogs</span> <span class="nl">addObject</span><span class="p">:</span><span class="n">rex</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">let</span> <span class="n">someDogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsWhere</span><span class="p">(</span><span class="s">"name contains 'Fido'"</span><span class="p">)</span> | |
<span class="n">jim</span><span class="p">.</span><span class="n">dogs</span><span class="p">.</span><span class="n">addObjects</span><span class="p">(</span><span class="n">someDogs</span><span class="p">)</span> | |
<span class="n">jim</span><span class="p">.</span><span class="n">dogs</span><span class="p">.</span><span class="n">addObject</span><span class="p">(</span><span class="n">rex</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h3 id="inverse-relationships">Inverse Relationships</h3> | |
<p>逆方向のリレーションシップを張っておくことで、特定のプロパティを用いて、関連するオブジェクトへアクセスすることができます。 | |
<a href="api/Classes/RLMObject.html#//api/name/linkingObjectsOfClass:forProperty:"><code>-linkingObjectsOfClass:forProperty:</code></a> を使い、<code>Dog</code>クラス定義しておくことで、紐づくオブジェクトを取得できるようになります。 | |
以下のようにreadonlyの<code>owners</code>プロパティを<code>Dog</code>クラスに定義することで、逆のリレーションシップを張ることができます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="k">@interface</span> <span class="nc">Dog</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSInteger</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="p">(</span><span class="k">readonly</span><span class="p">)</span> <span class="bp">NSArray</span> <span class="o">*</span><span class="n">owners</span><span class="p">;</span> <span class="c1">// Realm doesn't persist this property because it is readonly</span> | |
<span class="k">@end</span> | |
<span class="k">@implementation</span> <span class="nc">Dog</span> | |
<span class="c1">// Define "owners" as the inverse relationship to Person.dogs</span> | |
<span class="p">-</span> <span class="p">(</span><span class="bp">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="nf">owners</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="p">[</span><span class="nb">self</span> <span class="nl">linkingObjectsOfClass</span><span class="p">:</span><span class="s">@"Person"</span> <span class="nl">forProperty</span><span class="p">:</span><span class="s">@"dogs"</span><span class="p">];</span> | |
<span class="p">}</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Dog</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="k">var</span> <span class="nl">owners</span><span class="p">:</span> <span class="p">[</span><span class="n">Person</span><span class="p">]</span> <span class="p">{</span> | |
<span class="c1">// Realm doesn't persist this property because it only has a getter defined</span> | |
<span class="c1">// Define "owners" as the inverse relationship to Person.dogs</span> | |
<span class="k">return</span> <span class="n">linkingObjectsOfClass</span><span class="p">(</span><span class="s">"Person"</span><span class="p">,</span> <span class="nl">forProperty</span><span class="p">:</span> <span class="s">"dogs"</span><span class="p">)</span> <span class="kt">as</span> <span class="p">[</span><span class="n">Person</span><span class="p">]</span> | |
<span class="p">}</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h2 id="section-14">通知</h2> | |
<p>Realm内のデータの更新がかかる毎に、他のRealmインスタンスに通知を送り、それを受け取ることができます。 | |
通知を受け取る方法は、以下のように事前にブロックとして登録しておく必要があります。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Observe Realm Notifications</span> | |
<span class="nb">self</span><span class="p">.</span><span class="n">token</span> <span class="o">=</span> <span class="p">[</span><span class="n">realm</span> <span class="nl">addNotificationBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="bp">NSString</span> <span class="o">*</span><span class="n">note</span><span class="p">,</span> <span class="n">RLMRealm</span> <span class="o">*</span> <span class="n">realm</span><span class="p">)</span> <span class="p">{</span> | |
<span class="p">[</span><span class="n">myViewController</span> <span class="n">updateUI</span><span class="p">];</span> | |
<span class="p">}];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Observe Realm Notifications</span> | |
<span class="k">let</span> <span class="n">token</span> <span class="o">=</span> <span class="n">realm</span><span class="p">.</span><span class="n">addNotificationBlock</span> <span class="p">{</span> <span class="n">note</span><span class="p">,</span> <span class="n">realm</span> <span class="k">in</span> | |
<span class="n">viewController</span><span class="p">.</span><span class="n">updateUI</span><span class="p">()</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p><code>Notificaiton Token</code> が保持されてる限り、登録されたNotificationは存在し続けます。 | |
更新などをするためにクラス上で <code>Notification Token</code> の強参照を保持しておく必要があります。 | |
<code>Notification Token</code> が、解放された時点で登録されたNotificationは自動的に抹消されます。 </p> | |
<p>詳しくは、<a href="api/Classes/RLMRealm.html#//api/name/addNotificationBlock:"><code>[Realm addNotificationBlock:]</code></a> <a href="api/Classes/RLMRealm.html#//api/name/removeNotificationBlock:"><code>[Realm removeNotificationBlock:]</code></a> をご覧ください。</p> | |
<h2 id="section-15">マイグレーション</h2> | |
<p>データベースを使ってる場合、時間が経つにつれ、データモデルというのは変更されていくものです。 | |
Realmでのデータモデルは、シンプルなObjective-Cインターフェイスで定義されてますので、インターフェイスに変更を加えるだけで、簡単にデータモデルを変えられます。 | |
たとえば、以下の <code>Person.h</code> について考えてみてください。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">firstName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">lastName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">firstName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">lastName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>ここで、<code>firstName</code> と <code>lastName</code> を一つにして、<code>fullName</code> プロパティが必要になったとします。 | |
そこで以下のような単純な変更をインターフェイスに加えることにします。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">fullName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">fullName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>ここでのポイントは、もし以前に前のデータモデルでのデータが保存されている場合、新しく定義し直したデータモデルとディスクに保存されている古いデータモデルとで不都合が生じてしまいます。 | |
このままマイグレーションを実行しないままでは、Exception が生じます。</p> | |
<h3 id="section-16">マイグレーションの実行</h3> | |
<p>マイグレーション処理は、<a href="api/Classes/RLMRealm.html#//api/name/setSchemaVersion:withMigrationBlock:"><code>[RLMRealm setSchemaVersion:withMigrationBlock:]</code></a> を呼ぶ時に引数として渡すブロックの中に定義します。 | |
このとき、スキーマに関連しているバージョン毎にマイグレーション処理の分岐を書く必要があります。 | |
マイグレーションブロックの中には、全ての古いデータモデルから新しいデータモデルへ移行させるためのロジックが書かれていないといけません。 | |
<a href="api/Classes/RLMRealm.html#//api/name/setSchemaVersion:withMigrationBlock:"><code>[RLMRealm setSchemaVersion:withMigrationBlock:]</code></a> が呼ばれた後に、自動的にマイグレーションブロックが実行されます。</p> | |
<p>たとえば、上記の <code>Person</code> クラスのマイグレーションについて考えてみましょう。<br /> | |
最低限必要なマイグレーション処理は、以下のようなものです:</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Inside your [AppDelegate didFinishLaunchingWithOptions:]</span> | |
<span class="c1">// Notice setSchemaVersion is set to 1, this is always set manually. It must be</span> | |
<span class="c1">// higher than the previous version (oldSchemaVersion) or an RLMException is thrown</span> | |
<span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">setSchemaVersion</span><span class="p">:</span><span class="mi">1</span> | |
<span class="nl">forRealmAtPath</span><span class="p">:[</span><span class="n">RLMRealm</span> <span class="n">defaultRealmPath</span><span class="p">]</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">RLMMigration</span> <span class="o">*</span><span class="n">migration</span><span class="p">,</span> <span class="bp">NSUInteger</span> <span class="n">oldSchemaVersion</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// We haven’t migrated anything yet, so oldSchemaVersion == 0</span> | |
<span class="k">if</span> <span class="p">(</span><span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// Nothing to do!</span> | |
<span class="c1">// Realm will automatically detect new properties and removed properties</span> | |
<span class="c1">// And will update the schema on disk automatically</span> | |
<span class="p">}</span> | |
<span class="p">}];</span> | |
<span class="c1">// now that we have called `setSchemaVersion:withMigrationBlock:`, opening an outdated</span> | |
<span class="c1">// Realm will automatically perform the migration and opening the Realm will succeed</span> | |
<span class="p">[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Inside your application(application:didFinishLaunchingWithOptions:)</span> | |
<span class="c1">// Notice setSchemaVersion is set to 1, this is always set manually. It must be</span> | |
<span class="c1">// higher than the previous version (oldSchemaVersion) or an RLMException is thrown</span> | |
<span class="n">RLMRealm</span><span class="p">.</span><span class="n">setSchemaVersion</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nl">forRealmAtPath</span><span class="p">:</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">(),</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span> <span class="p">{</span> <span class="n">migration</span><span class="p">,</span> <span class="n">oldSchemaVersion</span> <span class="k">in</span> | |
<span class="c1">// We haven’t migrated anything yet, so oldSchemaVersion == 0</span> | |
<span class="k">if</span> <span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span> <span class="p">{</span> | |
<span class="c1">// Nothing to do!</span> | |
<span class="c1">// Realm will automatically detect new properties and removed properties</span> | |
<span class="c1">// And will update the schema on disk automatically</span> | |
<span class="p">}</span> | |
<span class="p">})</span> | |
<span class="c1">// now that we have called `setSchemaVersion:withMigrationBlock:`, opening an outdated</span> | |
<span class="c1">// Realm will automatically perform the migration and opening the Realm will succeed</span> | |
<span class="c1">// i.e. RLMRealm.defaultRealm()</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>Realmによって自動的にスキーマが更新されることを示すためにここでは、空のブロックでマイグレーションを実行しています。</p> | |
<p>これは最低限のマイグレーションですが、おそらく何かデータを新しいプロパティ(ここでは、fullName)に入れるために、ここに処理を記述すると思います。 | |
マイグレーションブロックの中では、特定の型の列挙処理を行うために <a href="api/Classes/RLMMigration.html#//api/name/enumerateObjects:block:"><code>[RLMMigration enumerateObjects:block:]</code></a> を呼ぶことができます。 | |
下記では、必要なマイグレーションロジックを適用しています。 | |
変数 <code>oldObject</code> を使って既にあるデータにアクセスし、新しく更新するデータには変数 <code>newObject</code> を使ってアクセスしています。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Inside your [AppDelegate didFinishLaunchingWithOptions:]</span> | |
<span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">setSchemaVersion</span><span class="p">:</span><span class="mi">1</span> | |
<span class="nl">forRealmAtPath</span><span class="p">:[</span><span class="n">RLMRealm</span> <span class="n">defaultRealmPath</span><span class="p">]</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">RLMMigration</span> <span class="o">*</span><span class="n">migration</span><span class="p">,</span> <span class="bp">NSUInteger</span> <span class="n">oldSchemaVersion</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// We haven’t migrated anything yet, so oldSchemaVersion == 0</span> | |
<span class="k">if</span> <span class="p">(</span><span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// The enumerateObjects:block: method iterates</span> | |
<span class="c1">// over every 'Person' object stored in the Realm file</span> | |
<span class="p">[</span><span class="n">migration</span> <span class="nl">enumerateObjects</span><span class="p">:</span><span class="n">Person</span><span class="p">.</span><span class="n">className</span> | |
<span class="nl">block</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">RLMObject</span> <span class="o">*</span><span class="n">oldObject</span><span class="p">,</span> <span class="n">RLMObject</span> <span class="o">*</span><span class="n">newObject</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// combine name fields into a single field</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">@"fullName"</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSString</span> <span class="nl">stringWithFormat</span><span class="p">:</span><span class="s">@"%@ %@"</span><span class="p">,</span> | |
<span class="n">oldObject</span><span class="p">[</span><span class="s">@"firstName"</span><span class="p">],</span> | |
<span class="n">oldObject</span><span class="p">[</span><span class="s">@"lastName"</span><span class="p">]];</span> | |
<span class="p">}];</span> | |
<span class="p">}</span> | |
<span class="p">}];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Inside your application(application:didFinishLaunchingWithOptions:)</span> | |
<span class="n">RLMRealm</span><span class="p">.</span><span class="n">setSchemaVersion</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nl">forRealmAtPath</span><span class="p">:</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">(),</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span> <span class="p">{</span> <span class="n">migration</span><span class="p">,</span> <span class="n">oldSchemaVersion</span> <span class="k">in</span> | |
<span class="k">if</span> <span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span> <span class="p">{</span> | |
<span class="c1">// The enumerateObjects:block: method iterates</span> | |
<span class="c1">// over every 'Person' object stored in the Realm file</span> | |
<span class="n">migration</span><span class="p">.</span><span class="n">enumerateObjects</span><span class="p">(</span><span class="n">Person</span><span class="p">.</span><span class="n">className</span><span class="p">())</span> <span class="p">{</span> <span class="n">oldObject</span><span class="p">,</span> <span class="n">newObject</span> <span class="k">in</span> | |
<span class="c1">// combine name fields into a single field</span> | |
<span class="k">let</span> <span class="n">firstName</span> <span class="o">=</span> <span class="n">oldObject</span><span class="p">[</span><span class="s">"firstName"</span><span class="p">]</span> <span class="kt">as</span> <span class="n">String</span> | |
<span class="k">let</span> <span class="n">lastName</span> <span class="o">=</span> <span class="n">oldObject</span><span class="p">[</span><span class="s">"lastName"</span><span class="p">]</span> <span class="kt">as</span> <span class="n">String</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">"fullName"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"\(firstName) \(lastName)"</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="p">})</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>一度、マイグレーション処理が適応されると、その後はいつもと同じようにRealm上の全てのオブジェクトに対してアクセスできます。</p> | |
<h3 id="section-17">バージョンの追加方法</h3> | |
<p><code>Person</code> クラスが、以前に異なる2つのデータモデルをとっていた場合を考えてみましょう:</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// v0</span> | |
<span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">firstName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">lastName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="c1">// v1</span> | |
<span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">fullName</span><span class="p">;</span> <span class="c1">// new property</span> | |
<span class="k">@property</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="c1">// v2</span> | |
<span class="k">@interface</span> <span class="nc">Person</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">fullName</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">email</span><span class="p">;</span> <span class="c1">// new property</span> | |
<span class="k">@property</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span> | |
<span class="k">@end</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// v0</span> | |
<span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">firstName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">firstName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="p">}</span> | |
<span class="c1">// v1</span> | |
<span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">fullName</span> <span class="o">=</span> <span class="s">""</span> <span class="c1">// new property</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="p">}</span> | |
<span class="c1">// v2</span> | |
<span class="k">class</span> <span class="nl">Person</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">fullName</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">email</span> <span class="o">=</span> <span class="s">""</span> <span class="c1">// new property</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">age</span> <span class="o">=</span> <span class="mi">0</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>ここでのマイグレーションブロックの中に書くロジックは、以下のようになります。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">setSchemaVersion</span><span class="p">:</span><span class="mi">2</span> <span class="nl">forRealmAtPath</span><span class="p">:[</span><span class="n">RLMRealm</span> <span class="n">defaultRealmPath</span><span class="p">]</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">RLMMigration</span> <span class="o">*</span><span class="n">migration</span><span class="p">,</span> | |
<span class="bp">NSUInteger</span> <span class="n">oldSchemaVersion</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// The enumerateObjects:block: method iterates</span> | |
<span class="c1">// over every 'Person' object stored in the Realm file</span> | |
<span class="p">[</span><span class="n">migration</span> <span class="nl">enumerateObjects</span><span class="p">:</span><span class="n">Person</span><span class="p">.</span><span class="n">className</span> | |
<span class="nl">block</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="n">RLMObject</span> <span class="o">*</span><span class="n">oldObject</span><span class="p">,</span> <span class="n">RLMObject</span> <span class="o">*</span><span class="n">newObject</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// Add the 'fullName' property only to Realms with a schema version of 0</span> | |
<span class="k">if</span> <span class="p">(</span><span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">@"fullName"</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSString</span> <span class="nl">stringWithFormat</span><span class="p">:</span><span class="s">@"%@ %@"</span><span class="p">,</span> | |
<span class="n">oldObject</span><span class="p">[</span><span class="s">@"firstName"</span><span class="p">],</span> | |
<span class="n">oldObject</span><span class="p">[</span><span class="s">@"lastName"</span><span class="p">]];</span> | |
<span class="p">}</span> | |
<span class="c1">// Add the 'email' property to Realms with a schema version of 0 or 1</span> | |
<span class="k">if</span> <span class="p">(</span><span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">@"email"</span><span class="p">]</span> <span class="o">=</span> <span class="s">@""</span><span class="p">;</span> | |
<span class="p">}</span> | |
<span class="p">}];</span> | |
<span class="p">}];</span> | |
<span class="c1">// now that we have called `setSchemaVersion:withMigrationBlock:`, opening an outdated</span> | |
<span class="c1">// Realm will automatically perform the migration and opening the Realm will succeed</span> | |
<span class="p">[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="n">RLMRealm</span><span class="p">.</span><span class="n">setSchemaVersion</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nl">forRealmAtPath</span><span class="p">:</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">(),</span> | |
<span class="nl">withMigrationBlock</span><span class="p">:</span> <span class="p">{</span> <span class="n">migration</span><span class="p">,</span> <span class="n">oldSchemaVersion</span> <span class="k">in</span> | |
<span class="c1">// The enumerateObjects:block: method iterates</span> | |
<span class="c1">// over every 'Person' object stored in the Realm file</span> | |
<span class="n">migration</span><span class="p">.</span><span class="n">enumerateObjects</span><span class="p">(</span><span class="n">Person</span><span class="p">.</span><span class="n">className</span><span class="p">())</span> <span class="p">{</span> <span class="n">oldObject</span><span class="p">,</span> <span class="n">newObject</span> <span class="k">in</span> | |
<span class="c1">// Add the 'fullName' property only to Realms with a schema version of 0</span> | |
<span class="k">if</span> <span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">1</span> <span class="p">{</span> | |
<span class="k">let</span> <span class="n">firstName</span> <span class="o">=</span> <span class="n">oldObject</span><span class="p">[</span><span class="s">"firstName"</span><span class="p">]</span> <span class="kt">as</span> <span class="n">String</span> | |
<span class="k">let</span> <span class="n">lastName</span> <span class="o">=</span> <span class="n">oldObject</span><span class="p">[</span><span class="s">"lastName"</span><span class="p">]</span> <span class="kt">as</span> <span class="n">String</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">"fullName"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"\(firstName) \(lastName)"</span> | |
<span class="p">}</span> | |
<span class="c1">// Add the 'email' property to Realms with a schema version of 0 or 1</span> | |
<span class="k">if</span> <span class="n">oldSchemaVersion</span> <span class="o"><</span> <span class="mi">2</span> <span class="p">{</span> | |
<span class="n">newObject</span><span class="p">[</span><span class="s">"email"</span><span class="p">]</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="p">})</span> | |
<span class="c1">// Realm will automatically perform the migration and opening the Realm will succeed</span> | |
<span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealm</span><span class="p">()</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>詳しくは、<a href="https://github.com/realm/realm-cocoa/tree/master/examples/objc/RealmMigrationExample">migration sample app</a> をご覧ください。</p> | |
<h3 id="linear-migrations">Linear Migrations</h3> | |
<p>二人のユーザーがいると考えてください。 JPとTimです。<br /> | |
JPは、よくアプリのアップデートをします。しかし、Timは、いくつかのバージョンをスキップすることがあります。 | |
JPにとっては、全てのバージョンをインストールしてることになるので、段階を踏んで全てのスキーマのアップデートを適用していることになります。 | |
V0からV1, V1からV2のように彼のアプリはアップデートしていきます。 | |
それとは対照的に、Timの場合は、V0からV2といきなりバージョンをすっ飛ばす恐れがあります。 | |
マイグレーションブロックの中では、たとえどのバージョンのスキーマから始めたとしても、ネストしていない <code>if (oldSchemaVersion < X)</code> で必ず必要なアップデート処理は行われなければなりません。 </p> | |
<p>また、他のケースで、ユーザーがバージョンのスキップをしてアプリのアップデートをしたとします。もしあなたが、”email” プロパティをバージョン2で一度、削除しバージョン3で再び定義したとします。 | |
そして、ユーザーはバージョン1からバージョン3へと、バージョン2をスキップしてアップデートした場合、Realmは、コードのスキーマとディスクのスキーマに実質、違いはないので、”email” プロパティが一度、消されたことを自動的に判別することはできません。これは、TimのPersonクラスで起こりうることで、V1でのプロパティの値をV3のプロパティの値として保持される可能性があります。 | |
V1とV3の間で、ストレージのスキーマが変わっていないため、このことは問題にならないかもしれません。 | |
しかし、これを避けるため、<code>if (oldSchemaVersion < 3)</code> の中で、データセットがV3のものであることを保証するために、一度nilを代入することをオススメします。</p> | |
<h2 id="section-18">暗号化</h2> | |
<div class="alert alert-info"> | |
<p>注意: 必ず、LICENSE.txtのExport Complianceセクションをお読みください。場合によっては、アメリカのEAR (Export Administration Regulations)で規制されることがあり、Realmの暗号化の機能が制限される場合があります。</p> | |
</div> | |
<p>iOSでは、標準の <a href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/doc/constant_group/File_Protection_Values"><code>NSFileProtection</code></a> APIを使用することで、少しのオーバーヘッドでRealmファイルを保護することができます。ただし、この方法でファイルを保護する場合、2つの注意点があります。 | |
1) NSFileProtectionでRealmファイルを保護すると、他のプラットフォームに移動させることができなくなります。(NSFileProtectionは、iOSでのみ有効な機能です) | |
2) パスワードロックがかかるだけで、Realmファイルは暗号化されません。 | |
これらの制限を避けるために(もしくは、OS Xアプリでお使いの場合)、Realmが実装している暗号化方法を使用することをオススメいたします。</p> | |
<p>Realmでは、64bit暗号化キーを用いて、AES-256とSHA-2暗号化方式でデータベースファイルを暗号化する機能があります。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Generate a random encryption key</span> | |
<span class="bp">NSMutableData</span> <span class="o">*</span><span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSMutableData</span> <span class="nl">dataWithLength</span><span class="p">:</span><span class="mi">64</span><span class="p">];</span> | |
<span class="n">SecRandomCopyBytes</span><span class="p">(</span><span class="n">kSecRandomDefault</span><span class="p">,</span> <span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">,</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">key</span><span class="p">.</span><span class="n">mutableBytes</span><span class="p">);</span> | |
<span class="c1">// Open the encrypted Realm file</span> | |
<span class="bp">NSError</span> <span class="o">*</span><span class="n">error</span><span class="p">;</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">realm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">realmWithPath</span><span class="p">:</span><span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span> | |
<span class="nl">key</span><span class="p">:</span><span class="n">key</span> | |
<span class="nl">readOnly</span><span class="p">:</span><span class="nb">NO</span> | |
<span class="nl">error</span><span class="p">:</span><span class="o">&</span><span class="n">error</span><span class="p">];</span> | |
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">realm</span><span class="p">)</span> <span class="p">{</span> | |
<span class="c1">// If the encryption key is wrong, `error` will say that it's an invalid database</span> | |
<span class="n">NSLog</span><span class="p">(</span><span class="s">@"Error opening realm: %@"</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span> | |
<span class="k">return</span><span class="p">;</span> | |
<span class="p">}</span> | |
<span class="c1">// Use the Realm as normal</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">dogs</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Dog</span> <span class="nl">objectsInRealm</span><span class="p">:</span><span class="n">realm</span> <span class="nl">where</span><span class="p">:</span><span class="s">@"name contains 'Fido'"</span><span class="p">]];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Generate a random encryption key</span> | |
<span class="k">let</span> <span class="n">key</span> <span class="o">=</span> <span class="bp">NSMutableData</span><span class="p">(</span><span class="nl">length</span><span class="p">:</span> <span class="mi">64</span><span class="p">)</span><span class="o">!</span> | |
<span class="n">SecRandomCopyBytes</span><span class="p">(</span><span class="n">kSecRandomDefault</span><span class="p">,</span> <span class="n">UInt</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">),</span> | |
<span class="n">UnsafeMutablePointer</span><span class="o"><</span><span class="kt">UInt8</span><span class="o">></span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">mutableBytes</span><span class="p">))</span> | |
<span class="c1">// Open the encrypted Realm file</span> | |
<span class="k">var</span> <span class="nl">error</span><span class="p">:</span> <span class="bp">NSError</span><span class="o">?</span> | |
<span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">realmWithPath</span><span class="p">(</span><span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">(),</span> | |
<span class="nl">key</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="nl">readOnly</span><span class="p">:</span> <span class="nb">false</span><span class="p">,</span> <span class="nl">error</span><span class="p">:</span> <span class="o">&</span><span class="n">error</span><span class="p">)</span> | |
<span class="k">if</span> <span class="n">realm</span> <span class="o">==</span> <span class="nb">nil</span> <span class="p">{</span> | |
<span class="c1">// If the encryption key is wrong, `error` will say that it's an invalid database</span> | |
<span class="n">println</span><span class="p">(</span><span class="s">"Error opening realm: \(error)"</span><span class="p">)</span> | |
<span class="k">return</span> | |
<span class="p">}</span> | |
<span class="c1">// Use the Realm as normal</span> | |
<span class="k">let</span> <span class="n">dogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectsInRealm</span><span class="p">(</span><span class="n">realm</span><span class="p">,</span> <span class="s">"name contains 'Fido'"</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>この機能を使用すると、ディスクに保存されるデータがAES-256で暗号化され、必要に応じ、複合化されます。 | |
また、その後、RLMRealmインスタンス作成時には、同じ暗号化キーが必要になります。インスンタス作成後は、メモリ上に暗号化キーを保持され、指定したパス先にあるRealmファイルへアクセスは、自動的に暗号化キーが使用されるようになります。 | |
たとえば、convenienceメソッドを使って、defaultRealmを指定するコードは以下のようになります。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Generate a random encryption key</span> | |
<span class="bp">NSMutableData</span> <span class="o">*</span><span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSMutableData</span> <span class="nl">dataWithLength</span><span class="p">:</span><span class="mi">64</span><span class="p">];</span> | |
<span class="n">SecRandomCopyBytes</span><span class="p">(</span><span class="n">kSecRandomDefault</span><span class="p">,</span> <span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">,</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">key</span><span class="p">.</span><span class="n">mutableBytes</span><span class="p">);</span> | |
<span class="c1">// Set the encryption key for the default Realm</span> | |
<span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">setEncryptionKey</span><span class="p">:</span><span class="n">key</span> <span class="nl">forRealmsAtPath</span><span class="p">:</span><span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">];</span> | |
<span class="c1">// Use the Realm as normal</span> | |
<span class="n">RLMResults</span> <span class="o">*</span><span class="n">dogs</span> <span class="o">=</span> <span class="p">[[</span><span class="n">Dog</span> <span class="nl">objectsWhere</span><span class="p">:</span><span class="s">@"name contains 'Fido'"</span><span class="p">]];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Generate a random encryption key</span> | |
<span class="k">let</span> <span class="n">key</span> <span class="o">=</span> <span class="bp">NSMutableData</span><span class="p">(</span><span class="nl">length</span><span class="p">:</span> <span class="mi">64</span><span class="p">)</span><span class="o">!</span> | |
<span class="n">SecRandomCopyBytes</span><span class="p">(</span><span class="n">kSecRandomDefault</span><span class="p">,</span> <span class="n">UInt</span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">),</span> | |
<span class="n">UnsafeMutablePointer</span><span class="o"><</span><span class="kt">UInt8</span><span class="o">></span><span class="p">(</span><span class="n">key</span><span class="p">.</span><span class="n">mutableBytes</span><span class="p">))</span> | |
<span class="c1">// Set the encryption key for the default Realm</span> | |
<span class="n">RLMRealm</span><span class="p">.</span><span class="n">setEncryptionKey</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nl">forRealmsAtPath</span><span class="p">:</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealmPath</span><span class="p">())</span> | |
<span class="c1">// Use the Realm as normal</span> | |
<span class="k">let</span> <span class="n">dogs</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">.</span><span class="n">objectswhere</span><span class="p">(</span><span class="s">"name contains 'Fido'"</span><span class="p">)</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>詳しくは、<a href="https://github.com/realm/realm-cocoa/tree/master/examples/ios/objc/Encryption">Objective-C</a>と<a href="https://github.com/realm/realm-cocoa/tree/master/examples/ios/swift/Encryption">Swift</a>の暗号化のサンプルコードをご覧ください。暗号化キーの作り方、キーチェーンへの安全な保存方法、Realmへのキーの渡し方などが分かるかと思います。 | |
注意することは、暗号化機能を使うと、デバッガがきちんと機能しません。暗号化は、開発中は使用せず、リリースビルドでのみ有効にすることをオススメいたします。</p> | |
<p>暗号化したRealmを使う場合、通常よりも20%未満パフォーマンスが下がります。</p> | |
<h2 id="section-19">デバッグ</h2> | |
<p>RealmのLLDB拡張と<a href="#realm-browser">Realm Browser</a>を使うと、Realmのデバッグをより簡単にしてくれます。</p> | |
<p>最新のRealmの <code>plugin/</code> に同梱されている、LLDB拡張 <code>rlm_lldb.py</code> は、デバッグ時にRLMObject, RLMResults, RLMArrayオブジェクトを調べるのに非常に役に立ちます。LLDBの拡張を入れなければ、フェッチ結果のプロパティが nil や 0 と表示されます。</p> | |
<p><img src="http://realm.io/assets/news/2014-11-25-lldb.png" alt="Screenshot of Xcode" /></p> | |
<p><strong>注意:</strong> LLDBスクリプトは、Objective-Cでのみ対応済みです。Swiftのサポートは開発中です。</p> | |
<h2 id="section-20">テスト</h2> | |
<h3 id="realm-5">Realmを使ったアプリのテスト</h3> | |
<p>最も、簡単な方法は、<a href="#the-default-realm">defaultRealm</a> を使用することです。テストコードを実行する前に、 <a href="api/Classes/RLMRealm.html#//api/name/setDefaultRealmPath:"><code>+[RLMRealm setDefaultRealmPath:]</code></a> でテスト用のdefaultRealmのパスを設定することで、アプリで使用されているデータを上書きされるのを避けられます。</p> | |
<p>また、テストする部分としては、引数として、RLMRealmのインスタンスが渡されるメソッドなどです。実際にアプリ実行時とテスト実行時で、異なるRealmインスタンスを投げても問題ないかテストします。 | |
例えば、以下のテストコードは、JSON APIからGETを使ってユーザー情報を取得し、正常にデータが作成されているかをテストしています。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Application Code</span> | |
<span class="p">+</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">updateUserFromServer</span> | |
<span class="p">{</span> | |
<span class="bp">NSURL</span> <span class="o">*</span><span class="n">url</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSURL</span> <span class="nl">URLWithString</span><span class="p">:</span><span class="s">@"http://myapi.example.com/user"</span><span class="p">];</span> | |
<span class="p">[[[</span><span class="bp">NSURLSession</span> <span class="n">sharedSession</span><span class="p">]</span> <span class="nl">dataTaskWithURL</span><span class="p">:</span><span class="n">url</span> | |
<span class="nl">completionHandler</span><span class="p">:</span><span class="o">^</span><span class="p">(</span><span class="bp">NSData</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> | |
<span class="bp">NSURLResponse</span> <span class="o">*</span><span class="n">response</span><span class="p">,</span> | |
<span class="bp">NSError</span> <span class="o">*</span><span class="n">error</span><span class="p">)</span> <span class="p">{</span> | |
<span class="p">[</span><span class="nb">self</span> <span class="nl">createOrUpdateUserInRealm</span><span class="p">:[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">]</span> <span class="nl">withData</span><span class="p">:</span><span class="n">data</span><span class="p">];</span> | |
<span class="p">}]</span> <span class="n">resume</span><span class="p">];</span> | |
<span class="p">}</span> | |
<span class="p">+</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">createOrUpdateUserInRealm:</span><span class="p">(</span><span class="n">RLMRealm</span> <span class="o">*</span><span class="p">)</span><span class="nv">realm</span> <span class="nf">withData:</span><span class="p">(</span><span class="bp">NSData</span> <span class="o">*</span><span class="p">)</span><span class="nv">data</span> | |
<span class="p">{</span> | |
<span class="kt">id</span> <span class="n">object</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSJSONSerialization</span> <span class="nl">JSONObjectWithData</span><span class="p">:</span><span class="n">data</span> <span class="nl">options</span><span class="p">:</span><span class="nb">nil</span> <span class="nl">error</span><span class="p">:</span><span class="nb">nil</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="nl">transactionWithBlock</span><span class="p">:</span><span class="o">^</span><span class="p">{</span> | |
<span class="p">[</span><span class="n">User</span> <span class="nl">createOrUpdateInRealm</span><span class="p">:</span><span class="n">realm</span> <span class="nl">withObject</span><span class="p">:</span><span class="n">object</span><span class="p">];</span> | |
<span class="p">}];</span> | |
<span class="p">}</span> | |
<span class="c1">// Test Code</span> | |
<span class="p">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">testThatUserIsUpdatedFromServer</span> | |
<span class="p">{</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">testRealm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="nl">realmWithPath</span><span class="p">:</span><span class="n">kTestRealmPath</span><span class="p">];</span> | |
<span class="bp">NSData</span> <span class="o">*</span><span class="n">jsonData</span> <span class="o">=</span> <span class="p">[</span><span class="s">@"{</span><span class="se">\"</span><span class="s">email</span><span class="se">\"</span><span class="s">: </span><span class="se">\"</span><span class="s">[email protected]</span><span class="se">\"</span><span class="s">}"</span> | |
<span class="nl">dataUsingEncoding</span><span class="p">:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">ClassBeingTested</span> <span class="nl">createOrUpdateUserInRealm</span><span class="p">:</span><span class="n">testRealm</span> <span class="nl">withData</span><span class="p">:</span><span class="n">jsonData</span><span class="p">];</span> | |
<span class="n">User</span> <span class="o">*</span><span class="n">expectedUser</span> <span class="o">=</span> <span class="p">[</span><span class="n">User</span> <span class="n">new</span><span class="p">];</span> | |
<span class="n">expectedUser</span><span class="p">.</span><span class="n">email</span> <span class="o">=</span> <span class="s">@"[email protected]"</span><span class="p">;</span> | |
<span class="n">XCTAssertEqualObjects</span><span class="p">([</span><span class="n">User</span> <span class="nl">allObjectsInRealm</span><span class="p">:</span><span class="n">testRealm</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> | |
<span class="n">expectedUser</span><span class="p">,</span> | |
<span class="s">@"User was not properly updated from server."</span><span class="p">);</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Application Code</span> | |
<span class="k">class</span> <span class="k">func</span> <span class="nf">updateUserFromServer</span><span class="p">()</span> <span class="p">{</span> | |
<span class="k">let</span> <span class="n">url</span> <span class="o">=</span> <span class="bp">NSURL</span><span class="p">(</span><span class="nl">string</span><span class="p">:</span> <span class="s">"http://myapi.example.com/user"</span><span class="p">)</span> | |
<span class="bp">NSURLSession</span><span class="p">.</span><span class="n">sharedSession</span><span class="p">().</span><span class="n">dataTaskWithURL</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="p">{</span> <span class="n">data</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="k">in</span> | |
<span class="nb">self</span><span class="p">.</span><span class="n">createOrUpdateUserInRealm</span><span class="p">(</span><span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealm</span><span class="p">(),</span> <span class="nl">withData</span><span class="p">:</span> <span class="n">data</span><span class="p">)</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="n">public</span> <span class="k">class</span> <span class="k">func</span> <span class="nf">createOrUpdateUserInRealm</span><span class="p">(</span><span class="nl">realm</span><span class="p">:</span> <span class="n">RLMRealm</span><span class="p">,</span> <span class="n">withData</span> <span class="nl">data</span><span class="p">:</span> <span class="bp">NSData</span><span class="p">)</span> <span class="p">{</span> | |
<span class="k">let</span> <span class="nl">object</span><span class="p">:</span> <span class="p">[</span><span class="nl">String</span><span class="p">:</span> <span class="n">String</span><span class="p">]</span> <span class="o">=</span> | |
<span class="bp">NSJSONSerialization</span><span class="p">.</span><span class="n">JSONObjectWithData</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="nl">options</span><span class="p">:</span> <span class="nb">nil</span><span class="p">,</span> <span class="nl">error</span><span class="p">:</span> <span class="nb">nil</span><span class="p">)</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">transactionWithBlock</span> <span class="p">{</span> | |
<span class="n">User</span><span class="p">.</span><span class="n">createOrUpdateInRealm</span><span class="p">(</span><span class="n">realm</span><span class="p">,</span> <span class="nl">withObject</span><span class="p">:</span> <span class="n">object</span><span class="p">)</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="c1">// Test Code</span> | |
<span class="k">func</span> <span class="nf">testThatUserIsUpdatedFromServer</span><span class="p">()</span> <span class="p">{</span> | |
<span class="k">let</span> <span class="n">testRealm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">realmWithPath</span><span class="p">(</span><span class="n">kTestRealmPath</span><span class="p">)</span> | |
<span class="k">let</span> <span class="nl">jsonString</span><span class="p">:</span> <span class="bp">NSString</span> <span class="o">=</span> <span class="s">"{</span><span class="se">\"</span><span class="s">email</span><span class="se">\"</span><span class="s">: </span><span class="se">\"</span><span class="s">[email protected]</span><span class="se">\"</span><span class="s">}"</span> | |
<span class="k">let</span> <span class="n">jsonData</span> <span class="o">=</span> <span class="n">jsonString</span><span class="p">.</span><span class="n">dataUsingEncoding</span><span class="p">(</span><span class="n">NSUTF8StringEncoding</span><span class="p">)</span> | |
<span class="n">ClassBeingTested</span><span class="p">.</span><span class="n">createOrUpdateUserInRealm</span><span class="p">(</span><span class="n">testRealm</span><span class="p">,</span> <span class="nl">withData</span><span class="p">:</span> <span class="n">jsonData</span><span class="p">)</span> | |
<span class="k">let</span> <span class="n">expectedUser</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span> | |
<span class="n">expectedUser</span><span class="p">.</span><span class="n">email</span> <span class="o">=</span> <span class="s">"[email protected]"</span> | |
<span class="n">XCTAssertEqual</span><span class="p">(</span><span class="n">User</span><span class="p">.</span><span class="n">allObjectsInRealm</span><span class="p">(</span><span class="n">testRealm</span><span class="p">).</span><span class="n">first</span> <span class="kt">as</span> <span class="n">User</span><span class="p">,</span> | |
<span class="n">expectedUser</span><span class="p">,</span> | |
<span class="s">"User was not properly updated from server."</span><span class="p">)</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>テスト実行時に <code>"Object type '...' not persisted in Realm"</code> というエラーが出る場合、Realm.framework がテストTargetにリンクされていないことが原因です。 </p> | |
<p>CocoaPodsをお使いの場合は、以下のようにPodfileをお書きください。</p> | |
<div class="highlight"> | |
<div class="highlight"> | |
<pre><code class="language-ruby" data-lang="ruby"><span class="n">target</span> <span class="s1">'MyApp'</span> | |
<span class="n">pod</span> <span class="s1">'Realm'</span> | |
<span class="k">end</span> | |
<span class="n">target</span> <span class="s1">'MyAppTests'</span><span class="p">,</span> <span class="ss">exclusive</span><span class="p">:</span> <span class="kp">true</span> <span class="k">do</span> | |
<span class="n">pod</span> <span class="s1">'Realm/Headers'</span> | |
<span class="k">end</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight --> | |
<h3 id="realm-6">Realmのテスト</h3> | |
<p>Realm自体は、全てのコミットにおいて広い範囲のテストが行われています。 | |
Realmは<a href="http://github.com/realm/realm-cocoa">オープンソース</a>で、私たちは、あなたのコントリビュートを喜んで歓迎いたします。</p> | |
<h2 id="rest-api">REST API</h2> | |
<p>Realmでは、簡単に REST API と統合ができ、いくつかの利点があります。</p> | |
<ul> | |
<li>REST API のみだと常にネットとの接続が必要ですが、データをキャッシュすることでオフラインでも、アプリを動作させることができます。</li> | |
<li>完全にデータをキャッシュさせておくことで、<code>REST API</code> だけでは、不可能なローカルでクエリを実行したり、データを閲覧したりできます。</li> | |
<li>データを保存させておくことで、サーバーサイド側での処理を新しい変更だけをロードするものだけに減らすことができます。</li> | |
</ul> | |
<h3 id="section-21">ベストプラクティス</h3> | |
<ol> | |
<li><strong>非同期リクエスト</strong> — リクエストを投げる時や、他のブロッキング操作は、UIスレッドを止めてしまう恐れがあるので、バックグラウンド処理で行うことが推奨されています。これと同じ理由で、Realmでの膨大なデータの変更は、バックグラウンド処理で行うべきです。バックグラウンドで行われた変更に対応するには、<a href="#notifications">Notifications</a> 機能を使いましょう。</li> | |
<li><strong>膨大なデータのキャッシュ</strong> - 可能な時に事前にデータをRealmにフェッチし保存させておくことをオススメします。そのようにしておくと、いつでもローカルで保存してあるデータに対してクエリが投げられます。</li> | |
<li><strong>挿入と更新</strong> - Primaryキーのような単一な識別子をデータセットが持っている場合、<a href="api/Classes/RLMObject.html#//api/name/createOrUpdateInRealm:withObject:"><code>[RLMObject createOrUpdateInDefaultRealmWithObject:]</code></a> を使うことで、REST APIからレスポンスを受け取ったときに、より簡単にデータを挿入/更新することができます。このメソッドは、更新が必要かどうかや、既に存在するデータかどうかなどを自動的にチェックしてくれます。</li> | |
</ol> | |
<h3 id="example">Example</h3> | |
<p>以下の例は、シンプルなRealmとREST APIとの連携例です。この例は、Foursquare APIからJSONデータをフェッチしてき、default RealmにRealm Objectとして保存している例です。<br /> | |
これに似たようなユースケース例として参考に、この <a href="http://static.realm.io/videos/demo.mp4">ビデオ</a> をご覧ください。<br /> | |
まず、Default Realmのインスタンスを生成します。そして、APIからデータをフェッチしてきます。 | |
より簡単にするためにここでは、<code>[NSData initWithContentsOfURL]</code> を使っています。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Call the API</span> | |
<span class="bp">NSData</span> <span class="o">*</span><span class="n">response</span> <span class="o">=</span> <span class="p">[[</span><span class="bp">NSData</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithContentsOfURL</span><span class="p">:</span> | |
<span class="p">[</span><span class="bp">NSURL</span> <span class="nl">URLWithString</span><span class="p">:</span><span class="s">@"https://api.foursquare.com/v2/venues/search?near=San%20Francisco&limit=50"</span><span class="p">]];</span> | |
<span class="c1">// Deserialize the response to JSON</span> | |
<span class="bp">NSDictionary</span> <span class="o">*</span><span class="n">json</span> <span class="o">=</span> <span class="p">[[</span><span class="bp">NSJSONSerialization</span> | |
<span class="nl">JSONObjectWithData</span><span class="p">:</span><span class="n">response</span> | |
<span class="nl">options</span><span class="p">:</span><span class="n">kNilOptions</span> | |
<span class="nl">error</span><span class="p">:</span><span class="o">&</span><span class="n">error</span><span class="p">]</span> <span class="nl">objectForKey</span><span class="p">:</span><span class="s">@"response"</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">// Call the API</span> | |
<span class="k">let</span> <span class="n">url</span> <span class="o">=</span> <span class="bp">NSURL</span><span class="p">(</span><span class="nl">string</span><span class="p">:</span> <span class="s">"https://api.foursquare.com/v2/venues/search?near=San%20Francisco&limit=50"</span><span class="p">)</span> | |
<span class="k">let</span> <span class="n">response</span> <span class="o">=</span> <span class="bp">NSData</span><span class="p">(</span><span class="nl">contentsOfURL</span><span class="p">:</span> <span class="n">url</span><span class="p">)</span> | |
<span class="c1">// De-serialize the response to JSON</span> | |
<span class="k">let</span> <span class="n">json</span> <span class="o">=</span> <span class="bp">NSJSONSerialization</span><span class="p">.</span><span class="n">JSONObjectWithData</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> | |
<span class="nl">options</span><span class="p">:</span> <span class="n">NSJSONReadingOptions</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> | |
<span class="nl">error</span><span class="p">:</span> <span class="nb">nil</span><span class="p">)[</span><span class="s">"response"</span><span class="p">]</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>このようなvenues(開催地)のデータのJSON配列がレスポンスとして返ってきます。</p> | |
<div class="highlight"> | |
<pre><code class="language-json" data-lang="json"><span class="p">{</span> | |
<span class="nt">"venues"</span><span class="p">:</span> <span class="p">[</span> | |
<span class="p">{</span> | |
<span class="nt">"id"</span><span class="p">:</span> <span class="s2">"4c82f252d92ea09323185072"</span><span class="p">,</span> | |
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">"Golden Gate Park"</span><span class="p">,</span> | |
<span class="nt">"contact"</span><span class="p">:</span> <span class="p">{</span> | |
<span class="nt">"phone"</span><span class="p">:</span> <span class="s2">"4152522590"</span> | |
<span class="p">},</span> | |
<span class="nt">"location"</span><span class="p">:</span> <span class="p">{</span> | |
<span class="nt">"lat"</span><span class="p">:</span> <span class="mf">37.773835608329</span><span class="p">,</span> | |
<span class="nt">"lng"</span><span class="p">:</span> <span class="mf">-122.41962432861</span><span class="p">,</span> | |
<span class="nt">"postalCode"</span><span class="p">:</span> <span class="s2">"94103"</span><span class="p">,</span> | |
<span class="nt">"cc"</span><span class="p">:</span> <span class="s2">"US"</span><span class="p">,</span> | |
<span class="nt">"state"</span><span class="p">:</span> <span class="s2">"California"</span><span class="p">,</span> | |
<span class="nt">"country"</span><span class="p">:</span> <span class="s2">"United States"</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="p">]</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
<p>JSONをRealmにインポートする方法は、いくつか存在します。カスタムメソッドを作り、手動でRLMObjectのそれぞれのプロパティに配置することもできます。 | |
この例の見どころは、直接NSDicionaryに挿入する代わりに、自動的にRLMObjectを作っているところです。 | |
これをきちんと動作させるためには、RLMObjectのプロパティの構造と、JSONのkeyを完全に一致させておく必要があります。 | |
もし、それらが違っている場合、そのプロパティまたはkeyは無視されます。以下のRLMObjectの定義では、問題なく動作します。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">// Contact.h</span> | |
<span class="k">@interface</span> <span class="nc">Contact</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">phone</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="k">@implementation</span> <span class="nc">Contact</span> | |
<span class="p">+</span> <span class="p">(</span><span class="bp">NSString</span><span class="p">)</span><span class="nf">primaryKey</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">@"phone"</span><span class="p">;</span> | |
<span class="p">}</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Contact</span><span class="p">)</span> | |
<span class="c1">// Location.h</span> | |
<span class="k">@interface</span> <span class="nc">Location</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="kt">double</span> <span class="n">lat</span><span class="p">;</span> <span class="c1">// latitude</span> | |
<span class="k">@property</span> <span class="kt">double</span> <span class="n">lng</span><span class="p">;</span> <span class="c1">// longitude</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">postalCode</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">cc</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">state</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">country</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="k">@implementation</span> <span class="nc">Location</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Location</span><span class="p">)</span> | |
<span class="c1">// Venue.h</span> | |
<span class="k">@interface</span> <span class="nc">Venue</span> : <span class="nc">RLMObject</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="kt">id</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="bp">NSString</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="n">Contact</span> <span class="o">*</span><span class="n">contact</span><span class="p">;</span> | |
<span class="k">@property</span> <span class="n">Location</span> <span class="o">*</span><span class="n">location</span><span class="p">;</span> | |
<span class="k">@end</span> | |
<span class="k">@implementation</span> <span class="nc">Venue</span> | |
<span class="p">+</span> <span class="p">(</span><span class="bp">NSString</span><span class="p">)</span><span class="nf">primaryKey</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">@"id"</span><span class="p">;</span> | |
<span class="p">}</span> | |
<span class="k">@end</span> | |
<span class="n">RLM_ARRAY_TYPE</span><span class="p">(</span><span class="n">Venue</span><span class="p">)</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="k">class</span> <span class="nl">Contact</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">phone</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="k">class</span> <span class="k">func</span> <span class="n">primaryKey</span><span class="p">()</span> <span class="o">-></span> <span class="n">String</span><span class="o">!</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">"phone"</span> | |
<span class="p">}</span> | |
<span class="p">}</span> | |
<span class="k">class</span> <span class="nl">Location</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">lat</span> <span class="o">=</span> <span class="mf">0.0</span> <span class="c1">// latitude</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">lng</span> <span class="o">=</span> <span class="mf">0.0</span> <span class="c1">// longitude</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">postalCode</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">cc</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">state</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">country</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="p">}</span> | |
<span class="k">class</span> <span class="nl">Venue</span><span class="p">:</span> <span class="n">RLMObject</span> <span class="p">{</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="kt">id</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">contact</span> <span class="o">=</span> <span class="n">Contact</span><span class="p">()</span> | |
<span class="n">dynamic</span> <span class="k">var</span> <span class="n">location</span> <span class="o">=</span> <span class="n">Location</span><span class="p">()</span> | |
<span class="k">class</span> <span class="k">func</span> <span class="n">primaryKey</span><span class="p">()</span> <span class="o">-></span> <span class="n">String</span><span class="o">!</span> <span class="p">{</span> | |
<span class="k">return</span> <span class="s">"id"</span> | |
<span class="p">}</span> | |
<span class="p">}</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<p>結果のデータが配列として返ってくるので、<code>[Venue createInDefaultRealmWithObject:]</code>を毎回呼びオブジェクトを作らなければいけません。<br /> | |
この例は、JSONデータから<code>Venue</code>オブジェクトを複数作りdefaultRealmに追加してます。</p> | |
<div class="highlight-wrapper"> | |
<div class="highlight"> | |
<pre><code class="language-objective-c" data-lang="objective-c"><span class="c1">//Extract the array of venues from the response</span> | |
<span class="bp">NSArray</span> <span class="o">*</span><span class="n">venues</span> <span class="o">=</span> <span class="n">json</span><span class="p">[</span><span class="s">@"venues"</span><span class="p">];</span> | |
<span class="n">RLMRealm</span> <span class="o">*</span><span class="n">realm</span> <span class="o">=</span> <span class="p">[</span><span class="n">RLMRealm</span> <span class="n">defaultRealm</span><span class="p">];</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">beginWriteTransaction</span><span class="p">];</span> | |
<span class="c1">// Save one Venue object (and dependents) for each element of the array</span> | |
<span class="k">for</span> <span class="p">(</span><span class="bp">NSDictionary</span> <span class="o">*</span><span class="n">venue</span> <span class="k">in</span> <span class="n">venues</span><span class="p">)</span> <span class="p">{</span> | |
<span class="p">[</span><span class="n">Venue</span> <span class="nl">createOrUpdateInDefaultRealmWithObject</span><span class="p">:</span><span class="n">venue</span><span class="p">];</span> | |
<span class="p">}</span> | |
<span class="p">[</span><span class="n">realm</span> <span class="n">commitWriteTransaction</span><span class="p">];</span></code></pre> | |
</div> | |
<div class="highlight"> | |
<pre><code class="language-swift" data-lang="swift"><span class="c1">//Extract the array of venues from the response</span> | |
<span class="k">let</span> <span class="n">venues</span> <span class="o">=</span> <span class="n">json</span><span class="p">[</span><span class="s">"venues"</span><span class="p">]</span> <span class="kt">as</span> <span class="p">[</span><span class="bp">NSDictionary</span><span class="p">]</span> | |
<span class="k">let</span> <span class="n">realm</span> <span class="o">=</span> <span class="n">RLMRealm</span><span class="p">.</span><span class="n">defaultRealm</span><span class="p">()</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">beginWriteTransaction</span><span class="p">()</span> | |
<span class="c1">// Save one Venue object (and dependents) for each element of the array</span> | |
<span class="k">for</span> <span class="n">venue</span> <span class="k">in</span> <span class="n">venues</span> <span class="p">{</span> | |
<span class="n">Venue</span><span class="p">.</span><span class="n">createOrUpdateInDefaultRealmWithObject</span><span class="p">(</span><span class="n">venue</span><span class="p">)</span> | |
<span class="p">}</span> | |
<span class="n">realm</span><span class="p">.</span><span class="n">commitWriteTransaction</span><span class="p">()</span></code></pre> | |
</div> | |
</div> | |
<!--/highlight-wrapper --> | |
<h2 id="section-22">次のステップ</h2> | |
<p>Realmをより深く理解する、次のステップとして、<a href="https://github.com/realm/realm-cocoa/tree/master/examples">サンプルコード</a>を用意しています。<br /> | |
HAPPY HACKING!!<br /> | |
<a href="https://groups.google.com/d/forum/realm-cocoa">Google グループ Realm</a> で、あなたはいつでもRealmデベロッパーと議論ができます。</p> | |
<h2 id="section-23">開発中の機能</h2> | |
<p>Realmは、現在β版としてリリースされています。バージョン1.0に向けて、機能追加、バグの修正などを行っています。私たちは、次に導入予定のリストを作成しました。<br /> | |
詳しくは、<a href="https://github.com/realm/realm-cocoa/issues">GitHub issues</a> をご覧ください。</p> | |
<h4 id="section-24">一般的な制約</h4> | |
<p>Realmは、柔軟性とパフォーマンスのバランスを上手く保つため、保存するデータに対していくつか制約があります。</p> | |
<ol> | |
<li>クラス名は、UTF-8の0~63バイトである必要があります。これを超過している場合、ロード時に例外が投げられます。</li> | |
<li>プロパティ名は、UTF-8の0~63バイトである必要があります。これを超過している場合、ロード時に例外が投げられます。</li> | |
<li>NSData型のプロパティでは、16MB以上のデータを持つことはできません。 | |
これ以上のデータを保存しようとすると、16MBのチャンクに分割されるか、ファイルにそのまま書き込まれるかのどちらかです。プロパティの値が16MB以上のデータを保存しようとすると、それを実行時に例外が投げられます。</li> | |
<li>NSDate型のプロパティは、保存されると少数点以下が切り捨てられます。 | |
<code>+[NSDate distantFuture]</code> や <code>+[NSDate distantPast]</code> で作られたデータは保持できません。詳しくは、<a href="#nsdate-is-truncated-to-the-second">NSDateについて</a>をご覧ください。</li> | |
<li>Realmファイルのサイズは、一つのiOSアプリに割り当てられるメモリサイズを超えてはいけません。割り当てられるメモリサイズは、デバイス毎に違い、また、どのくらいメモリのフラグメンテーションが進んでるかにも依存します。(ここについては、Open Radarの<a href="http://openradar.appspot.com/17119975">rdar://17119975</a>をご覧ください) これ以上のデータを保存される場合は、Realmファイルを複数に分けご使用ください。</li> | |
</ol> | |
<h4 id="notification">より詳細なNotification</h4> | |
<p>Realmのデータが変更される毎に、<a href="#notifications">Notification</a> を取得することはできますが、現在は、Notificationからアクション(Add, Remove, Move, Updateなど)を識別することができません。<br /> | |
この機能を近々、追加する予定です。</p> | |
<h4 id="nsdate">NSDateについて</h4> | |
<p><code>NSDate</code> は、一度、Realmに保存されると少数点以下は切り捨てられます。 この問題は、現在修正中です。 | |
詳しくは、 <a href="https://github.com/realm/realm-cocoa/issues/875">GitHub issue #875</a> をご覧ください。 | |
それまで、少数点以下の時間を正確に保存したい場合は、 <code>NSTimeInterval(double)型</code> をお使いください。</p> | |
<h4 id="realmobject">RealmObjectのセッター/ゲッターのオーバーライドについて</h4> | |
<p>Realmは、データベースのプロパティと直結させるためにセッター/ゲッターをオーバーライドしています。そのため、Realmモデルクラスで、プロパティのセッター/ゲッターをオーバーライドすることはできません。一時的な解決方法は、<strong>ignore properties</strong> として宣言することです。こうすることで、セッター/ゲッターのオーバーライドができるようになります。</p> | |
<h4 id="kvo">KVOのサポートについて</h4> | |
<p>現在、KVOはサポートされていませんが、独自の <a href="#notifications">Notification</a> の仕組みがあります。</p> | |
<h4 id="realm-7">複数プロセスからのRealmの利用</h4> | |
<p>もちろん、複数のスレッドから同時にRealmファイルへアクセスすることはできますが、シングルプロセスからのみ利用可能です。 | |
これは、主に、iOS8のExtentionsとOSXアプリケーションでの開発に影響します。複数のプロセスで同じRealmファイルを使う場合は、Realmファイルをコピーするか、もしくは、新しいRealmファイルを作成してください。<br /> | |
マルチプロセスサポートは、近々、追加するする予定です。</p> | |
<h4 id="section-25">ファイルサイズと中間バージョンについて</h4> | |
<p>誰もが、SQLiteを使ってデータを保存した時よりもディスクの使用容量が少なくなることを期待されることかと思います。 | |
Realmファイルの容量が非常に大きくなった場合、Realmがオブジェクトをトラッキングするために中間データを作っているためです。 | |
<a href="api/Classes/RLMRealm.html#//api/name/invalidate"><code>invalidate</code></a> を呼ぶことで、Realmオブジェクトを解放してください。<br /> | |
データの一貫性を保つために、データをフェッチしたときのみバージョンがアップデートされます。 | |
このことは、Realmからデータを読み込み、別のスレッドでそのデータの更新が行われた場合、読み込まれたデータの情報はアップデートされないということです。 | |
そして、Realmは、この中間バージョンを管理するために、内部でのみ使用されるデータが増えていき、その結果、ディスクの使用領域が肥大化してしまうことになります。 | |
(この余分なスペースは、今後の書き込みで再度、使われるか、圧縮されることになります。例えば、<a href="api/Classes/RLMRealm.html#//api/name/invalidate"><code>writeCopyToPath:error</code></a> が呼ばれた時などです)</p> | |
<p>その代わりに、<code>invalidate</code> を呼ぶことで、Realmにこれまでに読んできたデータは必要なく、オブジェクトの中間バージョンは必要ないと伝え、解放してあげてください。</p> | |
<h2 id="faq">FAQ</h2> | |
<h4 id="realm-8">Realmは、どれくらいの大きさですか?</h4> | |
<p>アプリをリリースビルドすると、Realmのサイズは1MBぐらいになります。<br /> | |
現在、配布されているRealmは、ARM, ARM64, x86 のシュミレータに対応しているのとDebug用のシンボルが含まれてるため、著しく大きく(iOS版は、~37MB, OSX版は、~2.4MB)なっています。それらは、ビルド時にXcodeが、自動的に取り除いてくれます。</p> | |
<h4 id="realm-9">Realmをプロダクション環境で使うことはできますか?</h4> | |
<p>Realmは、2012年から商業利用がされています。 | |
ご利用される場合は、RealmのObjective-C/SwiftAPIが、頻繁に変わるものだとお考えの上、<a href="http://eepurl.com/VEKCn">Community Feedback</a> を確認しながらお使いください。 | |
機能追加、バグ修正も同様にお考えください。</p> | |
<h4 id="relam">Realmを使うのにお金を払わないといけませんか?</h4> | |
<p>いいえ、Realmは、完全に無料です。商業利用も可能です。</p> | |
<h4 id="section-26">どのようなビジネスプランなのですか?</h4> | |
<p>すでにエンタープライズ向けの商品の販売や、周辺サービスによって収益を得ています。もし現在リリースされているものや<a href="http://github.com/realm/realm-cocoa">realm-cocoa</a>で更に必要なものがあれば、いつでも<a href="[email protected]">メール</a>で、お気軽にご連絡ください。また私たちのビジネスとは関係なく、<a href="http://github.com/realm/realm-cocoa">realm-cocoa</a>はオープンに開発をつづけていき、Apache License 2.0の元にオープンソースで公開し続けます。</p> | |
<h4 id="tightdb--core-">“tightdb” や “core” という文字をコードの中で見たのですが、これは何ですか?</h4> | |
<p>TightDBというのは、C++で実装されたストレージエンジンの名前です。現在、オープンソースではありませんが、Apache License 2.0として公開することを検討中です。<br /> | |
バイナリリリースは、<a href="https://github.com/realm/realm-cocoa/blob/master/LICENSE">Realm Core (TightDB) Binary License</a> として利用可能です。</p> | |
</div> | |
<!--/docs-wrapper --> | |
</div> | |
<!--/col--> | |
<div class="col-md-3 col-md-offset-1"> | |
<div class="navbar-docs visible-md visible-lg" data-spy="affix" data-offset-top="140"> | |
<ul class="nav nav-pills nav-stacked" id="markdown-toc"> | |
<li><a href="#section">はじめに</a> <ul> | |
<li><a href="#section-1">インストール</a></li> | |
<li><a href="#realm-browser">Realm Browser</a></li> | |
<li><a href="#xcode-plugin">Xcode Plugin</a></li> | |
<li><a href="#api-reference">API Reference</a></li> | |
<li><a href="#section-2">サンプル</a></li> | |
<li><a href="#section-3">ヘルプ</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-4">モデル</a> <ul> | |
<li><a href="#section-5">プロパティの型</a></li> | |
<li><a href="#section-6">プロパティ属性</a></li> | |
<li><a href="#realm">Realmモデルクラスのカスタマイズ</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-7">書き込み</a></li> | |
<li><a href="#section-8">クエリ</a> <ul> | |
<li><a href="#section-9">オブジェクトの取得</a></li> | |
<li><a href="#predicate">Predicateを使ったフェッチ</a></li> | |
<li><a href="#section-10">ソート</a></li> | |
<li><a href="#section-11">連続したクエリの実行</a></li> | |
</ul> | |
</li> | |
<li><a href="#realms">Realms</a> <ul> | |
<li><a href="#realm-1">デフォルトRealm</a></li> | |
<li><a href="#realm-2">その他のRealm</a></li> | |
<li><a href="#in-memory-realms">In-Memory Realms</a></li> | |
<li><a href="#section-12">スレッド間での実行</a></li> | |
<li><a href="#realm-3">Realm間でのオブジェクトのコピー</a></li> | |
<li><a href="#realm-4">初期データとしてのRealm</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-13">リレーションシップ</a> <ul> | |
<li><a href="#to-one">To-One</a></li> | |
<li><a href="#to-many">To-Many</a></li> | |
<li><a href="#inverse-relationships">Inverse Relationships</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-14">通知</a></li> | |
<li><a href="#section-15">マイグレーション</a> <ul> | |
<li><a href="#section-16">マイグレーションの実行</a></li> | |
<li><a href="#section-17">バージョンの追加方法</a></li> | |
<li><a href="#linear-migrations">Linear Migrations</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-18">暗号化</a></li> | |
<li><a href="#section-19">デバッグ</a></li> | |
<li><a href="#section-20">テスト</a> <ul> | |
<li><a href="#realm-5">Realmを使ったアプリのテスト</a></li> | |
<li><a href="#realm-6">Realmのテスト</a></li> | |
</ul> | |
</li> | |
<li><a href="#rest-api">REST API</a> <ul> | |
<li><a href="#section-21">ベストプラクティス</a></li> | |
<li><a href="#example">Example</a></li> | |
</ul> | |
</li> | |
<li><a href="#section-22">次のステップ</a></li> | |
<li><a href="#section-23">開発中の機能</a></li> | |
<li><a href="#faq">FAQ</a></li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
</div> | |
<footer> | |
<div class="container"> | |
<ul> | |
<li><a href="https://github.com/realm" title="Fork us on Github"><i class="fa fa-github fa-2x"></i><br>@realm</a></li> | |
<li><a href="http://twitter.com/realm" title="Follow us on Twitter"><i class="fa fa-twitter fa-2x"></i><br>@realm</a></li> | |
<li><a href="https://stackoverflow.com/questions/tagged/realm?sort=newest" title="#Realm on StackOverflow"><i class="fa fa-stack-overflow fa-2x"></i><br>#realm</a></li> | |
<li><a href="http://eepurl.com/VEKCn" title="Community Newsletter"><i class="fa fa-envelope fa-2x"></i><br>news</a></li> | |
<li><a href="http://j.mp/realm-office-hours" title="Online Office Hours"><i class="fa fa-comments fa-2x"></i><br>help</a></li> | |
</ul> | |
<p class="ycombinator-logo">A <a href="http://ycombinator.com/"><img src="/assets/ycombinator-logo.jpg" alt="a ycombinator company"/></a> company</p> | |
<p class="centered">© <a class="realm-inc" href="http://www.crunchbase.com/organization/realm-2">Realm</a> 2015, all rights reserved.</p> | |
</div><!--/container --> | |
</footer> | |
<script> | |
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | |
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | |
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | |
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | |
ga('create', 'UA-50247013-1', 'realm.io'); | |
ga('send', 'pageview'); | |
</script> | |
<script type="text/html" id="nav-pills-template"> | |
<ul class="nav nav-pills"> | |
<li class="active"><a href="#" data-index="0">Objective-C</a></li> | |
<li><a href="#" data-index="1">Swift</a></li> | |
</ul> | |
</script> | |
<script type="text/javascript"> | |
$(document).ready(function() { | |
var url = document.location.toString(); | |
if (url.match('#swift')) { | |
$('.nav-tabs.getting-started a[href=#'+url.split('#')[1]+']').tab('show') ; | |
} | |
}); | |
$( document ).ready(function() { | |
$(".navbar-docs>ul").append('<li><a href="api/" target="_blank">API Reference <span class="glyphicon glyphicon-new-window"></span></a></li>'); | |
}); | |
$(document).ready(function() { | |
var $nav_pills_template = $('#nav-pills-template') | |
// Decorate each .highlight-wrapper with a nav-pills element | |
$('.highlight-wrapper').each(function(index, wrapper) { | |
var $wrapper = $(wrapper) | |
var $nav_pills = $($nav_pills_template.html()) | |
$wrapper.append($nav_pills) | |
$(wrapper).find("pre").css("min-height", function(){ | |
return $(wrapper).first("pre").height(); | |
}); | |
}) | |
}); | |
$(document).ready(function() { | |
$('.highlight-wrapper .nav-pills li a[data-index="0"]').click(function(event){ | |
event.preventDefault(); | |
$('.highlight').has('code[data-lang="swift"]').hide(); | |
$('.highlight').has('code[data-lang="objective-c"]').show(); | |
$('.highlight-wrapper .nav-pills li').has("a[data-index='1']").removeClass('active'); | |
$('.highlight-wrapper .nav-pills li').has("a[data-index='0']").addClass('active'); | |
}) | |
$('.highlight-wrapper .nav-pills li a[data-index="1"]').click(function(event){ | |
event.preventDefault(); | |
$('.highlight').has('code[data-lang="swift"]').show(); | |
$('.highlight').has('code[data-lang="objective-c"]').hide(); | |
$('.highlight-wrapper .nav-pills li').has("a[data-index='1']").addClass('active'); | |
$('.highlight-wrapper .nav-pills li').has("a[data-index='0']").removeClass('active'); | |
}) | |
}); | |
$(document).ready(function() { | |
['RLMObject', 'RLMArray', 'RLMRealm', 'RLMResult'].map( function(classname){ | |
$("p:contains("+classname+")").contents().filter(function(){ return this.nodeType == 3; }).each( function(){ | |
var text = $(this).text(); | |
var re = new RegExp(classname+"(s)?", "gi"); | |
if (classname == 'RLMResult') { classname = 'RLMResults' } | |
text = text.replace(re, '<a href="api/Classes/'+classname+'.html">$&</a>', 'g'); | |
$(this).replaceWith(text); | |
}) | |
}) | |
}); | |
$(document).ready(function() { | |
['RealmObject', 'RealmList', 'RealmResult', 'RealmQuery', 'RealmBaseAdapter'].map( function(classname){ | |
$("p:contains("+classname+")").contents().filter(function(){ return this.nodeType == 3; }).each( function(){ | |
var text = $(this).text(); | |
var re = new RegExp(classname+"(s)?", "gi"); | |
if (classname == 'RealmResult') { classname = 'RealmResults' } | |
text = text.replace(re, '<a href="api/io/realm/'+classname+'.html">$&</a>', 'g'); | |
$(this).replaceWith(text); | |
}) | |
}) | |
}); | |
$(document).ready(function() { | |
var url = document.location.toString(); | |
if (url.match('#swift')) { | |
$('.nav-tabs.getting-started a[href=#'+url.split('#')[1]+']').tab('show') ; | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment