- 投稿日:2021-06-15T15:36:05+09:00
【iOS】Metal Best Practicesの解説(3) リソースオプション
Metal Best Practicesは、iOS/MacOS/tvOSのAPIであるMetalを用いた設計のベストプラクティスガイドです。 本稿では、何回かに分けてこのガイドを読み解き、コード上での実験を交えて解説していきます。 読んでそのまま理解できそうなところは飛ばしますので、原文を読みながら原文のガイドとしてご利用下さい。 また、iOSの記事なので他のOS(MacOS, tvOS)についての記載は割愛します。 他の記事の一覧は、初回記事より参照下さい。 Resource Options (リソースオプション) ベストプラクティス:適切なリソースストレージモードとテクスチャ使用オプションを設定します。 リソースストレージモードについて iOS, tvOSの場合は次の2種類があります。このように、CPUとGPUがメモリを共有するモデルをユニファイドメモリモデルといいます。 モード 説明 Shared モード CPU と GPU の両方にアクセス可能 Private モード GPU のみにアクセス可能 【iOS, tvOSのリソースストレージモードの概要図】 そして、iOSにおけるリソースストレージモードの選択は、通常はSharedモードが正しい選択であるとのこと。プライベートモードは、CPU がリソースにアクセスしない場合にのみ選択する。 適切なテクスチャ使用フラグの設定 Metalは、その使用目的に基づいて、特定のテクスチャのGPU操作をできる。事前に知っている場合は、必ず明示的なテクスチャ使用オプションを宣言します。 Unknownオプションに依存しないこと。このオプションはテクスチャに最も柔軟性を提供するが、かなりのパフォーマンスコストが発生します。 コードで検証してみる テクスチャの使用フラグの設定によってどの程度パフォーマンスに違いが出るのか検証してみます。 こちらのリポジトリにサンプルコードがあります。 サンプルコードの中に、Particleというサンプルがあるのでこれを改変しながら計測していきます。 (実行イメージ) テクスチャの使用フラグを設定する箇所の抜粋です。コメントにあるとおり、texDesc.usageの設定をUnknownとする場合と明示的に指定する場合の両方を用意し、実行するときに片方をコメントアウトしながら計測します。 ParticleMetalView.swift func initTexture() { func makeRenderTexture() -> MTLTexture { let texDesc = MTLTextureDescriptor() texDesc.width = 100//(parent.mtkView.currentDrawable?.texture.width)! texDesc.height = 100//(parent.mtkView.currentDrawable?.texture.height)! texDesc.depth = 1 texDesc.textureType = MTLTextureType.type2D texDesc.storageMode = .private texDesc.pixelFormat = .bgra8Unorm texDesc.usage = .unknown // Unknown版 texDesc.usage = [MTLTextureUsage.renderTarget, MTLTextureUsage.shaderRead] // 明示指定版 return metalDevice.makeTexture(descriptor: texDesc)! } texture = makeRenderTexture() } 計測は、Metal System Traceを使います。使い方はこちらをご覧ください。 アプリを実行し、一定時間計測してから、GPUのサマリーでFragmentとVertexの所要時間を見てみましょう。 <Unknown版の結果> <明示指定版の結果> 「Avg CPU to GPU Latency」を見てください。VertexはなぜかUnknown版の方が早いですが、Fragmentは明示指定版の方が、1ms近くなっています。トータルでも明示指定版の方が0.77ms早い結果となりました。 設定を1つ変えるだけで1msも早くなるのなら、労力に対して結構いい感じの成果なんじゃないでしょうか? 結論 ベストプラクティスにあるとおり、テクスチャ使用フラグを明示するほうが効率的ということがわかりました。 最後に 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
- 投稿日:2021-06-15T10:15:24+09:00
【Swift】UIAlertControllerと同じように使える自作ポップアップ
この記事は自分のブログの転記記事です。 元記事はこちら はじめに iOSアプリを作っているとき、ポップアップを出したいときにはUIAlertControllerを使っていますか? 最も簡単に実装できるのは良いのですが、少し見た目が物足りません。 そこでもう少し見た目にこだわった、かつUIAlertCotrollerと同じように使えるカスタムポップアップをコードのみで作ってみましたので紹介します。 ダークモードやアニメーション、多画面解像度にも対応済みです。使用、改変その他なんでもOKです。 注意事項 動作確認はiOS14でのみ行っています UIAlertControllerはStyleが.alertと.actionSheetの2つが使えますが、現段階では.alertのみの対応となっています UIAlertControllerではポップアップのボタン配置はいくつでもできますが、現段階では3つまでの対応となっています 最も簡単な使い方 ソースコードはGitHubに置いてあります。GitHub 1.「git clone」または「Download ZIP」でGitHubのソースコードをダウンロード 2.CustomAlertController -> CustomAlertExample -> CustomAlertController.swiftを自分のプロジェクトに追加 (ダウンロードしなくても、自分のプロジェクトでCustomAlertController.swiftを新規作成して、CustomAlertController.swiftの内容をコピペしても大丈夫です。) 3.ポップアップを表示させたい処理を行う部分で以下のように使ってください // カスタムアラートコントローラの作成 let alert = CustomAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) // カスタムアラートアクションの作成 let action = CustomAlertAction(title: "OK", style: .default, handler: {_ in // このボタンを押したときの処理 print("キャンセル") }) // アラートにアクションを追加 alert.addAction(action) // modalPresentationStyleを.overFullScreenに設定 alert.modalPresentationStyle = .overFullScreen // modalTransitionStyleを.crossDissolveに設定 alert.modalTransitionStyle = .crossDissolve // 表示 present(alert, animated: true) アラートコントローラの作成 -> アラートアクションの作成 -> コントローラにアクションを追加 -> present()という流れはUIAlertControllerと変わらないのですが、present()の前に.modalPresentationStyle = .overFullScreen、.modalTransitionStyleを.crossDissolveに設定することを忘れないでください。 最も簡単なカスタマイズ方法 CustomAlertController.swiftの上部に定数を用意してあり、ここをいじることでポップアップの見た目を変えることができます。 どの定数がなにかはコメントアウトを参考にしてください。 ソースコード詳細解説 カスタムアラートアクション カスタムアラートクラスを自作しますので、アラートアクションも自作します。 イニシャライザを作成し、標準のUIAlertActionのようにCustomAlertAction(title: “OK”, style: .default, handler: {_ in })で作成できるようになります。 titleがボタンに表示される文字列、styleがボタンのスタイル、handlerにはボタン押下時の処理が入ります。 /// カスタムアラートアクションの種類 enum CustomAlertControllerAction { case cancel case `default` case destructive } /// カスタムアラートアクションクラス class CustomAlertAction : NSObject { /// タイトル var title:String /// スタイル var style:CustomAlertControllerAction /// ハンドラ var handler: ((_ action: CustomAlertAction)->())? /// 初期化 init(title: String, style: CustomAlertControllerAction, handler: ((_ action: CustomAlertAction) -> ())?){ self.title = title self.style = style self.handler = handler } } カスタムアラートコントローラ スタイルは現時点では.alertのみ。 /// カスタムアラートコントローラの種類(.actionSheetは現段階では非対応) enum CustomAlertControlerStyle { case alert } /// カスタムアラートコントローラクラス class CustomAlertController: UIViewController, UIViewControllerTransitioningDelegate { // 省略 } カスタムアラートコントローラの中身 イニシャライザを用意してUIAlertControllerと同じようにCustomAlertController(title: “タイトル”, message: “メッセージ”, preferredStyle: .alert)で生成できるようにする。 /// アラートタイトル var alertTitle: String? /// アラートメッセージ var alertMessage: String? /// 初期化 internal convenience init(title: String?, message: String?, preferredStyle: CustomAlertControlerStyle) { self.init() self.alertTitle = title self.alertMessage = message } ビューやラベル、ボタンなどをすべてコードから生成している。 // タイトルラベル var titleLabel = UILabel() // メッセージラベル var messageLabel = UILabel() // アラート背景 var alertBackground = UIView() /// アラートビュー var alertView = UIView() /// 1つ目のボタン var firstButton = UIButton() /// 2つ目のボタン var secondButton = UIButton() /// 3つ目のボタン var thirdButton = UIButton() UIAlertControllerと同じようにalert.addAction(action)でアクションを追加できるようにaddActionメソッドを用意。 現段階ではアクションは3つまでしか追加できない仕様のため、すでに3つ以上ある場合はエラーを出すようにしている。 /// アクション格納配列 var actions = [CustomAlertAction]() /// アクション追加 func addAction(_ action:CustomAlertAction){ // 現段階ではアクションは3つまで追加可能 if actions.count >= 3 { abort() } actions.append(action) } viewDidLoad()にてポップアップの土台となるviewの.autoresizesSubviewsをfalseに設定する。 これをしないと、ポップアップ土台のサイズを変えたときに中身のラベルやボタンの大きさまで変わってしまう。 /// ビューが読み込まれたときに呼ばれる処理 override func viewDidLoad() { // 自身でサイズを決めているためリサイズを切る alertView.autoresizesSubviews = false } setUIParts()が実際にポップアップを生成する関数。 こういうレイアウト系はviewDidLoad()やviewWillAppear()の中では正常に作動しないため、viewDidLayoutSubview()の中でsetUIParts()を呼ぶ。 しかしviewDidLayoutSubview()は複数回呼ばれる処理のため、lazyを使った変数で定義することで_ = initViewLayoutと呼ばれた最初の一回のみ処理を行うようにする。 /// サブビューをレイアウトした際に呼ばれる処理 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() _ = initViewLayout } /// viewDidLayoutSubview()は複数回呼び出されるため最初の1度だけ呼び出されるようにlazyを利用 private lazy var initViewLayout : Void = { setUIParts() }() /// UI部品をセットする private func setUIParts() { // 省略 } あとはコードのゴリ押しでviewを作成する。慣れたらストーリーボードを使うより手っ取り早かったりする。 コード可読性のために別のプライベートメソッドへ切り出しを行っている。 /// UI部品をセットする private func setUIParts() { // 現在のY軸位置(作業用) var tmpY = 2 * INTERVAL // タイトル文言がある場合はタイトルラベルを作成 if self.alertTitle != nil { // タイトルラベルの作成 setUpTitle(tmpY: tmpY) // tmpYの更新 tmpY += titleLabel.frame.size.height + INTERVAL } // メッセージ文言がある場合はメッセージラベルを作成 if self.alertMessage != nil { // メッセージラベルの作成 setUpMessage(tmpY: tmpY) // tmpYの更新 tmpY += messageLabel.frame.size.height + INTERVAL } // 1つ目のアクションがある場合は1つ目のボタンを作成 if actions.count >= 1 { // 1つ目のボタンの作成 setUpButtons(button: firstButton, action: actions[0], tmpY: tmpY) // tmpYの更新 tmpY += BUTTON_HEIGHT + INTERVAL // 2つ目のアクションがある場合は2つ目のボタンを作成 if actions.count >= 2 { // 2つ目のボタンの作成 setUpButtons(button: secondButton, action: actions[1], tmpY: tmpY) // tmpYの更新 tmpY += BUTTON_HEIGHT + INTERVAL // 3つ目のアクションがある場合は3つ目のボタンを作成 if actions.count >= 3 { // 3つ目のボタンの作成 setUpButtons(button: thirdButton, action: actions[2], tmpY: tmpY) // tmpYの更新 tmpY += BUTTON_HEIGHT + INTERVAL } } } // アラートビューの作成 setUpAlertView(tmpY: tmpY) // アラート背景に追加 alertBackground.backgroundColor = BACKGROUND_COLOR alertBackground.addSubview(alertView) self.view = alertBackground } さいごに 今回はUIAlertControllerよりもう少し見た目にこだわった、かつUIAlertCotrollerと同じように使えるポップアップをコードのみで作ってみました。 UIImageViewで画像を追加したりなどもできます。皆さんのポップアップの参考になれば幸いです。 ご質問、不具合報告などありましたらTwitterまで(@ruemura3)
- 投稿日:2021-06-15T00:02:34+09:00
新 App Store 審査ガイドライン 翻訳&差分ガイド 2021年6月号
はじめに これは2021年6月7日付けで変更された App Store 審査ガイドラインの翻訳&差分ガイドです。 前回からの主な変更点は、開発者に対する行動規範の明記が目立ちます。2.3.1 で App Store 外の悪質行為を削除対象に、5.6 全般で誠実でなければ削除対象になど。これは、今年3月の Trezor に偽装した詐欺アプリ問題などが影響しているはず。 注目しておきたいのは、鬼門である「機能が少ないからリジェクト」の 4.2 に「実用性」が追記されたこと、5.6.4 にて、レビュー評価が開発者登録の抹消に影響することあたり。あと、地味に影響がありそうなのは、アカウントの作成機能と対で必須になる削除機能でしょうか。 https://developer.apple.com/app-store/review/guidelines/ 新規項目 1.2.1 Creator Content ユーザ生成コンテンツでコア機能の変更は不可。アプリ内で年齢レーティングを提示。追加購入となるコンテンツを明示。 Apps which feature content from a specific community of users called “creators” are a great opportunity if properly moderated. These apps present a singular, unified experience for customers to interact with various kinds of creator content. They offer tools and programs to help this community of non-developer creators to author, share, and monetize user-generated experiences. These experiences must not change the core features and functionality of the native app—rather, they add content to those structured experiences. These experiences are not native “apps” coded by developers—they are content within the app itself and are treated as user-generated content by App Review. Such creator content may include video, articles, audio, and even casual games. The App Store supports apps offering such user-generated content so long as they follow all Guidelines, including Guideline 1.2 for moderating user-generated content and Guideline 3.1.1 for payments and in-app purchases. Creator apps should share the age rating of the highest age-rated creator content available in the app, and communicate to users which content requires additional purchases. 1.7 Reporting Criminal Activity 犯罪報告アプリは法執行機関が関与する必要有。 Apps for reporting alleged criminal activity must involve local law enforcement, and can only be offered in countries where such involvement is active. 5.6.2 Developer Identity 提供する情報は正確に。 Providing verifiable information to Apple and customers is critical to customer trust. Your representation of yourself, your business, and your offerings on the App Store must be accurate. The information you provide must be truthful, relevant, and up-to-date so that Apple and customers understand who they are engaging with and can contact you regarding any issues. 5.6.3 Discovery Fraud App Store の情報操作は不可。 Participating in the App Store requires integrity and a commitment to building and maintaining customer trust. Manipulating any element of the App Store customer experience such as charts, search reviews, or referrals to your app erodes customer trust and is not permitted. 5.6.4 App Quality 否定的なレビューや返金は開発者が行動規範を遵守しているかどうかの判断要因。 Customers expect the highest quality from the App Store, and maintaining high quality content, services, and experiences promotes customer trust. Indications that this expectation is not being met include excessive customer reports about concerns with your app, such as negative customer reviews, and excessive refund requests. Inability to maintain high quality may be a factor in deciding whether a developer is abiding by the Developer Code of Conduct. 修正項目 1.1.4 ポルノ表現は不可。 Overtly sexual or pornographic material, defined by Webster’s Dictionary as “explicit descriptions or displays of sexual organs or activities intended to stimulate erotic rather than aesthetic or emotional feelings.” This includes “hookup” apps that may include pornography or be used to facilitate prostitution. This includes “hookup” apps that may include pornography or be used to facilitate prostitution. を追記。hookup app は文脈的に性交アプリ。 1.4.3 薬物・酒・タバコの助長は不可。合法大麻やタバコなどの販売促進は不可。 Apps that encourage consumption of tobacco and vape products, illegal drugs, or excessive amounts of alcohol are not permitted on the App Store. Apps that encourage minors to consume any of these substances will be rejected. Facilitating the sale of controlled substances (except for licensed pharmacies and licensed or otherwise legal cannabis dispensaries), or tobacco is not allowed. marijuana を and licensed or otherwise legal cannabis dispensaries に変更。このあたりは、5.1.1 (ix) で補足あり。 2.3.1 隠し機能は不可。Notes for Review で具体的に説明。機能しないコンテンツは不可。App Store 内外問わず悪質行為は開発者登録を抹消。 Don’t include any hidden, dormant, or undocumented features in your app; your app’s functionality should be clear to end users and App Review. All new features, functionality, and product changes must be described with specificity in the Notes for Review section of App Store Connect (generic descriptions will be rejected) and accessible for review. Similarly, marketing your app in a misleading way, such as by promoting content or services that it does not actually offer (e.g. iOS-based virus and malware scanners) or promoting a false price, whether within or outside of the App Store, is grounds for removal of your app from the App Store and termination of your developer account. Egregious or repeated behavior is grounds for removal from the Apple Developer Program. We work hard to make the App Store a trustworthy ecosystem and expect our app developers to follow suit; if you’re dishonest, we don’t want to do business with you. promoting a false price, whether within or outside of the App Store, is grounds for removal of your app from the App Store and termination of your developer account を追記。App Store 外の悪質行為も対象に。 2.3.10 各環境向けに最適化。他のモバイルプラットフォームに関する言及は不可。アプリと無関係の情報は不可。 Make sure your app is focused on the iOS, iPadOS, macOS, tvOS or watchOS experience, and don’t include names, icons, or imagery of other mobile platforms in your app or metadata, unless there is specific, approved interactive functionality. Make sure your app metadata is focused on the app itself and its experience. Don’t include irrelevant information. iOS, Mac, Apple TV or Apple Watch を iOS, iPadOS, macOS, tvOS or watchOS に変更。 文末から including but not limited to information about Apple or the development process を削除。 3.1.1 In-App Purchase: ● デジタル商品を対象としたギフト券はアプリ内課金でのみ販売可能。アプリ内であれば物理的なギフト券にもアプリ内課金が可能。 Digital gift cards, certificates, vouchers, and coupons which can be redeemed for digital goods or services can only be sold in your app using in-app purchase. Physical gift cards that are sold within an app and then mailed to customers may use payment methods other than in-app purchase. Physical gift cards that are sold within an app and then mailed to customers may use payment methods other than in-app purchase. を追記。これまで禁止していた物理アイテム (ギフト券) にアプリ内課金が使えるように。 3.1.2(a) Permissible uses: ● Apple が承認済みの音楽と映像のサブスクリプションアプリは携帯電話会社のバンドルに含まれる可能性有。アプリ内課金かつ元に戻せる仕組みがあれば他のサブスクリプションアプリも含めることが可能。 Cellular carrier apps may include auto-renewing music and video subscriptions in pre-defined bundles with cellular data plans, with prior approval by Apple. Other auto-renewing subscriptions may also be included in pre-defined bundles with cellular data plans, with prior approval by Apple, if the cellular carrier apps support in-app purchase for new users and the carrier provides a mechanism for customers to revert to in-app purchase upon termination of the customer’s bundled service. Such subscriptions cannot include access to or discounts on consumable items. 表現を全体的に変更。 3.1.3 Other Purchase Methods: アプリ内課金を阻害するような施策は不可。 The following apps may use purchase methods other than in-app purchase. Apps in this section cannot, within the app, encourage users to use a purchasing method other than in-app purchase. Developers cannot use information obtained within the app to target individual users outside of the app to use purchasing methods other than in-app purchase (such as sending an individual user an email about other purchasing methods after that individual signs up for an account within the app). Developers can send communications outside of the app to their user base about purchasing methods other than in-app purchase. 文章の後半を変更。 Developers can send communications outside of the app to their user base about purchasing methods other than in-app purchase. は新情報で、アプリ外であれば他の課金手段を紹介可能に。 4.2 Minimum Functionality 有用性のないアプリは不可。継続的な価値や実用性のないアプリは不可。曲や映画は iTunes Store に提出。本は iBooks Store に提出。 Your app should include features, content, and UI that elevate it beyond a repackaged website. If your app is not particularly useful, unique, or “app-like,” it doesn’t belong on the App Store. If your App doesn’t provide some sort of lasting entertainment value or adequate utility, it may not be accepted. Apps that are simply a song or movie should be submitted to the iTunes Store. Apps that are simply a book or game guide should be submitted to the Apple Books Store. or adequate utility を追記。実用的でないと駄目。 4.3 Spam 類似アプリの量産は不可。飽和カテゴリのアプリは審査が厳格。スパム行為は開発者登録を抹消。 Don’t create multiple Bundle IDs of the same app. If your app has different versions for specific locations, sports teams, universities, etc., consider submitting a single app and provide the variations using in-app purchase. Also avoid piling on to a category that is already saturated; the App Store has enough fart, burp, flashlight, fortune telling, dating, drinking games, and Kama Sutra apps, etc. already. We will reject these apps unless they provide a unique, high-quality experience. Spamming the store may lead to your removal from the Apple Developer Program. drinking games を追記。ドリンキングゲームは Wikipedia で初めて知った。 4.7 HTML5 Games, Bots, etc. 旧 4.7 を 4.7.1 と 4.7.2 に分割しただけ。 5.1.1 Data Collection and Storage (v) Account Sign-In: 重要なアカウント機能がない場合はログイン不要で使用できる必要有。アカウントの作成機能があれば削除機能も必要。主機能や法的に必要性がない個人情報の要求は不可。主機能が対象の SNS と無関係の場合はログイン以外の仕組みが必要。プロフィールの取得や共有・招待は主機能枠外。アプリに SNS 連携を無効化する仕組みが必要。 If your app doesn’t include significant account-based features, let people use it without a login. If your app supports account creation, you must also offer account deletion within the app. Apps may not require users to enter personal information to function, except when directly relevant to the core functionality of the app or required by law. If your core app functionality is not related to a specific social network (e.g. Facebook, WeChat, Weibo, Twitter, etc.), you must provide access without a login or via another mechanism. Pulling basic profile information, sharing to the social network, or inviting friends to use the app are not considered core app functionality. The app must also include a mechanism to revoke social network credentials and disable data access between the app and social network from within the app. An app may not store credentials or tokens to social networks off of the device and may only use such credentials or tokens to directly connect to the social network from the app itself while the app is in use. If your app supports account creation, you must also offer account deletion within the app. を追記。アカウントの削除機能も必須に。 (ix) 規制の多い分野や機密情報に関わるアプリは法人提出が必須。 Apps that provide services in highly-regulated fields (such as banking and financial services, healthcare, gambling, legal cannabis use, and air travel) or that require sensitive user information should be submitted by a legal entity that provides the services, and not by an individual developer. Apps that facilitate the legal sale of cannabis must be geo-restricted to the corresponding legal jurisdiction. legal cannabis use と Apps that facilitate the legal sale of cannabis must be geo-restricted to the corresponding legal jurisdiction. を追記。 5.6 Developer Code of Conduct コメントには敬意を持ち対応。詐欺行為は開発者登録を抹消。 Please treat everyone with respect, whether in your responses to App Store reviews, customer support requests, or when communicating with Apple, including your responses in Resolution Center. Do not engage in harassment of any kind, discriminatory practices, intimidation, bullying, and don’t encourage others to engage in any of the above. Repeated manipulative or misleading behavior or other fraudulent conduct will lead to your removal from the Apple Developer Program. Repeated manipulative or misleading behavior or other fraudulent conduct will lead to your removal from the Apple Developer Program. を追記。 行動規範を遵守しなければ開発者登録を抹消。復元するためには改善計画書を提出して承認される必要有。 Your Developer Program account will be terminated if you engage in activities or actions that are not in accordance with the Developer Code of Conduct. To restore your account, you may provide a written statement detailing the improvements you plan to make. If your plan is approved by Apple and we confirm the changes have been made, your account may be restored. 新規追加の段落。アカウントの復元は改善計画次第。