20210609のSwiftに関する記事は7件です。

プロパティについてのまとめ(備忘録)

プロパティについてのまとめ ・プロパティ : 型に紐づいた値のこと ・プロパティの分類 ①var,let ②ストアドプロパティ,コンピューテッドプロパティ ③インスタンスプロパティ,スタティックプロパティ,クラスプロパティ ①var,let var : 再代入可 let : 再代入不可 ②ストアドプロパティ,コンピューテッドプロパティ ・ストアドプロパティ(値を保持するプロパティ。プロパティオブザーバをもつ。) struct Bird { var status = "卵" { willSet { print("私は\(status)です。次は\(newValue)になります。") } didSet { print("私は\(status)になりました。前は\(oldValue)です。") } } func greet() { print("私は\(status)です。") } } var bird = Bird() bird.greet() //私は卵です。 bird.status = "鳥" bird.greet() // 私は卵です。次は鳥になります。私は鳥になりました。前は卵です。私は鳥です。 ・コンピューテッドプロパティ(値を保持せずに算出するプロパティ) struct Human { var gender = "男" var name : String { get { if gender == "男" { return "太郎" } else { return "花子" } } set { if newValue == "太郎" { gender = "男" } else { gender = "女" } } } func person() { print("私は\(name)です。性別は\(gender)です。") } } var human = Human() human.person() // 私は太郎です。性別は男です。 human.gender = "女" human.person() // 私は花子です。性別は女です。 ③インスタンスプロパティ,スタティックプロパティ,クラスプロパティ ①インスタンスプロパティ(型のインスタンスに紐づくプロパティ) struct Human { var gender = "男" } var human = Human() print(human.name) //山田太郎 ②スタティックプロパティ・クラスプロパティ(型そのものに紐づく) ・スタティックプロパティについて struct Animal1 { //スタティックプロパティはストアドプロパティ・コンピューテッドプロパティとして利用できる。オーバーライドはできない。 static var weight : Int { return 40 } static var height: Int = 180 } print(Animal1.weight) // 40 print(Animal1.height) // 180 ・クラスプロパティについて //クラスプロパティはコンピューテッドプロパティとして利用しなければならない。オーバーライド可能。 class Animal2 { class var name : String { return "Dog" } } class Animal3: Animal2 { override class var name: String { return "Cat" } } print(Animal2.name) //Dog print(Animal3.name) //Cat
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】アラートのテンプレート

テンプレート struct AlertUtils { private static var alertController = UIAlertController() static func alert(title: String, message: String, view: UIViewController) { alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) view.present(alertController, animated: true) } } 使用方法 AlertUtils.alert(title: "タイトル", message: "メッセージ", view: ViewController()) 終わりに コード貼り付けただけですみません。(特に説明することがない・・・)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iOSのリセマラを防ぐ

