20211124のiOSに関する記事は4件です。

サポーターズ エンジニア1on1面談イベントに参加してきた

はじめに B3 iOSインターン生のにいまるです。 逆求人イベントに参加してきたので、参考になるようにレポートを書いてみます。 サポーターズとは? 僕がいつも使ってる、学生エンジニア就活のサポートをしてくれるサービスです。(回し者じゃありません) どんなイベントなの? 一日に最大8社と面談できる逆求人イベントです。雰囲気はめちゃめちゃカジュアルでした! 参加するにはサポーターズ側で選考がありますが、選考を通り抜けると早期選考、自己紹介へのフィードバック、長期インターンのオファーなどがあり、非常に魅力的です。 参加確定後は企業さんにする自己紹介の準備をするのですが、任意でサポーターズ側で自己紹介準備のための面談みたいなものに参加することができます。 僕は自己紹介に命かけてたので、自己紹介資料は3日くらいかけてみっちり作りました! 参加までの流れ 選考 ↓ 参加確定 ↓ サポーターズ側でのサポート面談 ↓ 自己紹介の準備 ↓ 1on1面談イベント当日 ↓ 後日、オファーが届くかも? みたいな感じでした。普通のESみたいな感じで、そこまで選考の負担はないです! 当日 午前に企業プレゼンがあり、お昼休み中に面談希望アンケートを書き、午後は面談が組まれた企業さんと実際に面談をするという形式です。自分は8社(最大)と面談を組まれたため、後半は声がカスカスになってました。。もちろん人気な企業さんは面談希望が通らないこともありますが、それでもおおよそ通ったので、それほど心配する必要はないと思います! ↓ちなみに、自分の面談資料の表紙はインパクト重視でこんな感じにしました(笑)。ウケもめっちゃ良かったです! 面談の内容としては 開発物 現在参加しているインターンの話 将来どうなりたいか 企業選びの軸 企業さんへの質問タイム などでした。上の項目は重点的に聞かれるので準備していて損はないと思います。自分は現在参加している長期インターンの話が一番盛り上がった気がします。 さいごに、イベント終了後は企業さんから丁寧にフィードバックの文章が送られてきます。 参加してよかったこと 自己分析につながった 自分にとって間違いなく一番の収穫でした。自己紹介スライドをみっちり洗練させて作るので、改めて振り返る機会になります。また自分が作った資料が残るので、このイベントが終わった後でも見返したりできて便利です。 フィードバックがもらえた 選考過程で自己紹介をする機会はたくさんありますが、フィードバックをもらうことは殆どないため、このイベントに参加する最大のメリットだと思います。人間面、そして技術面でも非常に参考になりました。ちゃんとフィードバック聞いて改善すれば、本選考でも相当な武器になるはずです。 また「ここの話はウケたな」、「ここの話は盛り上がらなかったな」みたいなことも分かるので、今後の選考などで話すべき内容などもわかってきました。 自身がついた 企業さんの反応を見て、自分の今までの経験が無駄じゃなかったんだなと、大きな自信に繋がりました。 ネクストアクションがわかった 下記のようなフィードバックを丁寧に頂きました。 「今のインターン先で本当に良い経験を積んでいるみたいなので、これからもぜひ力を入れてやってほしい。」 「長期インターンで獲得したノウハウを個人開発に応用すると、さらにレベルアップに繋がる。」 「開発物をただ作っているだけでなく、課題感をここまで持っている学生はほとんどいない。」 「直面した課題をどう乗り越えたかについて話せるとより良い。」 イベント開催から1ヶ月ほど経ちましたが、今でもかなりの頻度で読み返しています。 技術力の高い企業から、長期インターンのオファーが来た 「自分がこんなすごい企業さんのところで働いていいんか!?!?!?」って思うくらい驚きました。自分がオファーを貰った企業は1回目に面談をしたところで、初めてということもあり非常にテンパった自己紹介を見せつけてしまったのですが、その後の話が盛り上がったのが良かったかも知れません。 早期選考、選考免除につながった 行きたい企業さんからオファーが来ると超ラッキー!!!忙しい就活生のミカタですね アマギフを大量にもらった(笑) あまり大きい声では言えませんが、中古のiPhoneが購入できるくらいには溜まりました。僕はガジェット大量に買いました。 感想 正直参加できると思ってなかったので、参加が確定した時点で就活の大きなターニングポイントになったと思います。渋谷の道玄坂で合格の連絡が来たのは今でも覚えています(笑) なので、出来なさそうでもとりあえず挑戦してみることが大事だと思いました。 その反面まだまだ頑張れる余地はあるなと、実感する機会になりました! おまけ 逆に悪かったことは? 非常に疲れます。マジで。後半になると自分も企業さんもかなりぐったりしています。 あとエンジニア仲間はオンラインだと殆どできない気がします。 学生エンジニア仲間はできた? オンライン開催ということもあり、全然できませんでした、、、slackで一言挨拶しただけです。 サポーターズの1on1面談イベントいくつかあるけど、何回でも参加できる? 僕は1回目(10/23)で味をしめたので、追加で2回( 10/24, 12/5 )参加予定です(笑) ただしサポーターズでの面談で聞いたのですが、同イベントで既に接触したことがある企業さんが多い場合、その1on1イベントには通りづらいそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】アプリ内でシステムログを取得したい

