20210608のSwiftに関する記事は11件です。

【swift】viewControllerとtableViewだけでtodoアプリを作る

お題 swiftで簡単なtodoアプリを作る 百万年ぶりにネイティブ言語に戻ってきたような気がします。 今回はswiftを使ってよくあるtodoアプリを作っていきたいと思います。 用意するファイルは以下の通り storyBord ViewController 後はUITableViewとtableCellがあれば一通りの機能は揃います。 まず初めにcreateNewXcodeProjectでAppを選択。 使用言語はswift。UI描画はswiftUIを使わずにstoryBordを使います。 上記の条件で作成するとswiftの初期アプリのソースが表示されます。 1. UIをstoryBordに配置 ViewControllerはまだ触らずstoryBordに以下のように配置します。 ※Command+shift+lでUI追加フォームが出てくるのでその中から textField,buton,UITableViewをそれぞれ以下のように設置。役割は以下。 textField: todoリストに表示したいテキストを入力 button: todoリストに追加 TableView: todoリスト(tableCell)を表示する領域 tableCell: todoテキストを表示するための入れ物。TableViewの傘下に追加 全て追加した後、tableCellをクリック。すると画面右側にメニューが表示されます。 右から3番目のshow the attributes inspectorを クリックして、その中にあるidentifierにtableCellと名前をつけます。 これがないと後に追加する関数にテキストが反映されません。 UIを全て追加・identifierを追加したところでstoryBordの作業はここで一旦終了。 2. storyBordの要素をViewControllerに紐付け storyBordのUI設置が終わったので実際にそれらを使えるようにします。 これらを機能させるにはViewContollerとstoryBordと連携させなければいけません。 連携するにはまずcontrolを押しながらViewControllerにドラッグ。すると以下のような 構文がViewControllerに追加されます。 ViewController class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var input: UITextField! @IBOutlet weak var tableCell: UITableView! } これらの変数はstoryBordで追加したUIの模型みたいな物であり、この中に後々やりたいことを 吹き込みます。 3. セルの生成 必要なものは揃ったので、いよいよセルに反映する処理を書いていきます。 tableViewを扱う際にはセルの数をtableViewに教える関数とセルを生成して テキストを表示させる関数が必須になります。 ViewController var textFieldString = "" let myItems: NSMutableArray = ["ハンバーグ", "とんかつ", "餃子"] override func viewDidLoad() { super.viewDidLoad() // Do any } // TableViewに表示するセルの数を返却。 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myItems.count } // 各セルを生成して返却。 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableCell.dequeueReusableCell ( withIdentifier: "tableCell", for: indexPath ) cell.textLabel?.text = "\(myItems[indexPath.row])" return cell } // ボタン押下時のアクション @IBAction func pushButton(_ sender: UIButton) { // TextFieldから文字を取得 textFieldString = input.text! print(textFieldString); myItems.add(input.text!) // TableViewを再読み込み. tableCell.reloadData() input.text = "" } 一気に増えましたね。myItemsのところは何でもいいです。配列だけ書いて let myItems: NSMutableArray = []でも構いません。 二番目のcellForRowAtで、1でidentifierに設定した名前をwithIdentifier に追加します。 一番下のpushButton関数ですが、これも先ほどのUITextFieldやUITableViewと 同様にアウトレットで紐付けをします。 storyBordの中のボタンを選択後コントロール+ドラッグでViewControllerまで 引っ張ってきます。中の処理では、入力された文字(input.text)を受け取ってmyItemに追加しています。 その後tableCell.reloadData()でテーブルを更新しています。 これで一通りの処理は完了です。 4. 全体コード ViewControllerの全体コードがこちら。 ViewController import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var input: UITextField! @IBOutlet weak var tableCell: UITableView! var textFieldString = "" let myItems: NSMutableArray = ["ハンバーグ", "とんかつ", "餃子"] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } // TableViewに表示するセルの数を返却。 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myItems.count } // 各セルを生成して返却します。 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableCell.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) cell.textLabel?.text = "\(myItems[indexPath.row])" return cell } // ボタン押下時のアクション @IBAction func pushButton(_ sender: UIButton) { // TextFieldから文字を取得 textFieldString = input.text! print(textFieldString); myItems.add(input.text!) // TableViewを再読み込み. tableCell.reloadData() input.text = "" } } 5.終わりに 動いたでしょうか。もし動かないのであればUIのアウトレットが正しく接続されているか・ タイプミスがないかを要チェックしてみてください。 この次は、cellに削除ボタンを実装して入力したテキストを削除する機能を作っていきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】RealmでのCURD操作

オブジェクトの生成 Realmでは下記のように専用のクラスを作成しオブジェクトを生成します。 class Plan: Object {    // 変数名の頭に"@objc dynamic var"をつける @objc dynamic var id: String = NSUUID().uuidString @objc dynamic var title: String = "" @objc dynamic var content: String = "" @objc dynamic var createdAt: Date = Date() // プライマリーキーを指定 override static func primaryKey() -> String? { return "id" //プライマリーキーに指定する変数名 } } // こんな感じで任意の方法で入れたいデータを入れる let newPlan = Plan() newPlan.title = "タイトル" newPlan.content = "内容" Create 任意の場所でrealmのインスタンスを作成し下記のようにadd()を使用することによってDBにデータが保存されます。 最後の行のようにデータが保存されているファイルのパスを出力することができ、そのファイルをRealmStudioなどで開くことで、どのんなデータが入っているかを見ることがきます。 import RealmSwift let realm = try! Realm() // DBの参照 //DBにnewPlanを追加 try! realm.write { // 追加したいオブジェクトを引数に入れる realm.add(newPlan) } print(Realm.Configuration.defaultConfiguration.fileURL!) //Realmのファイル場所をプリント Update 下記は保存されている任意のオブジェクトをcreatedAt昇順でソートし、取得しています。 この時に変数に格納されるのは配列になります。 soreted()ではbyKeyPathにPlanクラスで定義したメンバ変数を文字列で指定し、ascendingでは昇順で取得したい場合"true"を、降順で取得したい場合"false"を指定します。 // DBに保存されている任意のオブジェクトを配列で取得してくる let results = realm.objects(Plan.self).sorted(byKeyPath: "createdAt", ascending: true) Read 更新したいオブジェクトをfilterメソッドを使用し、プライマリーキーなどを指定してDBから取得します。 この時、targetPlanには配列が入ってくるので、realm.writeの中ではtargetPlan[0]のように記述しています。 (他の方法があれば教えていただきたいです・・・) // 更新したいオブジェクトをDBから取得してくる let targetPlan = realm.objects(Plan.self).filter("id == '\(planId)'") do{ try! realm.write{ targetPlan[0].title = "タイトル2" targetPlan[0].content = "更新したよ" } } Delete Updateの処理と同様に、プライマリーキーなどを指定して削除したいオブジェクトをDBから取得します。 下記のように記述することで任意のデータを削除できます。 realm.delete()ではtargetPlanが配列のため引数にはtargetPlan[0]を入れています。 // 削除したいオブジェクトをDBから取得してくる let targetPlan = realm.objects(Plan.self).filter("id == '\(planId)'") do{ try! realm.write{ realm.delete(targetPlan[0]) } } 終わりに 多分もっといい方法がありそうですが、お手柔らかに・・・ こういう方法もあるよーとか、自分はこういうふうに使ってるよーなどありましたらご教授いただけると幸いです。 参考資料
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WWDC 2021のSwiftの並行処理関連のセッション一覧

WWDC 2021 が始まりました。 今年は Swift 5.5 で並行処理の大型アップデートが予定 されており、長年待ち望まれていた async/await に加えて、さらに先進的な Structured Concurrency や Actor なども導入されます。そのため、 WWDC 2021 では並行処理関連のセッションが多数予定されています。 そこで、セッション一覧から並行処理関連のものを探して一覧にしてみました。内容はまだわかりませんが、個人的に重要度が高そうだと思う順に並べてみました。各セッション下部のリンクは内容に関係しそうな Proposal です。 (感想) は実際にそのセッションを見た感想です。 もし抜け漏れなどあればコメント下さい? What‘s new in Swift これは並行処理についてのセッションではないですが、 Swift 5.5 での新機能の大きな割合を並行処理関連のものが占めているので、最初にこれを見ることで全体を見渡すことができると思います。 (感想) Swift Evolution の Proposal のまとめだけでなく、 Swift 関連のニュース(たとえば Swift Collections や Swift Algorithms のようなライブラリ)の網羅的なダイジェストになっていてとても良かったです。各項目の詳細は他のセッションに橋渡しされており、並行処理関連でも本記事で次に挙げている三つのセッションが紹介されていました。まずはこれを見て全体像を掴むと良いと思います。 SE-0296: Async/await SE-0304: Structured concurrency SE-0306: Actors SE-0317: async let bindings Meet async/await in Swift (感想) async/await の基本的な使い方から、 Continuation 、同期・非同期処理のブリッジまで、 async/await の実用に求められることが詰まっていました。 Structured Concurrency や Actor の前提知識としても、まずはこれを見るのが良いと思います。ただし、 async { } は Task { } に変更予定なので要注意です1。 SE-0296: Async/await SE-0300: Continuations for interfacing async tasks with synchronous code SE-0310: Effectful Read-only Properties Explore structured concurrency in Swift (感想) Swift の並行処理では async/await や Actor が目立ってますが、僕が一番重要だと思うのがこの Structured Concurrency です。キャンセルの仕組みなんて感動的ですね。このセッションは Structured Concurrency をわかりやすく説明していて、初めて学ぶ人に最適だと思います。 一つだけ付け加えるとすると、 Proposal に書かれていた次の説明です。 a task is to asynchronous functions, what a thread is to synchronous functions ( async な)非同期関数にとっての Task は、( async で ない )同期関数にとってのスレッドのようなものだということですが、これはとても本質的な話だと思います。 同期関数では、その関数の処理は最初から最後まで必ず同じ一つのスレッド上で実行されます。関数の処理が実行されている間はスレッドは専有されていて、一つのスレッド上で複数の処理が並行して実行されることはありません。同様に、非同期関数は最初から最後まで一つの Task 上で実行されます。 await の前後でスレッドが異なることはありますが、それでも必ず同一の Task 上で実行されます。また、一つの Task が複数の処理を並行して実行することはありません。 実際に処理を並行に実行する仕組みであるスレッドと比べて初見ではなかなかとらえどころのない Task ですが、僕はこの説明が一番しっくりきました。 SE-0304: Structured concurrency SE-0311: Task Local Values SE-0317: async let bindings Protect mutable state with Swift actors SE-0302: Sendable and @Sendable closures SE-0306: Actors SE-0313: Improved control over actor isolation SE-0316: Global actors Meet AsyncSequence SE-0298: Async/Await: Sequences SE-0310: Effectful Read-only Properties Swift concurrency: Behind the scenes SE-0296: Async/await SE-0300: Continuations for interfacing async tasks with synchronous code SE-0302: Sendable and @Sendable closures SE-0304: Structured concurrency SE-0306: Actors SE-0311: Task Local Values SE-0313: Improved control over actor isolation Swift concurrency: Update a sample app Use async/await with URLSession Discover concurrency in SwiftUI Bring Core Data concurrency to Swift and SwiftUI https://forums.swift.org/t/swift-concurrency-feedback-wanted/49336, https://discord.com/channels/291054398077927425/291054454793306112/851983218789318658 ( @shiz さん、情報ありがとうございました) ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Swift] DateComponentsFormatterやRelativeDateTimeFormatterを使って日付の差分を表示する

はじめに 先日[Swift]日付を取得し差分を出す方法と言う記事を書いたが、いやいやもっと標準ライブラリ使って簡単に取得できるよ!って事を知れたので試してみました。 環境 ・ iOS 13 以上 DateComponentsFormatter A formatter that creates string representations of quantities of time. →時間の量の文字列表現を作成するFormatterです。(公式より翻訳) 時間の表現を作成するなら普段用使用するFormatterと同じでは?と言う感じがしますが、とにかく使用してみる。 let time: TimeInterval = 300 let formatter = DateComponentsFormatter() formatter.unitsStyle = .full formatter.includesApproximationPhrase = true formatter.includesTimeRemainingPhrase = true formatter.allowedUnits = [.minute] let outputString = formatter.string(from: time)! print(outputString) おお!約って言うのが気になるがどうやらtimeにある秒数から残りを算出してくれている様子。 続いてtime=330にして下記の書き換えてみる。 formatter.allowedUnits = [.minute] 分と秒がしっかり取れていることが確認できます。 またincludesApproximationPhraseは結果の語句が不正確な時間値を反映しているかどうかを示すBool値なので formatter.includesApproximationPhraseをfalseにすると となります。(省略可能) includesTimeRemainingPhraseは出力文字列が残り時間を反映するかどうかを示すBool値なのでfalseにすると”残り”と言う文字が消えます。 let time: TimeInterval = 30000000 let formatter = DateComponentsFormatter() formatter.unitsStyle = .full formatter.includesApproximationPhrase = false formatter.includesTimeRemainingPhrase = false formatter.allowedUnits = [.day, .hour, .minute, .second] let outputString = formatter.string(from: time)! print(outputString) allowedUnitsに追加していく事でそれぞれの日時を取得する事ができます。また0の場合は表示されません。(今回は秒が0秒で表示されていない) RelativeDateTimeFormatter A formatter that creates locale-aware string representations of a relative date or time. →相対日付または時刻のロケール対応文字列表現を作成するFormatterです。(公式より翻訳) またiOS13より使用可能となっています。 localizedString(for: Date, relativeTo: Date) -> String を使用する事でフォーマッタのカレンダーを使用して、参照日から指定された日付までの日付間隔をフォーマットしてくれます。 struct RelativeDateTimeFormatterTraining: View { @State var timeText = "" var body: some View { VStack{ Button(action: { let targetDate = Date(timeIntervalSinceNow: 300) let nowDate = Date(timeIntervalSinceNow: 0) let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .abbreviated formatter.locale = Locale(identifier: "ja-JP") timeText = formatter.localizedString(for: targetDate, relativeTo: nowDate) }, label: { Text("Button") }) Text(timeText) } } } formatter.localizedString(for: targetDate, relativeTo: nowDate)で forの部分ではフォーマットする間隔の終了日を、relativeToにはフォーマットする間隔の開始日を入れる事で300秒分の差分を計算して自動で5分後と算出してString型で返してくれます。 その他にも func localizedString(from: DateComponents) -> String 指定された日付コンポーネントで表される相対時間をフォーマットします。 func localizedString(fromTimeInterval: TimeInterval) -> String フォーマッタのカレンダーを使用して、指定された時間間隔をフォーマットします。 func string(for: Any?) -> String? 現在の日付と時刻に相対的な日付のフォーマットされた文字列を作成します。 があります。 timeIntervalSinceとlocalizedString(fromTimeInterval: TimeInterval) -> Stringを使用する事でTwitterの様な”〜分前”の様な実装を容易に行うことができます。※ RelativeDateTimeFormatterは文法的に正しくない可能性があります。と公式で一文があるように、一番大きな単位以下の単位は基本切り捨てとなりますのでかなり情報落ちするケースも出てきます。 例えば VStack{ Button(action: { let dateFormat = DateFormatter() // 日時をString型で定義 let textLogDate = "2021-01-01 12:00:00" let textNowDate = "2021-01-01 12:05:40" // dateFormatを初期設定した"2021-01-01 12:00:00"と同じ形式になるように定義 dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss" // timeZoneを日本に dateFormat.timeZone = TimeZone(identifier: "Asia/Tokyo") // String型の日時をDate型に変換 let logDate = dateFormat.date(from: textLogDate) ?? Date() let nowDate = dateFormat.date(from: textNowDate) ?? Date() // timeIntervalSinceを使用すると差分を取得できる->nowDate-logDate let dateSubtraction: TimeInterval = logDate.timeIntervalSince(nowDate) let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .abbreviated formatter.locale = Locale(identifier: "ja-JP") timeText = formatter.localizedString(fromTimeInterval: dateSubtraction) print(timeText) }, label: { Text("Button") }) Text(timeText) } とした場合結果は となります。正確には5分40秒前ですが、今回の場合は一番大きな単位は分になりますので秒は切り捨てられます。 まとめ とにかくTwitterにある様な”〜分前”みたいな実装をする際にはRelativeDateTimeFormatterは本当に便利なものだが正確に取得したい場合はDateComponentsFormatterを使用した方が良さそうだと感じました。しかし標準ライブラリでここまで簡単に差分を取って、String型で返してくれるのは本当に便利なので今後は活用して行きたいです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Xcode13から追加されたXCTestの連続実行を試す。

テストを実行すると、成功したり、失敗したりする場合が・・・ こんなことがたまにあるかと思います。 手動で10回くらいテスト実行して問題ないか確認するかと思いますが、今回のアップデートによって楽にできるようになりました! 成功したり、失敗したりするサンプルテストコードを作成 Sample.swift import Foundation class Sample { func random() -> Int { let array = [1, 2, 3, 4, 5] return array.randomElement()! } } SampleTest.swift class SampleAppTests: XCTestCase { func testExample() throws { let sample = Sample() XCTAssertEqual(sample.random(), 1) } } 試してみる 繰り返したいクラスorメソッドを副クリックしRun "クラスorメソッド" Repeatedly...をクリック リピートの設定をする Stop After...テストを停止するタイミング Failure...失敗時 Success...成功時 Maximum Repetitions...とりあえず全部実行 実行結果 100回分の実行結果がまとめて表示される まとめ これは良いアップデートだ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

actorって結局なんなん?

Swiftのasync/awaitはわかりやすいアップデートだけど一緒に出てきたactorって結局何者なのか?というのを軽く調べてみたメモ 参考 Swift Proposal ざっくり概要 並列化の安全を保証できるデータ構造、並列処理のためのクラス 何がいいの? プロポーザルによるとactorの変更には以下のような制約がかかる 属するプロパティを変更する際はselfに対して呼び出す必要がある 他のactorインスタンス(用語がこれでいいのかは不明)に変更をかけようとするとコンパイラレベルでエラーが出る すなわち、並列処理で別々のスレッドが同じインスタンスを触って変更に矛盾が生じるみたいな事故を言語レベルで防ごうぜってことだと思います。 他の機能もたくさんありそうですが、大事なのはここの理解かなと感じました。 結論 並列処理でガンガン変更を加えるデータにはclassではなくactorを使っていきましょう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最近Swift書いている時に気をつけている基本的なこと

初めに 人によっては当たり前すぎとなるようなことかもしれませんが書き記しておきます。 今後自分が成長するにつれてどんどんこの記事が膨れ上がっていくかもしれません 共通化 これはまじで当たり前かもしれませんが、コードを何かたす際や修正する際に常に他の所でも使えるように共通化できないか考えます。 例えば最近だとAPIを叩いている時に薄暗い画面にローディングインジケーターを出すタスクをしたのですが、その場合はViewControllerに直接書くのではなく、Utilフォルダなどにローディングインジケーターをスタートさせたり、ストップさせたりするクラスやプロトコルを作っておくみたいな感じです。 他にも色々な画面で使いそうなalertだったりサインインやサインアップで使用するvalidationなど共通化できるものは様々です。 文字列をハードコードしない これも当たり前なのですが、rswiftなどを駆使して文字列は直接書き込まないようにしています。おそらく企業が運営しているアプリなどではほとんど文字列を直接書き込んだりしないでしょう。 ただrswiftなどを使わずに定数などを使って管理する文字列もあったりとそこはプロジェクトによりけりだと思います。 swiftの関数について理解しておく これは自分の最近あったことで言うと pushViewControllerなど画面遷移で使う関数のcompletion引数はdefaultでnilが設定されているので何もしない場合省略でいいのですが、そうとは知らずにnilを毎回わざわざ代入してしまってました。 恥ずかしい笑 このようにいつも使用している関数などもっと簡潔に書けるかもしれないなど気をつけて行こうと思いました。 後日増えていきます ここからはおそらく今後どんどん増えていきます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MessageKitをカスタマイズして日付のセルを表示する

やりたいこと いい感じのチャットのUIを作りたい scroll to bottomの動きや、伸縮するキーボードなど、大変そうなのでライブラリを使いたい MessageKitを使う 用意されている以外のUIコンポーネントを自作して使用したい 作りたいのは下のような画面で、アバターの描画、カスタムセルの作り方などにハマったので書いていきます 画像 トピック 基本的な使い方 アイコン部分の細かい調整 自作セルを使って日付のセルを追加する 基本的な使い方 メッセージ部分のカラー設定やマージンの設定については割愛します。 基本的な使い方については下記を参考にさせていただきました。 MessageKit - README.md MessageKitの使いかた(初歩) 【Swift】JSQMessagesViewController後継のMessageKitでのチャット画面の作成方法 アイコン部分の細かい調整 メッセージ部分の構造は画像(READMEより抜粋)のようになっていて、赤枠がviewの構成単位になっています。 各Viewを適宜レイアウト調整用のメソッドを呼んだり、Delegateメソッド経由で調整することでレイアウトを組んでいきます。 アイコン部分はAvaterViewと呼ばれており、他のview要素と同じ用に上記のアプローチで細かくレイアウトを設定していくことになります。 今回のアイコン部分の実装では以下を要件とします 自分が送るときはアイコンなし 相手から来たメッセージはアイコンあり(48 x 48、画像の上辺と吹き出しの上辺を合わせる) アイコンには角丸+影をつけたい 自分が送るときはアイコンなし layout.setMessageOutgoingAvatarSize(.zero) 上記のメソッドからアバターサイズを.zeroで設定します。 自分から送る(出ていく = Outgoing)アバターサイズを設定するメソッド、 という感じの命名になっていて、他のコンポーネントも同じノリです。 ちなみにlayoutプロパティは下記のように、 messageCollectionViewから取得できるcollectionViewLayoutから呼び出すことができます。 (messageCollectionViewとはMessagesViewControllerのクラスが保持しているプロパティです) class ChatViewController: MessagesViewController { override func viewDidLoad() { super.viewDidLoad() if let layout = self.messagesCollectionView.collectionViewLayout as? MessagesCollectionViewFlowLayout { // ここでlayoutを取得できる } } } 相手から来たメッセージはアイコンあり layout.setMessageIncomingAvatarSize(CGSize(width: 48, height: 48)) layout.setMessageIncomingAvatarPosition(AvatarPosition(vertical: .cellTop)) 同じノリで、相手から受け取った(送られてくる = Incoming)メッセージも上記のように設定できます。 AvatarPositionは水平方向、垂直方向に対してenumが定義されていて、 垂直方向のみによるinitと、水平方向と垂直方向によるinitの2種類提供されています。 アイコンには影をつけたい ChatViewController.swift // MARK: - MessagesLayoutDelegate // バブルの部分的な描画処理や、アクセサリービューやアバタービューの描画のときに呼ばれるDelegate // ここでaddSubViewすることでいい感じにレイアウトを組む extension ChatViewController: MessagesDisplayDelegate { func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) { // 初期化 avatarView.subviews.forEach { $0.removeFromSuperview() } // 相手のみアイコンを描画 if !self.isFromCurrentSender(message: message) { // subViewにシャドーをつけるためにfalseにしておく avatarView.clipsToBounds = false // avatarViewにUserIconViewをaddする let userIconView = UserIconView() let avaterSize = avatarView.frame.size avatarView.addSubview(userIconView) } } } AvatarViewの画像などの設定は下記のdelegateを通して設定します。 AvatarViewにはopen func set(avatar: Avatar)のメソッドが公開されており、 このメソッド経由で画像を設定するべきですが、 角丸 + 影を付ける場合にはシャドー付きのviewとcornerRadiusを設定したviewを重ねて表示する必要があるため、 今回はAvaterViewには画像を設定せず、 直接角丸 + 影付きの自作のUserIconViewをaddSubViewすることで実現しました。 また、描画の際に毎回呼ばれるので、セルの再利用で影が再描画され濃くなっていかないように、 初期化してremoveFromSuperview()をしていく必要があります。 自作セルを使って日付のセルを追加する 基本的なチャットに必要なコンポーネントはMessageKitで提供してくれており、 メッセージ用のview要素も、テキスト用の他に画像や絵文字、音声にも対応したUIが利用できるみたいです。 ですが、やはりどうしても賄えない部分は存在するので、その場合はカスタムセルを作ってなんとかします。 そしてその方法もしっかりドキュメントに記されていて、この方法の通りやればカスタムセルを実装できます。 流れは以下のとおりです 1. UICollectionViewCellを継承した、カスタムセルを作る 2. MessageSizeCalculatorを継承したサイズ計算用のクラスを作る 3. MessagesCollectionViewFlowLayoutを継承した、レイアウトを決定クラスを作る 4. viewDidLoadでMessagesCollectionViewFlowLayoutを使ったcollectionViewの初期化と、セルのregisterを行う 1. UICollectionViewCellを継承した、カスタムセルを作る DateCustomCell.swift final class DateCustomCell: UICollectionViewCell { func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView, date: String) { // 描画処理 } } 2. MessageSizeCalculatorを継承したサイズ計算用のクラスを作る DateMessageSizeCalculator.swift final class DateMessageSizeCalculator: MessageSizeCalculator { override func messageContainerSize(for message: MessageType) -> CGSize { return CGSize(width: 124, height: 24) } } 3. MessagesCollectionViewFlowLayoutを継承した、レイアウトを決定クラスを作る DateMessagesFlowLayout.swift final class DateMessagesFlowLayout: MessagesCollectionViewFlowLayout { lazy var customMessageSizeCalculator = DateMessageSizeCalculator(layout: self) override func cellSizeCalculatorForItem(at indexPath: IndexPath) -> CellSizeCalculator { let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) if case .custom = message.kind { return customMessageSizeCalculator // カスタムの時は独自のcalculatorを使用 } return super.cellSizeCalculatorForItem(at: indexPath) // その他の時は親のcalculatorを使用 } } この処理の中でMessageKindがカスタムのときに 2. で作成したサイズ計算用クラスを使用するように指定する 4. viewDidLoadでMessagesCollectionViewFlowLayoutを使ったcollectionViewの初期化と、セルのregisterを行う ChatViewController.swift final class ChatViewController: MessagesViewController { // MARK: Life cycle override func viewDidLoad() { super.viewDidLoad() self.messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: DateMessagesFlowLayout()) // カスタムセルの時にも処理できるlayoutクラスをセットする self.messagesCollectionView.register(DateCustomCell.self) // カスタムセルを登録 } } 最後に 既にご存知だった方もいるかとは思いますが、 スクラッチだとかなり大変なチャットUIの大部分を提供してくれてるMessageKitむちゃくちゃありがたいです。 若干リサーチしつつ実装する必要は出てくるものの、Repository内のExampleもしっかり作られていて参考にできますし、 2021年現在しっかりメンテされているので、チャットをこれから実装しようという方は検討してはいかがでしょうか。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSAppSyncClientの処理をRxでラップする

やったこと AWSAppSyncClientで頻出のfetch, mutate, subscribe処理をRxでラップして、 SingleやObservableなどのオペレータで扱えるようにしました。 AWSAppSyncClientでは内部でApolloClientをラップしているので、 AWSサービスなどを使わずにApolloをGraphQLしてRxで扱うケースと同じようなコードになるかなと思います。 コード AWSAppSyncClient+Rx.swift import Foundation import AWSAppSync import RxSwift import SwiftyBeaver let log = SwiftyBeaver.self enum AppSyncError: Error { case gqlErrors([GraphQLError]) case noData case unknowned } extension AWSAppSyncClient: ReactiveCompatible {} extension Reactive where Base: AWSAppSyncClient { public func fetch<Query: GraphQLQuery>( query: Query, cachePolicy: CachePolicy = .returnCacheDataElseFetch, queue: DispatchQueue = DispatchQueue.main ) -> Single<Query.Data> { return Single.create { [weak base] observer in log.debug("query did called - query: \(query)") let cancellable = base?.fetch(query: query, cachePolicy: cachePolicy, queue: queue) {(result, error) in if let error = error { log.error("client connection error - error: \(error)") observer(.error(error)) } switch result { case .none: log.error("fetched result is nil") observer(.error(AppSyncError.noData)) case .some(let result): if let errors = result.errors { log.error("GraphQL fetch error - errors: \(errors.map { $0.description } )") observer(.error(AppSyncError.gqlErrors(errors))) } else if let data = result.data { observer(.success(data)) } else { log.error("Unknowned error. result and error, both values ​​are nil") observer(.error(AppSyncError.unknowned)) } } } return Disposables.create { cancellable?.cancel() } } } public func perform<Mutation: GraphQLMutation>( mutation: Mutation, queue: DispatchQueue = .main ) -> Single<Mutation.Data> { return Single.create { [weak base] observer in log.debug("mutation did called - mutation: \(mutation)") let cancellable = base?.perform(mutation: mutation, queue: queue, optimisticUpdate: nil, conflictResolutionBlock: nil, resultHandler: { (result, error) in if let error = error { log.error("client connection error - error: \(error)") observer(.error(error)) } switch result { case .none: assertionFailure("Unexpected error - in case result is nil, should return error before evaluating result value") observer(.error(AppSyncError.resultIsNil)) // 一応エラーを返しておく case .some(let result): if let errors = result.errors { log.error("GraphQL perform error - errors: \(errors.map { $0.description } )") observer(.error(AppSyncError.gqlErrors(errors))) } else if let data = result.data { observer(.success(data)) } else { log.error("perform unknowned error. result and error, both values ​​are nil") observer(.error(AppSyncError.unknowned)) } } }) return Disposables.create { cancellable?.cancel() } } } public func subscribe<Subscription: GraphQLSubscription>( subscription: Subscription, queue: DispatchQueue = .main ) -> Observable<Subscription.Data> { return Observable.create { [weak base] observer in log.debug("subscription did called - subscription: \(subscription)") var cancellable: Cancellable? do { cancellable = try base?.subscribe(subscription: subscription, queue: queue, statusChangeHandler: nil, resultHandler: { (result, _, error) in if let error = error { log.error("client connection error - error: \(error)") observer.onError(error) } switch result { case .none: assertionFailure("Unexpected error - in case result is nil, should return error before evaluating result value") observer.onError(AppSyncError.resultIsNil) // 一応エラーを返しておく case .some(let result): if let data = result.data { log.debug("subscribed data: - \(data)") observer.onNext(data) } else if let errors = result.errors { log.error("GraphQL subscribe error - errors: \(errors.map { $0.description } )") observer.onError(AppSyncError.gqlErrors(errors)) } } }) } catch { log.error("subscribe configurations error") observer.onError(AppSyncError.unknowned) // base?.subscribe内でthrowされるがどんなerrorが投げられているのかは不明 cancellable?.cancel() } return Disposables.create { cancellable?.cancel() } } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WWDC 2021基調講演をもとにしたメモ(新しいフレームワークの紹介)

これは、WWDC基調講演の公開映像をもとにしたメモであり、iOS、iPadOSおよびMacOSの新たな変更点を理解するのに役立ちます。 ※一般公開されているWWDC Keynoteの動画と公開Session/Documentationページだけを使ってこの記事を執筆しました。 https://www.apple.com/apple-events/june-2021/ https://developer.apple.com/wwdc21/sessions/ https://developer.apple.com/documentation/ https://developer.apple.com/documentation/technologies?changes=latest_minor ここにはスクリーンショットは含めません。 この他にもたくさんのセッションや動画があります。これまで紹介したのはその一部のみです。すべての動画についてはこのページをチェックしてください。 デベロッパー関連の機能 フレームワーク 写真を撮影して3D ARオブジェクトの作成が可能になりました。 Documentation -> Capturing Photographs for RealityKit Object Capture Documentation -> Creating 3D Objects from Photographs Sample code -> Taking Pictures for 3D Object Capture Sample code -> Creating a Photogrammetry Command-Line App Xcodeクラウド クラウドサーバーを利用してアプリをビルドし、チーム全体でビルドの結果を確認できます(クラウド上でテストを実行できて、その結果がXcode上で表示にされます)。 また、TestFlightを介してアプリをテスターに自動配布することも可能です。 Session -> Customize your advanced Xcode Cloud workflows(公開予定) Documentation -> https://developer.apple.com/documentation/Xcode/Xcode-Cloud ShazamKit(音楽認識) Documentation -> https://developer.apple.com/documentation/shazamkit フェイスタイム通話とアクティビティ共有(SharePlay) アプリはFaceTimeグループでデータを送信できます。 Session -> Coordinate media experiences with Group Activities(公開予定) Session -> Build custom experiences with Group Activities(公開予定) Session -> Design for Group Activities(公開予定) Documentation -> https://developer.apple.com/documentation/GroupActivities 空間オーディオ 新しいサウンド分析フレームワークで、音を検知(人間の声、楽器、動物、その他300種以上の音) Documentation -> https://developer.apple.com/documentation/soundanalysis iOSシステムでSafariウェブ拡張機能がご利用いただけます。 Session -> Explore Safari Web Extension improvements(公開予定) Nearby Interaction フレームワークは、 U1チップを搭載したiPhone用のUWBサード​パーティ製アクセサリと連動できるようになりました。 これにより、携帯とアクセサリ間の正確な相対位置を取得できます。 Session -> Explore UWB-based car keys(公開予定) Documentation -> https://developer.apple.com/documentation/nearbyinteraction/ninearbyaccessoryconfiguration スクリーンタイムAPI Documentation -> https://developer.apple.com/documentation/ManagedSettings 空間オーディオの統合 / 動的な3Dオブジェクトのテクスチャ 通知のための新しいAPI(マインドセット/モード) アプリは、システムの通知モードを確認することができます。(個人、仕事モード...) Session -> Send communication and Time Sensitive notifications(公開予定) iCloud Keychainで認証コードを生成して、より安全なサインイン体験を Session -> Secure login with iCloud Keychain verification codes(公開予定) (関連)パスワードなしでユーザーを登録して認証します。 Documentation -> Public-Private Key Authentication ライブテキスト テキストの写真を撮り、そのテキストを選択できます。すでにライブラリにある写真にも対応しています。(ジェスチャーで写真の中のテキストを選択するだけです)。 iCloud+ プライベートリレー。メールを隠す。ランダムでユニークなメールアドレスをシェアできます。(必要なだけ)。ホームキットの安全なビデオ。 Matter Matterと呼ばれるスマートホームデバイス用の新たな通信プロトコルがあり、AppleのHomekitに対応しています。 Session -> Add support for Matter in your smart home app(公開予定) メールアプリの拡張機能を構築できるようになりました(コンテンツブロッカー、メッセージコンポーザー、メッセージカスタムアクション、メール暗号化など) Session -> Build Mail app extensions(公開予定) Swift 並行プログラミング Session -> Discover concurrency in SwiftUI(公開予定) Session -> Meet AsyncSequence(公開予定) Session -> Swift concurrency: Update a sample app(公開予定) Session -> Use async/await with URLSession(公開予定) Session -> Bring Core Data concurrency to Swift and SwiftUI(公開予定) Documentation -> https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html App Store 複数の商品ページを作成(異なるアプリアイコン、スクリーンショット) App Storeでアプリ内イベントを特集できるようになりました。 iPadOS iPadウィジェット用の特大サイズhttps://developer.apple.com/documentation/widgetkit/widgetfamily/systemextralarge iPad OS クイックノート Appleペンシルを使って画面(右下)の角からスワイプしてから、ノートを取ってください。ノートは、それを取ったアプリへリンクされます(また、同じアプリを開いたときにハイライトされます) Session -> Adopt Quick Note(公開予定) iPad版Swift Playground: SwiftUIコンポーネント。 iPadでアプリを作成。 iPadで作成したアプリをそのまま直接App Storeに提出することが可能。 MacOS Macシステムでショートカットアプリがご利用いただけます。 他の機能: - 地域に基づく通知 - WatchOSのNearby Interactionフレームワーク - UI試験の強化 - メモリーグラフ - スマート音量 SwiftUIを使って検索ビューを追加する方法を学ぶ Apple Watch 常時表示 アプリケーションが常にApple Watchの画面に表示されるようにする Documentation -> https://developer.apple.com/documentation/watchkit/designing_your_app_for_the_always_on_state 一部の機能は既に上で触れられておりますので、次のいくつかのセクションでは取り上げません。 iOS フェイスタイム通話 グループ通話での空間オーディオ 人の発言だけが聞こえるように、雑音を除去 参加者全員を一つの画面で見ることができるグリッド表示 ポートレートモードへ切り替え、背景をぼかす フェイスタイムリンク / フェイスタイム通話をスケジュール(イベントをフェイスタイム通話にする) その他のシステムをお使いの場合(アンドロイドおよびウィンドウズのデバイス)、ウェブ上でフェイスタイム通話に参加できます(エンドツーエンド暗号化も) フェイスタイム通話とアクティビティ共有(映画を見たり、音楽を聴いたり、など)(SharePlay) 共有 iMessageを使用して共有したコンテンツは、さまざまなシステムアプリケーションで表示できます。 フォーカスモード: 通知要約 お友達は、いつあなたがiMessageアプリで「Do Not Disturb」をオンにしたかを知ることができます。 デバイスを現在のマインドセット/モード(個人モード、仕事モード...)に合わせます。 仕事中であれば、仕事用アプリケーションからの通知だけを受け取ることができます。 インテリジェンス: ビジュアル検索(犬のパン、花の種類、本、ペット、目印)。 スポットライトで写真を検索します。写真の中にあるもの、場所、テキストで検索します。 連絡先の豊富な検索結果(電話をかけるアクション、関連するすべて、Find My、カレンダー、メール、メモ、ファイル)。 Spotlightのテレビ番組、映画の結果。 Photos Memories:Apple Musicの曲を使用できます。思い出のペースに合わせた音楽。 Memory Mixesでいろいろなミックスを試してみましょう。 ウォレット: アパート、家、ホテルの部屋(対応するホテル)の解錠 ID(運転免許証など)をウォレットに(現在はアメリカでのみ利用可能) 天気: 美しい新デザイン。 気象パターンに合わせて背景を追加 Appleマップ: 地球を見る 新しいマップを更に色々な国に。 道路の色や標高、カスタムデザインされたランドマークなど、新しい情報が追加されています。(バイクレーン、横断歩道、高速道路のインターチェンジなどを3Dで表現します) グロー機能付きマップのナイトタイムモード トランジット。エリア内の建物をスキャンし、ARで方向を生成。 AirPods: AirPodsがiPhoneから離れたときに作動する置き忘れ防止アラート。 「探す」アプリのネットワークでAirPodsの位置を探せるように。 健康アプリ: 歩行の安定性。スマホでその人の転倒リスクを評価できるようになりました。 システムで健康データのトレンドを生成できるようになりました。 健康アプリで記録した健康データを医療機関と共有しましょう。 さらに、健康データを家族と共有することもできます。 iPad: ウィジェットをホーム画面に配置。 iPad アプリライブラリ マルチタスキング : iPad 画面上部に表示される新しいコントロールでスプリットビューをすばやく作成。 新しいシェルフビューで異なるウィンドウ間の切り替えが手軽に。 新しいキーボードショートカットセットでマルチタスキングを実行。 メモアプリ メモアプリの共有ノートで誰かの名前に言及。 メモアプリのアクティビティ表示で、最新の変更を見る。 翻訳: この度、iPadでご利用いただけるようになりました。 プライバシー: メールのプライバシー保護: IP アドレスを隠します。 Safari: ウェブサイト トラッカーから IP アドレスを隠します。 アプリのプライバシー レポート: アプリがユーザーの位置、写真、カメラ、連絡先、その他の情報にアクセスする頻度 (過去 7 日間) の概要を表示します。 アプリが接続を確立したすべてのサードパーティ ドメインを表示します。 Apple Watch: 睡眠トラッキング(睡眠中の呼吸数)を改善。 ワークアウトの種類を新たに追加。 ポートレート写真(特殊効果付き)を文字盤に。 Apple Watchの写真アプリで写真のハイライト(写真共有機能を含む)を表示できるように。 複数のタイマー、身体の項目、およびその他機能。 Apple TV: SiriやHomePodにApple TVで番組を再生してもらう みんなの興味に合わせて映画を提案する。 Apple TVのスピーカーとしてHomePod miniを選択する。 HomePod miniでSiriに個人的なリクエストをする。 他のデバイス(サーモスタットなど)にSiriを使う(リクエストは自宅のHomePodにルーティングされます) カメラが荷物を検知する(荷物が配達された時のリマインダー)。 すべてのカメラの映像をApple TVで表示する MacOS: 新しいMacOSの名は「Monterey」 新しいフェイスタイム機能(上に記載の通り) コントロール機能 マウス、キーボード、またはトラックパッド一つでMacとiPadをコントロール MacBookのタッチパッドカーソルを直接画面の端まで動かして、iPadへ移動させることが可能(たとえば、iPadをMacBookの右隣りに置き、カーソルを右へ動かすと、iPadにカーソルが現れます)。 ドラッグとドロップも機能します。 別のMacコンピューター上でも機能します。 3台以上のデバイスでも機能します(オブジェクトを複数のデバイス間で移動させることが可能)。 AirPlayを使ってあなたのコンテンツをMacで再生できます。 サファリでそれぞれ異なったグループにタブを分けることが可能です(iCloudによって同期) すべての新機能についてはこちらをご覧ください。 https://www.apple.com/jp/newsroom/ すばらしいセッションやビデオがたくさんあります。このメモを参考に、すばやくナビゲートしていただければ幸いです。 Twitter ツイッター @MszPro 私の公開されているQiita記事をカテゴリー別にご覧いただけます。 今後ともよろしくお願い致します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WWDC 2021基調講演の公開映像をもとにしたメモ

これは、WWDC基調講演の公開映像をもとにしたメモであり、iOS、iPadOSおよびMacOSの新たな変更点を理解するのに役立ちます。 ※一般公開されているWWDC Keynoteの動画と公開Session/Documentationページだけを使ってこの記事を執筆しました。 https://www.apple.com/apple-events/june-2021/ https://developer.apple.com/wwdc21/sessions/ https://developer.apple.com/documentation/ https://developer.apple.com/documentation/technologies?changes=latest_minor ここにはスクリーンショットは含めません。 セッションページへのリンクがわかりましたら、それを追加して記事を更新します。 この他にもたくさんのセッションや動画があります。これまで紹介したのはその一部のみです。すべての動画についてはこのページをチェックしてください。 https://developer.apple.com/wwdc21/sessions/ デベロッパー関連の機能 フレームワーク 写真を撮影して3D ARオブジェクトの作成が可能になりました。 Session -> Create 3D models with Object Capture Documentation -> Capturing Photographs for RealityKit Object Capture Documentation -> Creating 3D Objects from Photographs Sample code -> Taking Pictures for 3D Object Capture Sample code -> Creating a Photogrammetry Command-Line App Xcodeクラウド クラウドサーバーを利用してアプリをビルドし、チーム全体でビルドの結果を確認できます(クラウド上でテストを実行できて、その結果がXcode上で表示にされます)。 また、TestFlightを介してアプリをテスターに自動配布することも可能です。 Session -> Explore Xcode Cloud workflows Session -> Customize your advanced Xcode Cloud workflows Documentation -> https://developer.apple.com/documentation/Xcode/Xcode-Cloud ShazamKit(音楽認識) Session -> Create custom audio experiences with ShazamKit Session -> Explore ShazamKit Documentation -> https://developer.apple.com/documentation/shazamkit フェイスタイム通話とアクティビティ共有(SharePlay) アプリはFaceTimeグループでデータを送信できます。 Session -> Coordinate media experiences with Group Activities Session -> Build custom experiences with Group Activities Session -> Design for Group Activities Documentation -> https://developer.apple.com/documentation/GroupActivities 空間オーディオ Session -> Immerse your app in spatial audio 新しいサウンド分析フレームワークで、音を検知(人間の声、楽器、動物、その他300種以上の音) Session -> Discover built-in sound classification in SoundAnalysis Documentation -> https://developer.apple.com/documentation/soundanalysis iOSシステムでSafariウェブ拡張機能がご利用いただけます。 Session -> Explore Safari Web Extension improvements Nearby Interaction フレームワークは、 U1チップを搭載したiPhone用のUWBサード​パーティ製アクセサリと連動できるようになりました。 これにより、携帯とアクセサリ間の正確な相対位置を取得できます。 Session -> Explore Nearby Interaction with third-party accessories Session -> Explore UWB-based car keys スクリーンタイムAPI Session -> Meet the Screen Time API Documentation -> https://developer.apple.com/documentation/ManagedSettings 空間オーディオの統合 / 動的な3Dオブジェクトのテクスチャ Session -> Dive into RealityKit 2 通知のための新しいAPI(マインドセット/モード) アプリは、システムの通知モードを確認することができます。(個人、仕事モード...) Session -> Send communication and Time Sensitive notifications iCloud Keychainで認証コードを生成して、より安全なサインイン体験を Session -> Secure login with iCloud Keychain verification codes ライブテキスト テキストの写真を撮り、そのテキストを選択できます。すでにライブラリにある写真にも対応しています。(ジェスチャーで写真の中のテキストを選択するだけです)。 Session -> Use the camera for keyboard input in your app iCloud+ プライベートリレー。メールを隠す。ランダムでユニークなメールアドレスをシェアできます。(必要なだけ)。ホームキットの安全なビデオ。 Session -> Get ready for iCloud Private Relay Matter Matterと呼ばれるスマートホームデバイス用の新たな通信プロトコルがあり、AppleのHomekitに対応しています。 Session -> Add support for Matter in your smart home app メールアプリの拡張機能を構築できるようになりました(コンテンツブロッカー、メッセージコンポーザー、メッセージカスタムアクション、メール暗号化など) Session -> Build Mail app extensions Swift 並行プログラミング Session -> Explore structured concurrency in Swift Session -> Meet async/await in Swift Session -> Protect mutable state with Swift actors Session -> Discover concurrency in SwiftUI Session -> Meet AsyncSequence Session -> Swift concurrency: Update a sample app Session -> Use async/await with URLSession Session -> Bring Core Data concurrency to Swift and SwiftUI Documentation -> https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html App Store 複数の商品ページを作成(異なるアプリアイコン、スクリーンショット) App Storeでアプリ内イベントを特集できるようになりました。 Session -> Meet in-app events on the App Store iPadOS iPadウィジェット用の特大サイズ iPad OS クイックノート Appleペンシルを使って画面(右下)の角からスワイプしてから、ノートを取ってください。ノートは、それを取ったアプリへリンクされます(また、同じアプリを開いたときにハイライトされます) Session -> Adopt Quick Note iPad版Swift Playground: SwiftUIコンポーネント。 iPadでアプリを作成。 iPadで作成したアプリをそのまま直接App Storeに提出することが可能。 MacOS Macシステムでショートカットアプリがご利用いただけます。 Session -> Meet Shortcuts for macOS 他の機能: - 共有の再生コントロール - 地域ベースの通知 - WatchOSのNearby Interactionフレームワーク - UI試験の強化 - メモリーグラフ - スマート音量 Apple Watch 常時表示 アプリケーションが常にApple Watchの画面に表示されるようにする Documentation -> https://developer.apple.com/documentation/watchkit/designing_your_app_for_the_always_on_state 一部の機能は既に上で触れられておりますので、次のいくつかのセクションでは取り上げません。 iOS フェイスタイム通話 グループ通話での空間オーディオ 人の発言だけが聞こえるように、雑音を除去 参加者全員を一つの画面で見ることができるグリッド表示 ポートレートモードへ切り替え、背景をぼかす フェイスタイムリンク / フェイスタイム通話をスケジュール(イベントをフェイスタイム通話にする) その他のシステムをお使いの場合(アンドロイドおよびウィンドウズのデバイス)、ウェブ上でフェイスタイム通話に参加できます(エンドツーエンド暗号化も) フェイスタイム通話とアクティビティ共有(映画を見たり、音楽を聴いたり、など)(SharePlay) 共有 iMessageを使用して共有したコンテンツは、さまざまなシステムアプリケーションで表示できます。 フォーカスモード: 通知要約 お友達は、いつあなたがiMessageアプリで「Do Not Disturb」をオンにしたかを知ることができます。 デバイスを現在のマインドセット/モード(個人モード、仕事モード...)に合わせます。 仕事中であれば、仕事用アプリケーションからの通知だけを受け取ることができます。 インテリジェンス: ビジュアル検索(犬のパン、花の種類、本、ペット、目印)。 スポットライトで写真を検索します。写真の中にあるもの、場所、テキストで検索します。 連絡先の豊富な検索結果(電話をかけるアクション、関連するすべて、Find My、カレンダー、メール、メモ、ファイル)。 Spotlightのテレビ番組、映画の結果。 Photos Memories:Apple Musicの曲を使用できます。思い出のペースに合わせた音楽。 Memory Mixesでいろいろなミックスを試してみましょう。 ウォレット: アパート、家、ホテルの部屋(対応するホテル)の解錠 政府の身分証明書をウォレットに。(現在はアメリカでのみ利用可能) 天気: 美しい新デザイン。 気象パターンに合わせて背景を追加 Appleマップ: 地球を見る 新しいマップを更に色々な国に。 道路の色や標高、カスタムデザインされたランドマークなど、新しい情報が追加されています。(バイクレーン、横断歩道、高速道路のインターチェンジなどを3Dで表現します) グロー機能付きマップのナイトタイムモード トランジット。エリア内の建物をスキャンし、ARで方向を生成。 AirPods: AirPodsがiPhoneから離れたときに作動する置き忘れ防止アラート。 「探す」アプリのネットワークでAirPodsの位置を探せるように。 健康アプリ: 歩行の安定性。スマホでその人の転倒リスクを評価できるようになりました。 システムで健康データのトレンドを生成できるようになりました。 健康アプリで記録した健康データを医療機関と共有しましょう。 さらに、健康データを家族と共有することもできます。 iPad: ウィジェットをホーム画面に配置。 iPad アプリライブラリ マルチタスキング : iPad 画面上部に表示される新しいコントロールでスプリットビューをすばやく作成。 新しいシェルフビューで異なるウィンドウ間の切り替えが手軽に。 新しいキーボードショートカットセットでマルチタスキングを実行。 メモアプリ メモアプリの共有ノートで誰かの名前に言及。 メモアプリのアクティビティ表示で、最新の変更を見る。 翻訳: この度、iPadでご利用いただけるようになりました。 プライバシー: メールのプライバシー保護: IP アドレスを隠します。 Safari: ウェブサイト トラッカーから IP アドレスを隠します。 アプリのプライバシー レポート: アプリがユーザーの位置、写真、カメラ、連絡先、その他の情報にアクセスする頻度 (過去 7 日間) の概要を表示します。 アプリが接続を確立したすべてのサードパーティ ドメインを表示します。 Apple Watch: 睡眠トラッキング(睡眠中の呼吸数)を改善。 ワークアウトの種類を新たに追加。 ポートレート写真(特殊効果付き)を文字盤に。 Apple Watchの写真アプリで写真のハイライト(写真共有機能を含む)を表示できるように。 複数のタイマー、身体の項目、およびその他機能。 Apple TV: SiriやHomePodにApple TVで番組を再生してもらう みんなの興味に合わせて映画を提案する。 Apple TVのスピーカーとしてHomePod miniを選択する。 HomePod miniでSiriに個人的なリクエストをする。 他のデバイス(サーモスタットなど)にSiriを使う(リクエストは自宅のHomePodにルーティングされます) カメラが荷物を検知する(荷物が配達された時のリマインダー)。 すべてのカメラの映像をApple TVで表示する MacOS: 新しいMacOSの名は「Monterey」 新しいフェイスタイム機能(上に記載の通り) コントロール機能 マウス、キーボード、またはトラックパッド一つでMacとiPadをコントロール MacBookのタッチパッドカーソルを直接画面の端まで動かして、iPadへ移動させることが可能(たとえば、iPadをMacBookの右隣りに置き、カーソルを右へ動かすと、iPadにカーソルが現れます)。 ドラッグとドロップも機能します。 別のMacコンピューター上でも機能します。 3台以上のデバイスでも機能します(オブジェクトを複数のデバイス間で移動させることが可能)。 AirPlayを使ってあなたのコンテンツをMacで再生できます。 サファリでそれぞれ異なったグループにタブを分けることが可能です(iCloudによって同期) すべての新機能についてはこちらをご覧ください。 https://www.apple.com/jp/newsroom/ すばらしいセッションやビデオがたくさんあります。このメモを参考に、すばやくナビゲートしていただければ幸いです。 Twitter ツイッター @MszPro 私の公開されているQiita記事をカテゴリー別にご覧いただけます。 今後ともよろしくお願い致します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む