要約 DeviceCheckを使ってリセマラを防ぎます 概要 リセマラ(リセットマラソン)を防ぐために、DeviceCheckを使って端末チェックを行います。 ここでいうリセマラとは、アプリをアンインストール/インストールを繰り返して、初回限定の利益を何度も受ける行為を指します。 端末チェックの結果、「この端末ではまだ初回限定の利益を受けていない」と判断できた場合、初回限定の特典を与えます。 DeviceCheckを使った端末チェックはiOSアプリ単体で完結するわけではなく、さまざまな手順が必要になります。 また、仕組み上、中古端末や譲渡を受けた端末では初回限定の判断はできないかと思われます。 アプリの流れ iOSアプリがDeviceCheckを利用して、トークンを発行する iOSアプリは、サーバーに対してトークンを送信する サーバーは、JWTを生成して、トークンとともにApple APIへリクエストを送る サーバーは、Apple APIの結果を受け取り、iOSアプリへ返す サーバーのレスポンスを元に、初回限定の利益を与える/与えない 端末チェックの手順 p8編 iOS Developer centerで、Keysを作成することができる権限のアカウントが必要です。 iOS Developer centerでDeviceCheck用のP8ファイルを作成する必要があります。 下記は手順の一例です。iOS Developer centerに変更が行われている場合は適宜読み替えてください。 Certificates, Identifiers & Profiles の Keysを選択 Create Keyを押下 Register a New Keyで、Key Nameを任意、DeviceCheckをチェック Downloadで、p8ファイルをダウンロードする。これはサーバーサイドで利用します。 サーバ編 先ほどダウンロードしたp8ファイルが必要です。 サーバーサイドでは、p8ファイル、iOS Developer centerで生成したKeyのKey ID、iOS Developer centerのチームIDが必要になり、組み合わせてJWTを生成し、iOSアプリからデバイストークン受信時、Authorizationヘッダーに Bearer <GeneratedJWT> を付与して、bodyにPayloadを付与してAppleのAPIへリクエストを行います。 APIには query_two_bits と update_two_bits があり、まず query_two_bits を確認して、200 Bit State Not Foundであれば初回限定とみなせます。 必要であればこの時点でupdate_two_bitsで初回特典を付与済みとすればよいでしょう。 AppleのDevice check用APIについての公式はこちらです。 JWTを生成するライブラリは各種環境で選定してください。 以下はJWT生成時のHEADERとPAYLOADの例です。 HEADER例 { "alg": "ES256", "kid": "(iOS Developer centerで生成したKeyのKey ID)" } PAYLOAD例 { "iss": "(iOS Developer centerのチームID)", "iat": 1573712797, "exp": 1573716397 } bodyの例 { "device_token": "Base 64エンコードされた、iOSから送られてきたデバイストークン", "transaction_id": "C94E26BD-714B-4D3F-8733-E86A790C0F8D", "timestamp": 1573707063000 } iOSアプリ編 DeviceCheckは実機じゃないと動作しません。プロビジョニングもDeviceCheckのp8ファイルを作ったチームIDと等しい必要があります。 iOSアプリでは DCDevice.current.generateToken を実行し、生成したトークンをサーバーへ送信し、その結果を受け取って初回限定の特典を与えることになります。 import DeviceCheck DCDevice.current.generateToken { (deviceToken, error) in // TODO: サーバーにdeviceTokenを送信して、レスポンスを受け取って処理をする } iOS単体での実機デバッグ DeviceCheckは、サーバーと連携して使うことが前提のものですが、iOSアプリ単体でテストとして使いたい場合、CupertinoJWT を使ってApple APIとの通信が可能です。 下記はquery_two_bitsの例です。 あくまでテストとしてお使いください。 import DeviceCheck import CupertinoJWT DCDevice.current.generateToken { (deviceToken, error) in //p8ファイルの中身 let p8 = """ -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- """ let keyID = "iOS Developer centerで生成したKeyのKey ID" let teamID = "iOS Developer centerのチームID" let jwt = JWT(keyID: keyID, teamID: teamID, issueDate: Date(), expireDuration: 60 * 60) do { let generatedJWT = try jwt.sign(with: p8) let url = URL(string: "https://api.development.devicecheck.apple.com/v1/query_two_bits")! var request = URLRequest(url: url) request.httpMethod = "POST" let deviceTokenString = deviceToken!.base64EncodedString(options: Data.Base64EncodingOptions.init()) let timestamp:Int = Int(Date().timeIntervalSince1970) let transaction = UUID().uuidString let requestBody = """ { "device_token" : "\(deviceTokenString)", "transaction_id" : "\(transaction)", "timestamp" : \(timestamp)000 } """ let data = requestBody.data(using: .utf8) request.addValue("Bearer \(generatedJWT)", forHTTPHeaderField: "Authorization") request.httpBody = data let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // NOTE:Apple Device Check APIの結果を判断して初回限定の付与などを判定 } task.resume() } catch { // Handle error } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WWDC 2021 基調講演 まとめ

基調講演の内容をスクショと共に要約しました iOS 15 FaceTime 立体音響で喋る人の方角から聞こえるようになる ノイズキャンセリング機能で声を聞きやすくできる Meetのようにグリッド表示が可能に ポートレートで背景をボカせるようになる シェアリンクを生成してAppleデバイス以外からもブラウザからFaceTimeが可能に シェアプレイで音楽や映画を一緒に楽しめる シェアプレイはAppleTVに接続していながらでも可能 画面共有もできるように Messages あなたと共有でシェアされたリンクや写真、音楽などが各アプリでリコメンドされるようになる 通知 通知のデザインが見やすくなった 通知を要約して見やすくする新機能 集中モードが追加され、通知がくるタイミングを調整できるように ライブテキスト カメラや画像から文字を認識して、コピーしたり検索、翻訳ができるようになる(*日本語未対応) ビジュアルルックアップ つまりはGoogle Lensと同じことできる Spotlight 検索機能が強化されて、ライブテキストを使用して写真が検索できたり、さまざまな情報が検索できるようになる 写真 AppleMusicの音楽に合わせてシャレオツなメモリーを自動作成してくれるようになる Wallet 車や家の鍵、ホテルの鍵まで追加できるようになる 身分証明証も追加でき、保安検査場などで使えるように(アメリカのみ) 天気 デザインが新しくなってより詳細な天気情報が確認しやすくなる マップ 3D表示の地図がオシャレに 経路案内時に道路の詳細な情報がわかるようになる(*日本未対応) 将来の自動運転に向けての準備? 交通機関の検索も簡単に ARで道案内も可能に(Google Mapのライブビューと同じ) AirPods 会話の強調機能でお話ししやすくなる 通知のアナウンス機能が強化 AirPods Pro, AirPods MaxもAirTagと同じ探す機能を搭載 AppleTVでも空間オーディオが使えるようになる iPadOS 15 ウィジェット iPadでもウィジェットが使えるように iPad用の大きなサイズのウィジェット爆誕 Appライブラリ Appライブラリが使えるように                   マルチタスク 新しいコントロールメニューが表示されるように 画面中央に表示することができるように Macの仮想デスクトップ的なことが可能に App SwitcherからSplitViewが可能に メモ タグ機能が追加 クイックメモですぐにメモすることが可能に 開いているアプリのリンクも取得可能 メモしたリンクを表示しているとメモが表示される 翻訳 iPadでも使用可能に あらゆる場所で翻訳が使用できる SwiftPlaygrounds SwiftPlaygroundsでSwiftUIを使用してアプリ開発が可能に そのままAppStoreに提出できる プライバシー メール メールプライバシーでIPアドレスを隠すことが可能に Appプライバシーレポート Appプライバシーレポートでアプリがどんな情報にアクセスしているかサマリーされるようになる Siri Siriの音声が端末内で処理されるようになる(サーバーに録音されない) iCloud 家族などをアカウントの復旧先に指定できるようになる 没後に親族などに情報を引き継げる iCloud+ メールアドレスを隠すことができる(ステアド的な) safariでIPアドレスを隠すことができる(VPN的な) HomeKitのカメラの接続上限が上がる 価格は据え置き                   Health 歩行安定性 歩行の安定性を測れるようになり転倒リスクがわかる 10万人のデータから算出されている 安定性をよくするストレッチなども見れる Labs 健康診断結果などがよりわかりやすく表示できる Trends 長期的な変化がわかるようになる 医療機関 医療機関にこれらの情報を共有することができるようになる Family 家族の健康状態が見れるようになる                   WatchOS 8 呼吸 呼吸アプリが強化、ストレス軽減させリラックスを促す 睡眠 睡眠時に呼吸数が記録できるように                   ワークアウト 太極拳が追加 ピラスティックワークアウトが追加 Fitness+ アーティストスポットライトが追加                   文字盤 ポートレート文字盤が追加(動きのある感じ) その他 写真の共有が簡単に GIFが使えるようになる Home AppleTVで家族ごとにユーザーが作れ、好み調整が簡単になる homePodsMiniをAppleTVのスピーカーとして使用可能になる サードパーティ製Siri爆誕 スマートホーム新規格登場(互換性が上がることに期待) MacOS Monterey SharePlay 集中モード クイックノート ユニバーサルコントロール macからiPadや他のmacを操作可能になる AirPlay iPhoneからMacにAirPlayで表示出るようになる ショートカット ショートカットがmacでも使用可能に Safari デザインが刷新 タブをグループで保存できるようになり、iPadやiPhoneと共有される Developer Technologies Object Capture 写真から3Dデータを自動作成                   Swift async ・ awaitが追加                   XcodeCloud CICDを自動で行える                   自動テストも                   展開もテストフライトで                   AppStore カスタムページ ユーザーごと表示する内容を変えられる?                   app内イベント appstore前面に出せて宣伝できる                   さいごに 今回のWWDCはかなりボリューミーでしたね。 個人的にはXCode Cloudがbitriseやdeploygateの代替ができるのか期待しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ちょっとマイナーだけど知っておくと便利なXcodeのショートカット

Xcodeで開発する際に知っておくと便利かつ「こんな機能あったんだ!」と、思うようなショートカットもまとめました。 使いこなしていければ、「へー、そんな機能あったんですか!」等言われたり、開発効率も上がりオススメです。 ナビゲータエリア ショートカット 機能 cmd + 0 ナビゲーターエリア表示/非表示 cmd + 1 ナビゲーターエリアのプロジェクト表示 cmd + 2 ナビゲーターエリアのリポジトリ表示 cmd + 3 ナビゲーターエリアのシンボル表示 cmd + 4 ナビゲーターエリアの検索表示 cmd + 5 ナビゲーターエリアの問題ナビゲータの表示 cmd + 6 ナビゲーターエリアのデバックの表示 cmd + 7 ナビゲーターエリアのデバッグナビゲータの表示 cmd + 8 ナビゲーターエリアのブレークポイントの表示 cmd + 9 ナビゲーターエリアのレポートナビゲータの表示 option + cmd + N ナビゲーターエリアの新規グループ作成 エディターエリア ショートカット 機能 cmd + L Line Numberの表示 cmd + Shift + Y console表示/非表示 cmd + Shift + L UIパーツ選択画面 cmd + Shift + [ or ] ミニタブの移動 cmd + control + ← or → 前に開いていたファイルに移動する cmd + ¥ ブレークポイントを貼る cmd + option + [ or ] ラインを1行上or下に移動する control + I フォーマット整形 shift + option + ドラッグ 部分的に複数行選択 shift + control + クリック 部分的に複数選択 control + command + クリック Jump to Definition shift + cmd + 1 プロジェクト選択画面を開く shift + cmd + 2 デバイス,simulatorsウィンドウの表示 shift + cmd + 8 画面上にTouch Barの表示 shift + cmd + 0 documentationの表示 shift + cmd + (-) コード画面縮小 shift + cmd + (+) コード画面拡大 control + option + cmd + return 選択したstoryboardのアシスタントエディタを開く Simulator ショートカット 機能 cmd + Shift + A simulator起動時ライト/ダーク切り替え
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】Metal System Traceを使ってMetalアプリの処理時間を計測する方法

InstrumentsのMetal System TraceのMetalを使ったアプリの処理時間を詳細に分析することができます。 この記事ではそのやり方を説明します。 今回計測するアプリ GitHubにTokyYoshida/MetalExamplesというMetalのサンプルコードを集めたリポジトリを作りました。今回はこの中のParticleというサンプルを使用します。 パーティクルが上から下に流れるだけの処理です。 なお、このアプリはステータスバーにFPSが表示されているので、いまどのぐらいのFPSがでているのかすぐに確認できるようになっています。 (実行イメージ) 実はパーティクルはハートマークでしかも回転しているのですが、小さすぎて分かりません? 計測の手順 それでは計測してみます。 1. XcodeからMetal System Traceを起動する Xcode > Open Developer Tool > InstrumentsでInstrumentsを起動し、さらにMetal System Traceを選択します。 2. パーティクルの数を決めてアプリを実行する パーティクルの数を決めてアプリを実行します。 パーティクルはこの部分のinstanceCountに指定する値で決まります。 まずは100万を指定してみましょう。私のiPhone 11だと45FPSが出ていました。 ParticleMetalView.swift renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4, instanceCount: 100000) ビルドして、アプリを実行します。 3. Metal System Traceで計測を開始する アプリを実行してパーティクルを表示した状態でMetal System Traceに戻り、左上のボタンを押して計測を開始します。 4. 計測結果をみる 適当なところで■ボタンを押すと計測が止まります。 結果を見てみましょう。 <図1> アプリケーション(CPU)の処理、GPUの処理、ディスプレイのインスタンスの処理間隔が表示されます。今回なぜかvsyncが表示されなかったので、手書きで入れてみました。 vsyncは16.67ms間隔になっているので、60FPSを出すためにはこの範囲内でCPUとGPUの処理を終わらせている必要があります。 下のペインにはBuilt-in Displayの1つ1つの処理がリスト化されています。みると16.67msで終わっているものもあれば、33msかかっているものもあります。このように処理時間がかかるとフレームがスキップされて16.67のn倍の時間がかかってしまいます。 5. 処理の内訳を確認する 原因を分析するためには、遅くなっている処理の内訳を確認していきます。 上の図1をみるとCPUの処理は間に合っていますが、GPUの処理が大幅に遅くなっています。 ということで、GPUの処理の内訳を見ていきます。 使用しているiPhoneのチップの名前(この記事の場合はA13)の▶をクリックすると処理の内訳をみることができます。 処理は、フレームごとに色分けされていて次の順番で処理していることがわかります。 MetalExamples ・・・ CPUの処理 => Driver Processing ・・・ GPUドライバの処理 => Vertex ・・・ 頂点の変換や頂点シェーダーの実行 => Fragment ・・・ ラスタライズ、フラグメント シェーダーの実行 => Direct to Display ・・・ 描画 図中にコメントを書きましたが、Direct to Displayより前の処理がvsyncに間に合わないと、現在の画面を表示し続けることになるためFPSのレートが落ちます。緑色で示されたフレームの場合、特にVertexとFragmentの処理に時間がかかりすぎており、描画がvsyncに間に合っていないことがわかります。 6. パーティクルの数を減らして処理を観測する パーティクルの数を10万にしてさきほどのグラフを出してみましょう。 この場合、私のiPhoneでも60FPSが出ていました。 すべての処理がvsyncに収まっていることがわかります。 最後に iOSを使ったARやML、音声処理などの作品やサンプル、技術情報を発信しています。 作品ができたらTwitterで発信していきますのでフォローをお願いします? Twitterは作品や記事のリンクを貼っています。 https://twitter.com/jugemjugemjugem Qiitaは、iOS開発、とくにARや機械学習、グラフィックス処理、音声処理について発信しています。 https://qiita.com/TokyoYoshida Noteでは、連載記事を書いています。 https://note.com/tokyoyoshida Zennは機械学習が多めです。 https://zenn.dev/tokyoyoshida
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【watchOS8】アプリの常時表示機能で文字盤を作る