この記事はNTTコムウェア Advent Calendar 2021 1日目の記事です。 初日からかなりニッチな内容ですが、iOSでシステムログを取得する方法について考えます。 ベータテストあるある そんなこと言われても解析のしようがない せめてログをください... という光景を社内で見たことはないでしょうか。 実際アプリをリリースする前にシステムログを取得してもらうのは容易ではないため、 ログをもらうのを諦めているケースは多いと思います。 今までのログ取得方法 iOSでシステムログを確認する方法としては Macにつないで、XCode経由で取得 Macにつないで、Console.app経由で取得 端末の電源ボタンと音量ボタンを長押ししてiPhone内にsysdiagnoseログを出力して、Macに繋いでファイルを取得して何らかの方法で送信してもらう 等の方法がありますが、 開発者ならまだしもテストに協力してもらっている方々にMac用意してXcodeインストールして...はハードルが高すぎます。 iOS15以降のログ取得方法 実は最近(2021年8月)にリリースされたiOS15Beta版からアプリ内でシステムログが取得できるようになりました。 参考) Apple Developer Documentation OSLogStore Class https://developer.apple.com/documentation/oslog/oslogstore この機能を利用してアプリ内にバグ報告機能を実装しておけば、簡単にテスターからログを送信してもらうことができそうです。 サンプルコード if #available(iOS 15.0, *) { do { let store = try OSLogStore.init(scope: .currentProcessIdentifier) // 1時間前までのログを取得 let position = store.position(date: Date().addingTimeInterval(-3600)) // 時間の降順で取得 let enumerator = try store.__entriesEnumerator(options: [.reverse], position: position, predicate: nil) enumerator.forEach { element in let message = element as? OSLogEntry dump(message.debugDescription) dump(message?.composedMessage) } } catch { dump(error) } } else { // iOS14以下の処理 } 実際に取得できたログの一部 2021-11-19 11:39:01:Using ~iphone resources 2021-11-19 11:39:01:Initializing connection 2021-11-19 11:39:01:Removing all cached process handles 2021-11-19 11:39:01:Sending handshake request attempt #1 to server 2021-11-19 11:39:01:Creating connection to com.apple.runningboard 2021-11-19 11:39:01:Received message from server: async_didChangeInheritances:completion: 2021-11-19 11:39:01:didChangeInheritances: <RBSInheritanceChangeSet| gained:{( <RBSInheritance| environment:(none) name:com.apple.frontboard.visibility origID:6452-6464-44> )} lost:(null)> 2021-11-19 11:39:01:Handshake succeeded 2021-11-19 11:39:01:Identity resolved as application<com.xxxx.yyyy> 2021-11-19 11:39:02:No persisted cache on this platform. 2021-11-19 11:39:02:Deactivation reason added: 10; deactivation reasons: 0 -> 1024; animating application lifecycle event: 0 2021-11-19 11:39:02:assertion failed: 20G165 19A339: libxpc.dylib + 55577 [68F6BE69-6DB2-3A18-A053-2C03A9D2A10A]: 0x7d 2021-11-19 11:39:02:activating monitor for service com.apple.frontboard.open 2021-11-19 11:39:02:activating monitor for service com.apple.frontboard.workspace-service 2021-11-19 11:39:02:FBSWorkspace connecting to endpoint : <BSServiceConnectionEndpoint: 0x600000a84210; target: com.apple.frontboard.systemappservices; service: com.apple.frontboard.workspace-service> 2021-11-19 11:39:02:FBSWorkspace registering source: <FBSWorkspaceScenesClient: 0x600002ff8070> 2021-11-19 11:39:02:FBSWorkspace connected to endpoint : <BSServiceConnectionEndpoint: 0x600000a84210; target: com.apple.frontboard.systemappservices; service: com.apple.frontboard.workspace-service> 2021-11-19 11:39:02:Added observer for process assertions expiration warning: <_RBSExpirationWarningClient: 0x6000004d1040> 2021-11-19 11:39:02:Lookup of 'AppleLocale' from current preferences failed (app preferences do not contain the key; falling back to generation via preferred languages) 2021-11-19 11:39:02:CFLocaleCopyCurrent() constructing a locale identifier from preferred languages without a set country code 2021-11-19 11:39:02:[FBSScene] [sceneID:com.xxxx.yyyy-default] Created client agent: <UIApplicationSceneClientAgent: 0x6000006ec3c0> 2021-11-19 11:39:02:Language lookup at CFBundle 0x7fcee7a04cf0 </Users/xxxx/Library/Developer/CoreSimulator/Devices/xxxxxx/data/Containers/Bundle/Application/yyyyyy/dummy.app> (executable, loaded) Localizations : [Base, en] Dev language : en User prefs : [en, ja-US] Main bundle : [<null>] Allow mixed : 0 Result : [en] 2021-11-19 11:39:02:Resource lookup at CFBundle 0x7fcee7a04cf0 </Users/xxxx/Library/Developer/CoreSimulator/Devices/xxxxxx/data/Containers/Bundle/Application/yyyyyy/dummy.app> (executable, loaded) Request : InfoPlist type: strings Result : None 動作的に不完全な部分がある アプリ起動後からのログしか実際は取得できていない ログ取得期間、例えば60分前〜のログを取得、を指定できるパラメータが存在しているが、実際はパラメータを指定しても効果が無い まだできたてほやほやの機能ということもあって今後の改善に期待です。 おわりに アプリ内でシステムログが取得できる、という事実だけでも非常に有用ですのでお困りの方は試してみてはいかがでしょうか。 参考 https://developer.apple.com/documentation/oslog/oslogstore https://developer.apple.com/forums/thread/650843 https://developer.apple.com/forums/thread/677068
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

