LaTeX関連のめちゃくちゃ便利な機能たち
はじめに
論文を書くようになって色々と機能を使わないと書くのが大変になってきたため、色々と導入してみました。それの備忘録かつこんなの使えると便利!っていうのがまとまってるといいなと思ったので記事の執筆に至りました。
ファイル分割
1つのtexファイルに全ての内容を書いてしまうと、編集しづらくなったりなどといった不便が生じます。したがって分量のある文書を作成する際は、SectionやChapterごとにファイルを分割するのが一般的です。
方法
\documentclass{hoge-thesis} \usepackage{docmute} \input{setting} \begin{document} \include{1-introduction} %\include{2-hoge} \end{document}
\documentclass{hoge-thesis} \input{setting} \begin{document} \section{introduction} hogehoge... \end{document}
% その他のパッケージなど % \usepackage{...}
1. 分割するファイル(ここではsetting.texと1-introduction.tex)を作成
2. master.texでdocmuteパッケージを読み込む
3. master.texおよび1-introduction.texに\input{setting}によりsetting.texを読み込む
4. master.texに\include{1-introduction}で1-introduction.texを挿入
※\input{}および\include{}にはファイル名の.texを外したものを書いてください。
ちょっとだけ説明
参考
bibtex
bibtexを用いることで100個など多数ある参考文献の記載をとても楽にできます。
方法
\begin{document} 〜らの研究[\cite{test}]によると〜 %... \bibliography{reference} \bibliographystyle{junsrt} %.. \end{document}
@article{test, author="Mairittha, Nattaya and Mairittha, Tittaya and Inoue, Sozo", title="On-Device Deep Learning Inference for Efficient Activity Data Collection", journal="Sensors", ISSN="1424-8220", publisher="MDPI", year="2019", month="aug", volume="19", number="15", pages="3434-1-3434-20", URL="https://ci.nii.ac.jp/naid/120006719301/", DOI="", }
reference.bibの内容は大抵のサイトからアクセスでき、それをコピペしてくるだけでokです。
1. mastex.texをコンパイル
2. 以下のどちらかのコマンドでデータベースの参考文献を反映
・和文 → bibtex {TeXファイル名}
・英文 → bibtex {TeXファイル名}
3. master.texを3回コンパイル
引用や参考文献の表示順などについては以下の記事を参照してください。
qiita.com
latexmk
latexmkはplatexやdvipdfmx、bibtexなど複数あって面倒な処理をコマンド一つで全てやってくれるやつでMakefileに近いですが、設定が遥かに楽なものになっているので、こちらの方が良いかなと思います。
設定
~/.latexmkrcを作成します。
#!/usr/bin/env perl $pdf_mode = 3; $latex = 'platex -halt-on-error'; $latex_silent = 'platex -halt-on-error -interaction=batchmode'; $bibtex = 'pbibtex'; $dvipdf = 'dvipdfmx %O -o %D %S'; $makeindex = 'mendex %O -o %D %S';
実行
$ latexmk master.tex
これだけで.texから.pdfを作成してくれます。また上記の設定では記述していませんが、この後pdfビューワーを開いてくれるなどといった設定も可能です。詳細は以下をどうぞ。
qiita.com
qnighy.hatenablog.com
ReactNative+Expoでジャイロセンサーと加速度センサーを使って姿勢を推定し、WebSocketでPCに送信して、OpenGLで可視化する
やりたいこと
WebSocketとPyOpenGLは姿勢の精度を視覚的に確認したかったのでやりました。姿勢推定はオイラー角、回転行列、クォータニオンなど色々ありますが、今回はクォータニオンを使います。また、姿勢の補正(ジャイロと加速度の合成??)はとりあえず一番簡単であろう相補フィルターを使います。OpenGLについてはあまり書かないのでご了承願います。。。
追記(2018/3/6): 姿勢の推定はExpoのDeviceMotionを使うことで簡単に実装することができるようです
Pythonによるデータ受信と可視化
ソースコードを貼っておきます。
Gyroscope Tester · GitHub
姿勢推定のクォータニオン周りは出来るだけ視覚的に確認しながら作りたいのでサーバーサイドからやります。
WebSocket
WebSocketは少ないデータ量でリアルタイムに通信するためのプロトコルです。今回はリアルタイムに通信を行いたいのでこれを使います。実装は今回のような一時的に使うような凝ったものでなければ、詳細を知らなくてもできると思いますが、一応WebSocketとはなんぞや的なものが書いてある記事を下に貼っておきます。OpenGLとWebSocketをメインスレッドで同時に行えない(?)ので別スレッドを立てて行いました。(これが正しいかはわかりませんが一応できたので良しとしています...)
WebSocketのインストール
sudo pip3 install websocket-server
サーバー(描画側)のコード
from websocket_server import WebsocketServer import threading def new_client(client, server): print("connected") def received_quaternion(client, server, message): # クォータニオンから回転軸と回転角を計算し、その値を更新する処理 # 送られてくるデータはmessageに格納されている def buildServer(): # サーバーのIPアドレスとポート番号を引数にしてWebsocketServerクラスを生成 # IPは各自で調べて入力してください server = WebsocketServer(9999, host='192.168.1.6') # 新しい接続があったときの関数を設定 server.set_fn_new_client(new_client) # データを受け取ったときの関数を設定 server.set_fn_message_received(received_quaternion) # サーバーを立ち上げる server.run_forever() if __name__ == "__main__": threadServer = threading.Thread(target=buildServer) threadServer.start()
動作確認
wscatを用いることでクライアントやサーバーがない状態でも動作確認を行うことができます。まずはインストールします。
sudo apt-get install npm sudo npm install -g wscat
次に以下のコマンドで起動します。IPアドレスはプログラム内で使用したものを入力します。
wscat -c ws://192.168.1.6:9999
"connect"で出力されればコネクションの確立が完了しています。
qiita.com
www.raspberrypirulo.net
PyOpenGL
最近はglutではなくglfwを使うのが流行りらしいですが、スマホのセンサーのテスト用に作るプログラムで、学習コストを割きたくないので、glutを使います。
PyOpenGLとGLUTのインストール
次のリンクを頼りにインストールしてください。
tokoik.github.io
プログラム
from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * rotationValue = 90 rotationVector = [1, 0, 0] def display(): glEnable(GL_DEPTH_TEST) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glPushMatrix() glRotatef(rotationValue*180/math.pi, rotationVector[0],rotationVector[1],rotationVector[2]) glMaterialfv(GL_FRONT, GL_DIFFUSE, [1.0, 0.0, 0.0,1.0]) glColor3f(1.0, 1.0, 1.0) glutSolidCube(0.5) glColor3f(0.0, 0.0, 0.0) glutWireCube(0.5) glDisable(GL_LIGHTING) # Axis glColor3f(0.0, 0.0, 1.0) glBegin(GL_LINES) glVertex3f( 999.0, 0.0, 0.0) glVertex3f(-999.0, 0.0, 0.0) glEnd() glColor3f(0.0, 1.0, 0.0) glBegin(GL_LINES) glVertex3f( 0.0, 999.0, 0.0) glVertex3f( 0.0, -999.0, 0.0) glEnd() glColor3f(1.0, 0.0, 0.0) glBegin(GL_LINES) glVertex3f( 0.0, 0.0, 999.0) glVertex3f( 0.0, 0.0, -999.0) glEnd() glPopMatrix() glFlush() def timer(value): glutPostRedisplay() glutTimerFunc(10, timer, 0) def pyMain(): glutInit(sys.argv) glutInitWindowSize(600, 600) glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH) glutCreateWindow(b"OpenGL") glMatrixMode(GL_PROJECTION) glLoadIdentity() glMatrixMode(GL_MODELVIEW) glutDisplayFunc(display) glutTimerFunc(10, timer, 0) glClearColor(0.0, 0.0, 0.0, 1.0) glutMainLoop() if __name__ == "__main__": pyMain()
PyOpenGLに関しては何も書いてないのですが、OpenGLとほとんど同じ(セミコロンがなかったりするだけ)なので、OpenGLで検索して出てきた解説ページなどを見ればなんとなく理解できると思います。
- 作者: 林武文,加藤清敬
- 出版社/メーカー: コロナ社
- 発売日: 2003/04/01
- メディア: 単行本
- 購入: 3人 クリック: 38回
- この商品を含むブログ (13件) を見る
ReactNativeでクライアント側を作る
加速度と角速度の取得方法
加速度にはAccelerometer、角速度にはGyroscopeというexpoでデフォルトで使えるAPIを使用します。
docs.expo.io
docs.expo.io
AccelerometerとGyroscopeの使い方はほとんど一緒です。
import React from 'react'; import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { Accelerometer, Gyroscope } from 'expo'; export default class App extends React.Component { componentDidMount() { this._toggle(); } componentWillUnmount() { this._unsubscribe(); } _toggle = () => { if (this._subscription) { this._unsubscribe(); } else { this._subscribe(); } }; _subscribe = () => { // Accelerometerがデータを取得するインターバルと取得した際の処理を設定 Accelerometer.setUpdateInterval(16); this._accSubscription = Accelerometer.addListener((result) => { console.log("Acc:", result); # 相補フィルターの処理を書く }); // Gyroscopeがデータを取得するインターバルと取得した際の処理を設定 Gyroscope.setUpdateInterval(16); this._gyroSubscription = Gyroscope.addListener((result) => { console.log("Gyro:", result); # クォータニオンによる姿勢推定をここで行う }); }; _unsubscribe = () => { this._accSubscription && this._accSubscription.remove(); this._accSubscription = null; this._gyroSubscription && this._gyroSubscription.remove(); this._gyroSubscription = null; }; render() return ( <View style={styles.container}> <Text>Hello World</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, }, });
WebSocketでサーバーに送信する
WebSocketもAccelerometerなどと同様にexpoでデフォルトで使うことができます。
docs.expo.io
import React from 'react'; import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; export default class App extends React.Component { componentDidMount() { // WebSocketクラスを生成 this.ws = new WebSocket("ws://192.168.1.6:9999"); } // コネクション確立時に実行される this.ws.onopen = () => { console.log("connected"); // データを送信できる // 実際にはtimerなどを使ってクォータニオンを送信する this.ws.send("Javascript"); } this.ws.onerror = (e) => { console.log(e.message); } render() return ( <View style={styles.container}> <Text>Hello World</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, }, });
ジャイロセンサーのデータから姿勢推定する
下の動画にあるように角速度を単純に積算するだけでは、姿勢は推定できません。そのため、クォータニオンを用います。
www.youtube.com
クォータニオンについては以下のサイトが参考になるかと思います。特にMSSさんの「クォータニオン計算便利ノート」は非常にまとまっていてわかりやすいです。
・【Unity道場 博多スペシャル 2017】クォータニオン完全マスター - YouTube
・http://www.mss.co.jp/technology/report/pdf/18-07.pdf
・Python 3.x - ジャイロセンサーから測定したquaternionによる姿勢推定を用いた加速度の回転方法について|teratail
・クォータニオンから回転角と回転軸の算出 ( プログラム ) - Color Model:色をプログラムするブログ - Yahoo!ブログ
・quaternion - npm
初期クォータニオンを作って、角速度からクォータニオンの時間変化を作って足しこむことで、次ステップでのクォータニオンを求められます。計算を繰り返していると誤差が累積してしまうので、計算毎に正規化を行います。
var quat = new Quaternion([1.0, 0.0, 0.0, 0.0]); // グローバル変数 var Quaternion = require('quaternion'); this._gyroSubscription = Gyroscope.addListener((result) => { var dt = 0.10 var wx = -result.x var wy = -result.y var wz = result.z var dq = new Quaternion([ 0*quat.w -wx*quat.x -wy*quat.y -wz*quat.z, wx*quat.w + 0*quat.x -wz*quat.y +wy*quat.z, wy*quat.w +wz*quat.x + 0*quat.y -wx*quat.z, wz*quat.w -wy*quat.x +wx*quat.y + 0*quat.z]) dq = dq.scale(0.5*dt) quat = quat.add(dq) quat = quat.normalize(); this.ws.send("Gyroscope " + "Quaternion:" + " w:"+quat.w.toString() + " x:"+quat.x.toString() + " y:"+quat.y.toString() + " z:"+quat.z.toString()); });
加速度で相補フィルターをかける
相補フィルターはざっくりいえばジャイロセンサーと加速度センサーの加重平均のようなものです。以下の記事が非常にわかりやすいです。ベクトル演算をしたかったので、Three.jsをちょっとだけ使いました。以下のコードはまだ係数の設定をしていません。加速度とジャイロだけだとヨー軸を揃えることはできません。
qiita.com
import ExpoTHREE from 'expo-three' import { THREE } from 'expo-three' Accelerometer.setUpdateInterval(10); this._accSubscription = Accelerometer.addListener((result) => { var dt = 0.050 var acc = new THREE.Vector3(result.x*dt, result.y*dt, result.z*dt) var gravity = new THREE.Vector3(0, 0, 1) // Gが大きい時はそもそも加速度計の値を使用しないようにしています。 if(Math.abs(acc.x)+Math.abs(acc.y)+Math.abs(acc.z) < 1.5){ var accVectorCalc = quat.inverse().mul(acc).mul(quat).toVector().slice(1,4) var accVector = new THREE.Vector3(accVectorCalc[0],accVectorCalc[1],accVectorCalc[2]) var correctionVector = accVector.cross(gravity) var correctionValue = Math.acos(accVector.dot(gravity)) var accQuat = new Quaternion(Math.cos(0.5*correctionValue), [correctionVector.x*Math.sin(0.5*correctionValue),correctionVector.y*Math.sin(0.5*correctionValue),correctionVector.z*Math.sin(0.5*correctionValue)]) quat = quat.mul(accQuat) } });
React-Native-Chart-kitでグラフを書く
※ほとんどDocumentの翻訳です。Get Startedだけです。
Get Started
とりあえずDocumentに載っていたQuickExampleを動かしてみる。
yarn add react-native-chart-kit
import React from 'react'; import { StyleSheet, Text, View, Dimensions } from 'react-native'; import { LineChart, BarChart, PieChart, ProgressChart, ContributionGraph } from 'react-native-chart-kit' const screenWidth = Dimensions.get('window').width; export default class App extends React.Component { render() { return ( <View> <Text> Bezier Line Chart </Text> <LineChart data={{ labels: ['January', 'February', 'March', 'April', 'May', 'June'], datasets: [{ data: [ Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100 ] }] }} width=screenWidth height={220} chartConfig={{ backgroundColor: '#e26a00', backgroundGradientFrom: '#fb8c00', backgroundGradientTo: '#ffa726', decimalPlaces: 2, // optional, defaults to 2dp color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`, style: { borderRadius: 16 } }} bezier style={{ marginVertical: 8, borderRadius: 16 }} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
チャートのスタイルはchartConfigで記述されている。指定できる値はチャートの種類によって違う。Documentにグラフの各種類におけるchartConfigで指定できる値が書いてある。グラフの種類は以下の通り。
・Line
・Bezier Line
・Progress Ring
・Bar
・Pie
・Contribution graph
github.com
レスポンシブな(様々なデバイスの大きさに対応した)グラフを書くにはDimensionsを使って画面サイズを取得して、その値を渡してあげる必要がある。
import { Dimensions } from 'react-native' const screenWidth = Dimensions.get('window').width // <LineCharts>タグ内 width=screenWidth
ImagePickerを使うときのデバイスのパーミッション関連
ImagePicker
Udemyの"実践的!作って学ぶReactNative入門!"でexpoを使っていてreact-native-image-crop-pickerの代わりにImagePickerを使ったのですが、その時にパーミッションでちょっと苦戦したのでメモを残しておきます。以下のサイトを参考にしました。JavaScript, ReactNative初心者なので書き方が適切であるかはわかりません。
Permissions - Expo Documentation
ImagePicker - Expo Documentation
ソースコード
import React from 'react'; import { StyleSheet, Text, View, Button, Image, TouchableOpacity } from 'react-native'; import { ImagePicker, Permissions, Camera, CameraRoll } from 'expo'; export default class App extends React.Component { constructor(props) { super(props); this.state = { image: null, permission: false, }; } async componentWillMount() { let results = await Promise.all([ await Permissions.askAsync(Permissions.CAMERA), await Permissions.askAsync(Permissions.CAMERA_ROLL) ]); this.setState({ permission: results.every((result) => { const { status } = result; return status === 'granted'; }) }); } render() { let { image } = this.state; const { permission } = this.state; if (permission === false) { return ( <View style={styles.container}> <Text>カメラの使用が許可されていません。</Text> </View> ); } return ( <View style={styles.container}> <Button title="Pick an image from camera roll" onPress={this._pickImage} /> {image && <Image source={{ uri: image }} style={{ width: 200, height: 200 }} /> } </View> ); } _pickImage = async () => { let result = await ImagePicker.launchImageLibraryAsync({ allowsEditing: true, aspect: [4, 3], }); //console.log(result); if (!result.canelled) { this.setState({ image: result.uri }); } } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
Google Map SDK for iOS (addSubviewを使う)
今回やったところ
公式のドキュメントやQiitaにある記事を見ても下のコードのようにUIViewそのものをそっくり置き換え(?)ていたが、Mapと同一のUIViewにStoryboard上でボタンを配置したい。
view = mapView
とりあえず作成したプログラムとストーリーボード。
let BoundSize: CGSize = UIScreen.main.bounds.size let camera = GMSCameraPosition.camera(withLatitude: 35.681167, longitude: 139.767052, zoom: 14.0) let mapView = GMSMapView.map(withFrame: CGRect.init(x: 0, y: 0, width: BoundSize.width, height: BoundSize.height), camera: camera) mapView.center = CGPoint(x:self.view.frame.width/2,y:self.view.frame.height/2) view.addSubview(mapView) self.view.sendSubviewToBack(mapView)
AddDataViewControllerのシーンのバックにマップを表示させて、マップ以外はStoryboardで作った。
- BoundSizeで画面の大きさを取得
- GMSMapView.mapの引数withFrameにCGRectでマップを表示する領域を指定して(?)Viewを作成
- addSubviewでAddDataViewControllerのビューに追加
- 最全面に配置されて他の部品が隠れてしまうので、sendSubviewToBackで最背面に移動
未解決の問題
上記の方法でやる前にContainer Viewを使って、それにembedした(?)MapViewContrallerという別クラスで作ろうとした。(それが設計上適切であるかはわからないけど、公式ドキュメントがview = mapViewとしていたのもあって)
でもマップとその他部品は正しく表示されたけど、指定した緯度経度の位置が画面の一番左上にきてしまった。
色々試行錯誤したけど解決できなかったので、原因等がわかるかたは良かったらコメントしてほしい。。。
iOSでFirebase入門 その2
今回やること
- データの読み込み
- データの書き込み
- 実装
メモ帳みたいな記事なので悪しからず...
読み込みと書き込みで共通のやるべきこと
まず、以下がインストールされていることを確認。
pod 'Firebase/Core' pod 'Firebase/Database' pod 'SwiftyJSON'
RealTime DatabaseとCloud Firestoreの2種類があるが、ここではRealTimeDatabaseを使う。コンソール(Webサイトのやつ)からRealtime Databaseのルールを開き、writeとreadの権限をtrueにする。
次はXcodeのプロジェクト側。データベースへの参照を定義する。
var ref: DatabaseReference! ref = Database.database().reference()
データの読み込み
observeを使うことでデータベースにアクセスできる。observeメソッドはデータベースに変更がある度に自動的に呼び出される。引数によって、変更の種類を選択できる。observeの他にobserveSingleEventというメソッドがあり、こっちは一度だけ実行されるメソッド。結果はsnapShotに格納される。
var username: [String] override func viewDidLoad() { super.viewDidLoad() ref = Database.database().reference() let postRef = ref.child("users") postRef.observe(.value) { (snapShot) in let json = JSON(snapShot.value as? [String : AnyObject] ?? [:]) self.username = [] for (key, val) in json.dictionaryValue { self.username.append(json[key]["username"].stringValue) } } }
データの書き込み
Firebase Realtime DatabaseではJsonオブジェクトで保存される。Jsonは連想配列のようなもの。
{ "users": { "alovelace": { "name": "Ada Lovelace", "contacts": { "ghopper": true }, }, "ghopper": { ... }, "eclarke": { ... } } }
データベースにデータを保存する為のメソッド一覧。(公式からの引用)
メソッド | 一般的な使用例 |
---|---|
setValue | users/ |
childByAutoId | データのリストに追加します。childByAutoId を呼び出すたびに、user-posts/ |
updateChildValues | データのすべてを置換することなく、定義済みのパスのキーの一部を更新します。 |
runTransactionBlock | 同時更新によって破損する可能性がある複合データを更新します。 |
以下のようにすることで、データベースにデータが追加されます。
let data = ["username": "jon", "message": "hello"] let uid = "001" ref.child("users").child(uid).setValue(data)
let data = ["username": "Albert"] let uid = "001"
とし、ユーザー名前だけを変更したい場合、setValueだと前回追加した際に記録されている"message"が消えてしまいます。これはsetValueはchildで指定した階層以下全てを書き換えるためです。他の値を残したいまま、更新したい場合はupdateChildvaluesを用います。
childByAutoIdは自動的にIDを割り振ってくれます。
let data = ["username": "bob","message":"good bye"] ref.child("chat").childByAutoId().setValue(data)
実装
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { var ref: DatabaseReference! var username: [String] = [] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.delegate = self ref = Database.database().reference() let postRef = ref.child("users") postRef.observe(.value) { (snapShot) in let json = JSON(snapShot.value as? [String : AnyObject] ?? [:]) if json.count == 0 { return } self.username = [] for (key, val) in json.dictionaryValue { self.username.append(json[key]["username"].stringValue) } self.tableView.reloadData() } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.username.count } func numberOfSections(in tableView: UITableView) -> Int { // sectionの数を決める return 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "firebase_cell", for: indexPath) cell.textLabel?.text = self.username[indexPath.row] return cell } } class AddDataViewController: UIViewController, UITextFieldDelegate{ @IBOutlet weak var username_textField: UITextField! @IBOutlet weak var message_textField: UITextField! var ref: DatabaseReference! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. ref = Database.database().reference() username_textField.delegate = self message_textField.delegate = self } @IBAction func sendData(_ sender: Any) { let data = ["username": username_textField.text!,"message":message_textField.text!] ref.child("users").childByAutoId().setValue(data) performSegue(withIdentifier: "toTableView",sender: nil) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }
iOSでFirebase入門 その1 サインアップとサインイン
Firebaseとは
Googleが提供してるサーバー処理を楽に行なってくれるmBaaS。
※ mBaaSは「Backend as a Service」の略で、スマホ向けのウェブアプリ機能を提供するサービスのこと。
(Firebaseについてわかってきたら追記予定。
プロジェクトのスタートアップ
Xcodeでプロジェクトを作成したら、Bundle Identifierの値をコピーしておく。Firebaseのページからプロジェクトの追加する。
先ほどコピーしたBundle Identifireをここに貼り付ける。
以降しばらくXcodeのプロジェクトとFirebaseのプロジェクトをリンクする手順が示されるのでそれに沿って進める。
ここまででとりあえず、XcodeのプロジェクトでFirebaseを使えるようになっているはず。
サインインとサインアップ
Firebaseではアカウント管理を簡単に行うことができる。また、メール、電話認証、Google、Facebook、Twitterなど様々なプロバイダ認証が行える。ここではもっとも単純(そうな)メールでの認証を行なってみる。
まず、Firebase/Authをpod installしておく。
pod ‘Firebase/Auth’
サインアップ部分。
@IBAction func signUpButtonTapped() { // "in"以下で完了時に実行される処理を記述。authResultかerrorに値が代入されている。 Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!) { (authResult, error) in if let error = error { self.statusLabel.text = "Creating the user failed! \(error)" } // authResultからユーザー情報を取得できる。 if let user = authResult?.user { // user.mailとすることでメールアドレスが取得できる。 self.statusLabel.text = "user : \(String(describing: user.email)) has been created successfully." } } }
authResult.userではメール以外でも下記の情報が管理できるらしい。
user.getUid(); // UID(ユーザー一意のID)
user.getDisplayName(); // 表示名
user.getEmail(); // E-mail
user.getPhotoUrl(); // プロフ用画像URL
user.getProviders(); // プロバイダ情報
user.isAnonymous(); // true:匿名ユーザー
次にサインイン。
@IBAction func signInButtonTapped() { Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!) { (authResult, error) in if let error = error { self.statusLabel.text = "Login failed. error: \(error)" } if let user = authResult?.user { self.statusLabel.text = "user: \(String(describing: user.email)) has been signed in successfully." } } } }
なお、登録されているユーザー情報はFirebaseのコンソール(Webサイト側のやつ)の開発->Authentificationからみることができる。