注: 自作文字版は審査に落ちます。自作文字版はあくまで遊びです。 前書き 初めまして! iOSアプリのエンジニアでVTuberになれるアプリを開発中の、蒼黯(あおぐろ)です。 https://twitter.com/pc_blue_screen WWDC21、iOS15やwatchOS 8などが発表されましたね。 早速ですが、watchOS 8でアプリが常時表示できる新機能が発表されたので、試していきましょう。(本当はSharePlayやりたかったけど、署名サーバーが未対応だった...) Appleとの秘密保持契約に基づきベータ版のスクリーンショット投稿は行いません。 記事内容もAppleが一般向けに公開している資料に書かれてることを記事化しています。 環境 macOS BigSur 11.4 Xcode 13 Beta 1 iOS 15 Developer Beta 1 watchOS 8 Beta 常時表示 Apple Watch Series 5以降(SE除く)の常時表示がwatchOS 8でデベロッパに解放された。 音楽再生やワークアウトなどのセッション時に限られるものの、 事前設定 常時表示を実現するために、まずはInfo.plistでWKSupportsAlwaysOnDisplayキーをtrueにする必要がある。 Info.plistにWKSupportsAlwaysOnDisplayと打つか、一覧からApp Supports Always On Display (Watch)を選択すれば出てくるので、YESを選択する。 状態の判別 @Environment(.scenePhase) private var scenePhase で判定できる。 戻り値はactive/inactive/backgroundの3つで、意味はそのまま。 if scenePhase == .active { Text("通常表示") } else { Text("腕を下げた時") } ※TimelineViewというViewでswitch分岐も作れるが、現時点ではバグで再現できていない。 情報を隠す 手首を下げた時に表示するべきでないプライベートな情報は.privacySensitive() で隠す。 もしくは@Environment(.redactionReasons) var redactionReasonsを呼んでおき、 if !redactionReasons.contains(.privacy) { Text("5000兆円欲しい") } のようにする。 まとめ struct ContentView: View { @Environment(\.scenePhase) private var scenePhase @Environment(\.redactionReasons) var redactionReasons VStack { if scenePhase == .active { Text("腕を上げた時") } else { Text("腕を下げた時") } Text("Privacy") .privacySensitive() } } 文字版を作る 上の仕組みを悪用すれば、簡易的に文字版も作ることができます。 (フォントは廻想体お借りしました! https://moji-waku.com/kaiso/) 右上の時計表示はプライベートAPIじゃないと消せないっぽいです。 ContentView.swift import SwiftUI struct ContentView: View { @Environment(\.scenePhase) private var scenePhase @State var D = Calendar.current.component(.day, from: Date()) @State var H = Calendar.current.component(.hour, from: Date()) @State var M = Calendar.current.component(.minute, from: Date()) @State var S = Calendar.current.component(.second, from: Date()) let timer = Timer.publish(every: 1, on: .current, in: .common).autoconnect() var body: some View { VStack { ZStack{ Circle() .trim(from: 0, to: CGFloat(Double(self.H) / 30)) .stroke(Color.blue,style: StrokeStyle(lineWidth: 10, lineCap: .square, lineJoin: .bevel)) .rotationEffect(.degrees(-90)) .rotation3DEffect(Angle(degrees: 12), axis: (x: 0, y: 0, z: 0)) .frame(width: 120, height: 120) .animation(Animation.linear, value: CGFloat(Double(self.H) / 30)) Circle() .trim(from: 0, to: CGFloat(Double(self.M) / 60.0)) .stroke(Color.red,style: StrokeStyle(lineWidth: 10, lineCap: .square, lineJoin: .bevel)) .rotationEffect(.degrees(-90)) .rotation3DEffect(Angle(degrees: 60), axis: (x: 0, y: 0, z: 0)) .frame(width: 100, height: 100) .animation(Animation.linear, value: CGFloat(Double(self.M) / 60.0)) if scenePhase == .active { Circle() .trim(from: 0, to: CGFloat(Double(self.S) / 60.0)) .stroke(Color.orange,style: StrokeStyle(lineWidth: 10, lineCap: .square, lineJoin: .bevel)) .rotationEffect(.degrees(-90)) .rotation3DEffect(Angle(degrees: 80), axis: (x: 0, y: 0, z: 0)) .frame(width: 80, height: 80) .animation(Animation.linear, value: CGFloat(Double(self.S) / 60.0)) } Text("\(self.D)") .font(.custom("Kaisotai-Next-UP-B", size: 30)) } }.onReceive(timer){ _ in self.H = Calendar.current.component(.hour, from: Date()) self.M = Calendar.current.component(.minute, from: Date()) self.S = Calendar.current.component(.second, from: Date()) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } 宣伝 【更新】開発中のVTuberアプリについて#Vtuber #Vtuberさんと繋がりたい pic.twitter.com/g9Q2IWMxQs— 蒼黯@VTuberアプリ開発中 (@pc_blue_screen) May 8, 2021 参考 Designing Your App for the Always On State - Apple Developer https://developer.apple.com/documentation/watchkit/designing_your_app_for_the_always_on_state
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む