機械学習で必殺技分類(動作分類モデル作成からiOSでの推論実行まで:失敗編)

動画を機械学習して、動作の種類を判定する GUIで機械学習ができるCreateML(Macで実行可能)。 動作の分類(Action Clasification)もできます。 実は僕は今回学習に失敗したのですが、作業フローはひととおり書いたので、公開しちゃいます。 【こういうのが作りたかった】 手順(データセット準備) 1、動画を集める。 分類したい動作の動画を集めます。 今回はこのようなアクションを用意してみました。     ピースサインなど静止的な動きだと画像分類で十分なので、動画シーケンスに意味のある動きにしました。 集める動画の推奨事項 ・一つのアクションに50個以上の動画を集める ・アプリで使うフレームレート以上の動画を集める(トレーニング時に解析する動画のフレームレートを指定する必要がある。アプリで実行する際も、このフレームレートがを基準に解析する) ・カメラは固定 ・うつすのは一人 ・全身を映す ・明るい環境で ・ぶかぶかすぎる服は適さない ・背景に溶け込みすぎている服の色も適さない ・アプリでいろんな角度からキャプチャする場合は、データセットもいろんな角度のものを用意する ・一つの動画に、一つのアクションの複数回の動作が入っている場合、動作の間の静止や間隔は最小限に抑える。 ・静止が入る場合は、その部分をトリミングするか、注釈つきのデータセットにする。 ・ネガティブケースを入れる(アプリ実行時に起こり得る他の動作。例えば、筋トレ前後でフレームに出入りする歩行シーンを入れる。) ・静止ケースを入れる(筋トレ前後で動かずに座っている状態など。) 2、データを整理する(フォルダ分け、もしくはアノテーション・ファイルをつける) CreateMLに与えるデータをフォルダ分けしてデータセットにします。 フォルダ分けには二つの方法があります。 構成方法1、アクションごとにビデオをフォルダ分けする 「一つの動画に一つのアクション分類」になるように、きちんと動画をトリミングしている場合にこの方法が使えます。 構成方法2、注釈ファイルをつける 一つのビデオに複数のアクションが含まれる場合は、csvやjsonでアノテーションファイル(注釈ファイル)を作ります。 方法1、は一つの動画に一つの動作を隙間なく撮影するもしくはトリミング編集するなど、留意が必要です。 ビデオを細かく撮影したり、後でトリミングするのはけっこう手間なため、僕の個人的おすすめは方法2、です。 アノテーションファイルの例 jsonでは以下のようにアクションごとに「ファイル名、ラベル、時間」キーの辞書の配列を作ります。 時間の形式は、秒数の整数もしくは小数が認識されます。 annotations.json [ { "video" : "killMove1.mov", "label" : "Nmehameha", "start" : 0, "end" : 3.1 }, { "video" : "killMove1.mov", "label" : "Nkankousappou", "start" : 3.2, "end" : 6 }, { "video" : "killMove2.mov", "label" : "Negative", "start" : 0, "end" : 3.7 }, { "video" : "killMove2.mov", "label" : "Ki", "start" : 3.8, "end" : 6.5. } ] 注意:公式ドキュメントには、String形式の分:秒でも、時間:分:秒.コンマ秒でも認識されるとありますが、これはなぜか認識されません。 // これらのJson形式は認識されないので注意 [ { "video" : "specialMoves.mov", "label" : "Nmehameha", "start" : "8:3.2", "end" : "8:4.5" }, { "video" : "specialMoves.mov", "label" : "Ki", "start" : "1:59:5.8", "end" : "1:59:7" }, { "video" : "specialMoves.mov", "label" : "Nkankousappou", "start" : "1:59:14", "end" : "1:59:15.1" } ] 手順(学習) 3、CreateMLでActionClassificationを開く XcodeをControlクリックしてOpenDeveloperToolからCreateMLを開いて以下を選択。 4、学習データを指定 「Training Data」の項目から学習データのフォルダを選択します。 注意:JSONを読み込ませる場合は、JSONファイルを直接選択する必要があります。フォルダ選択では認識しません。 検証データは学習データと別に用意してもいいし、しなくてもOKです。指定しない場合はcreateMLがトレーニングデータの一部を検証データとしてより分けてくれます。 5、学習の設定をする 以下の設定をします。 パラメーター Iterations 計算ステップ数。CreateMLがデータセットから自動で設定してくれます。 増やしたり減らしたりもできます。 Frame Rate アプリで想定するフレームレート。 データセットはこの数値以上のフレームレートで用意する必要があります。 action duration: アクション1回に想定される時間を設定します。 これによってcreateMLはアクション分析のフレーム間隔を認識できます。 Augmentations データを水増しできます。 アクションの左右がどちらでもいい場合は、Horizontal Flip(画像を水平にひっくり返して学習データを増やす)でデータを2倍に拡張できます。 6、学習を開始する 「Run」ボタンで学習を開始します。 自動で指定した計算回数まで学習します。 手順(学習結果) 7、手持ちの動画でモデルをためしてみる CreateMLのPreviewタブをクリックし、動画ファイルをドロップすると、作成したモデルを試せます。 8、CoreMLモデルを取得する CreateMLのOutputタブをクリックし、Getをクリックすると、作成したモデルのCoreMLファイルが取得できます。 手順(モバイルでの推論) 9、CoreMLファイルをアプリにバンドルする 取得したCoreMLモデルをアプリで使うには、アプリにCoreMLファイルをドロップしてバンドルします。 以下のプロセスで、Visionフレームワークを使ってカメラフィードから人体の特徴ポイントを取得し、CoreMLフレームワークでモデルを実行します。 10、人体ポーズの特徴ポイントを取得する まずは Vision で人体ポーズの特徴ポイントを検出し、その特徴ポイントをモデルに与えます。 VisionのVNDetectHumanBodyPoseRequestで人体のキーポイントを取得します。 do { let request = try VNDetectHumanBodyPoseRequest() let handler = try VNImageRequestHandler(cvPixelBuffer: capturedImage) // AVFoundationやARKitなどで、カメラフィードから取得したフレームのPixelBufferを与える try handler.perform([request]) guard let poses = request.results as? [VNRecognizedPointsObservation] else {return} // これが1フレーム分の人体の特徴ポイント poseWindow.append(poses.first) } catch let error { print(error) } //※ カメラからリアルタイムでフレームを与える場合、計算コストからカメラ・プレビューをブロックすることがあるので、グローバルキューで実行しましょう。 上記は、1フレーム分の人体の特徴ポイントです。 動画解析ですので、特徴ポイントを必要フレーム分ためて、モデルにあたえます。 60 フレーム分が必要な場合は、以下のように配列にします。 private lazy var posesWindow:[VNRecognizedPointsObservation] = { // 特徴ポイントの配列を作る var window = [VNRecognizedPointsObservation]() window.reserveCapacity(predictionWindowSize) // 必要なフレーム分のスペースを確保 return window }() { didSet { if posesWindow.count == predictionWindowSize { // 必要なフレーム枚数がたまったら、推論を実行 do { try makePrediction() } catch let error { print(error) } } } } var predictionWindowSize: Int = 60 11、特徴ポイントをマルチアレイ(多次元配列)に変換する 必要なフレーム分の人体の特徴ポイントがたまったら、モデルのインプット用にマルチアレイにしてからモデルにあたえます。 【特徴ポイント × XY座標の信頼度 × 必要フレーム数】の3次元配列マルチアレイにします。 この変換には Vision のメソッドをつかいます。 VNRecognizedPointsObservationを【特徴ポイント × XY座標の信頼度】のマルチアレイに変換してくれるkeypointsMultiArrayメソッドです。 // func makePrediction() throws { let poseMultiArrays: [MLMultiArray] = try posesWindow.map { person in guard let person = person else { return makeZeroedMultiArray() // ポーズリクエストの結果がnil(人が映っていない)場合は、[1,3,18]が全て0値のマルチアレイを入れる } return try person.keypointsMultiArray() // 1フレーム分の人体ポイントを、ポイントと信頼度の配列にしてくれる Vision のメソッド } let modelInput = MLMultiArray(concatenating: poseMultiArrays, axis: 0, dataType: .float) // モデルに必要なフレーム量の配列にまとめる 人体が映っていない時は、全ての値が0のマルチアレイをモデルに与えます。 ゼロ・マルチアレイの作り方はこちら。 private func makeZeroedMultiArray() -> MLMultiArray { let shape:[Int] = [1,3,18] guard let array = try? MLMultiArray(shape: shape as [NSNumber], dataType: .double) else { fatalError("Creating a multiarray with \(shape) shouldn't fail.") } guard let pointer = try? UnsafeMutableBufferPointer<Double>(array) else { fatalError("Unable to initialize multiarray with zeros.") } pointer.initialize(repeating: 0.0) return array } 12、インプットをモデルにあたえる(推論実行) 取得した指定フレーム分のマルチアレイをモデルに与えます。 CoreMLフレームワークを使います。 // func makePrediction() throws { // let poseMultiArrays: [MLMultiArray] = try posesWindow.map { person in // ............ 上記 // ............ // let modelInput = MLMultiArray(concatenating: poseMultiArrays, axis: 0, dataType: .float) let prediction = try classifier.prediction(poses: modelInput) posesWindow.removeAll() // 次の推論のために、ためたフレームを空にする print(prediction.label) // 最も信頼度の高い動作のラベル print(prediction.labelProbabilities[prediction.label]) // 信頼度 与えた動画(必要フレーム分の特徴ポイントの配列)に対しての推論結果がラベルと信頼度として返ってきます。 Nmehameha Optional(0.728015124797821) 13、失敗談 僕が試した時は、データ数が少なかったせいか、不正解のラベルがつくことも多かったです。 リアルタイムで動作解析をして、AR効果をつけたかったのですが。 ちなみに、GifのAR効果は別の方法を用いて作成しました。ARKitのボディ・スケルトンの認識です。 ARKitで両手のポイントを取得し、「手が体の中央からどれくらい離れているか」と「両手の距離で必殺技の体勢をしているか」を判定しました。 機会があれば、CreateMLのシーケンシャルな動作解析を再チャレンジしたいところです。 ? フリーランスエンジニアです。 お仕事のご相談こちらまで rockyshikoku@gmail.com Core MLやARKitを使ったアプリを作っています。 機械学習/AR関連の情報を発信しています。 Twitter Medium
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Firebase Cloud Messaging(FCM)は中国では使えない

iOS/Androidアプリの開発を協業している他社担当者から、システムテストにおいて、 「プッシュ通知が届かない」 「iOS/Androidとも同じく」 という報告があり、再現性を確認したのですが弊社側では再現せず… 同アプリはプッシュ通知にFirebase Cloud Messaging(FCM)を利用しています。 バックエンド側のログなどを追うと、どうやら、SDK経由で取得できるはずのプッシュトークンが取得できていない模様。 協業他社によくよく聞いてみると、「中国でテストをしている」、とのこと。 そこで調べたところ、FCMって中国(本土)では使えないんですね…(→参考リンク) 同アプリは日本国内での利用が前提なので、協業他社に「プッシュ通知のテストだけは国内でお願いします」と依頼するだけで済んだのですが… もしグローバルなサービスだったら、中国本土で使えるプッシュ通知mBaaSに乗り換えるなど、大幅なアーキテクチャ変更になるところでした。 なお、FCMの公式ドキュメントではその辺りの制限事項に関する記述は見つけられませんでした。 参考リンク:
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む