【App Store】ガイドライン 5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

前回、古いアプリがガイドライン4.3スパムであると、判断されて公開停止になったと書きました。
んで、「かたっぽ削除するからえーやろ」って返事を書いたら斜め上の返事が来ました。

その内容はこちら。

App Store Review

Hello,

Thank you for your responses. In order to reduce fraudulent activity on the App Store and comply with government requests to address illegal online gambling activity, we are no longer allowing gambling apps submitted by individual developers. This includes both real money gambling apps as well as apps that simulate a gambling experience.

For this reason the apps will not be made available for sale at this time.

Best regards,

ググる翻訳すると、

App Storeレビュー

こんにちは、

ご回答いただきありがとうございます。 App Storeでの不正行為を減らし、違法なオンラインギャンブル活動に対処する政府の要請に従うため、個々の開発者から提出されたギャンブルアプリは許可されなくなりました。 これには、リアルマネーギャンブルアプリとギャンブル体験をシミュレートするアプリの両方が含まれます。

このため、この時点でアプリを販売することはできません。

宜しくお願いします、

どうやらApp Storeではくじ引きや抽選を含むギャンブル系のアプリがだめになったっぽいです。
他のサイトでもそのようなことが書いてありました。
一斉摘発のようですね。

参考サイト
【iPhone】App Storeでギャンブル性のある個人開発アプリが一斉にリジェクト | 楽しくiPhoneライフ!SBAPP

Appleのガイドラインだとこちらですね。
5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

5.3 賭博ゲーム、ギャンブル、宝くじ/ロト

ギャンブル、賭博ゲーム、宝くじ/ロトは管理が複雑であり、App Storeでもっとも規制が厳しい分野の1つです。アプリケーションを提供するすべての地域におけるあらゆる法的義務を確認した後、こうした機能を搭載してください。この場合、審査には通常よりも時間がかかります。以下の点に注意してください。

5.3.1 抽選やコンテストの主催者は、アプリケーションのデベロッパである必要があります。
5.3.2 抽選、コンテスト、チャリティーくじの公式ルールをアプリケーションで提示し、Appleは主催者ではなく、いかなる形でも関わりがないことを明記する必要があります。
5.3.3現実のお金を使用するあらゆる形式の賭博ゲームで、ゲームのクレジットや通貨の購入にApp内課金を使用することはできません。また、アプリケーション内で抽選やチャリティーくじの購入、資金の振替を可能にすることは許可されません。
5.3.4 現実のお金を使用する賭博ゲーム(スポーツ賭博、ポーカー、カジノゲーム、競馬など)または宝くじ/ロトを提供するアプリケーションは、アプリケーションが利用される地域で必要なライセンスおよび許可を取得し、アプリケーションの利用をその地域のみに制限し、App Storeで無料配信する必要があります。カードカウンターなどの違法なギャンブルツールは、App Storeで許可されません。ロトアプリケーションには、考慮、機会、賞品の3つの要素が必要になります。

お金をかけてするギャンブルじゃなくて、縁日やイベント用の抽選アプリと行っても通用しなさそうですね。
諦めるしか無いかな〜。
うじゃうじゃ。/(^o^)\

【App Store】ガイドライン 4.3 SPAM

え〜、3年前から公開しているアプリが突然非公開にされました。

メールの本文はこんな感じ。

Hello,

We are writing to let you know about new information regarding your app currently live on the App Store.

Upon re-evaluation, we found that your app is not in compliance with the App Store Review Guidelines. Specifically, we found:

Design – 4.3
This app duplicates the content and functionality of other apps submitted by you or another developer to the App Store, which is considered a form of spam.

For this reason, your app will be removed from sale on the App Store at this time.

Deliberate disregard of the App Store Review Guidelines and attempts to deceive users or undermine the review process are unacceptable and is a direct violation Section 3.2(f) of the Apple Developer Program License Agreement. Continuing to violate the Terms & Conditions of the Apple Developer Program will result in the termination of your account, as well as any related or linked accounts, and the removal of all your associated apps from the App Store.

If you have any questions about this information, please reply to this message to let us know.

Best regards,

App Store Review

翻訳すると、

こんにちは、

現在App Storeに登録されているあなたのアプリに関する新しい情報をお知らせします。

再評価の結果、あなたのアプリはApp Storeレビューガイドラインに準拠していないことが判明しました。具体的には、

デザイン – 4.3
このアプリは、あなたや他の開発者がApp Storeに提出した他のアプリのコンテンツや機能を複製します。これは迷惑メールの一種です。

このため、この時点であなたのアプリはApp Storeで販売されなくなります。

App Storeレビューガイドラインの意図的な無視、ユーザーの欺瞞またはレビュープロセスの悪化は容認できず、アップルデベロッパープログラムライセンス契約の第3.2条(f)に直接違反しています。引き続きApple Developer Programの利用規約に違反した場合、アカウントや関連アカウント、リンクされたアカウントの削除、関連するすべてのアプリケーションのApp Storeからの削除が行われます。

この情報に関するご質問がある場合は、このメッセージに返信してお知らせください。

宜しくお願いします、

App Storeレビュー

画面右にリンクのある「ガラポン抽選機の代わりに催事用スロット」ってのがそうなんですけどね。
まだ課金がよくわからない時に作ったアプリで、機能制限したお試し用の無料版と、機能制限のない有料版の2つに分けてリリースしてるのがダメらしい。

Appleのガイドラインだとここだね。
4.3 スパム

4.3 スパム

同一のアプリケーションに対して複数のバンドルIDを作成しないでください。特定の場所、スポーツチーム、大学などに向けた異なるバージョンが存在するアプリケーションの場合は、単一のアプリケーションを提出し、異なるバージョンはApp内課金で提供する方法を検討してください。また、すでに飽和状態のカテゴリにアプリケーションを追加することは避けてください。App Storeには、おなら、げっぷ、懐中電灯、カーマ・スートラといったアプリケーションが多数あります。App Storeでスパム行為をすると、Developer Programから除名される可能性があります。

とりあえず「有料版だけ残すわー」って返事書いたら予想外の返事が。
それは次の投稿で。/(^o^)\

【Swift4】【Objective-c】SKStoreReviewController でアプリ内レビュー

最近流行りのアプリの中でレビュー(アプリの評価)をつけてもらうやつを調べてみた。

参考サイト
SKStoreReviewController を単純な条件で出すだけでも好意的なレビューが増えて良かった
SKStoreReviewController で App Store の評価数が急増した話 – wootan’s diary

機能としてはiOS10.3以降が対応のようです。
表示されるのは年に3回まで。
有意の時点で呼び出して、年に3回に達していないと表示されるらしい。
つまり、何回起動したときとか、そういう条件をつけて、レビューの請求をされてもおかしくない、
できれば好レビューが貰えそうな時に表示されるようにするのが良いっぽい。

コードとしてはStoreキットをインポートして使う。

Swiftの場合。

objective-cの場合。

一度この表示が出て評価を送信すると、その後は出なくなるのか、それとも、直後でも呼び出されるとまた表示されてしまうのか、そのへんの詳しい挙動がわからんのでそれなりの対応が必要そうです。

と、ゆーことで、いま手入れしてるobjective-c用にコードを書いてみた。

最初は10回呼ばれたら、その後は100回呼ばれる毎にレビューが請求されます。

あ、バージョンでの切り分けはこちらを参考にしました。
Objective-C で OS バージョン判定を簡潔に行う方法

【Swift】ちょっと珍しいエラー?【libclosured.dylib】

先日、アプリをアップデートして課金機能を実装しました。
ユーザーから課金しても良いので広告を外してほしいと熱望されていたのです。
しかし、ただでさえプログラミングに慣れていないのに、課金はかなり理解し難く、たいへん手を焼きました。
おかげで途中数ヶ月放置なんてこともあり、実装できるまでに1年近くかかりました。

で、Xcodeのシミュレータでも、実機でもsandBoxを使って問題なく課金が出来ることを確認して、Appleの審査に提出しました。
アプリの説明にも堂々と「課金で広告が外せるようになりました」と書いて。
最近は審査の時間がどんどん短くなってるようで、今回はびっくりの24時間切り、18時間位で無事リリースされました。

が、そこで問題が起こりました。
設定の画面から課金の画面に行くと、フリーズしてクラッシュするのです。
何度試しても同じ、実験機でも、嫁のiPhoneでも同様でした。
もう一度、Xcodeからビルドして動作確認をしてもこちらは問題なし。
appSotreからダウンロードし直してみるとやっぱりクラッシュ。
こんなんどうやって、デバグしたらいいのと、血の引く思いでした。
毎度、Appleに審査出して通ってから実地確認ってわけにも行かないしね。^^;
あんなに堂々と課金できますよって書いちゃったのに。/(^o^)\

で、まあ、とりあえずいろいろ検索して
下記サイト見つけエラーログが調べられることがわかりました。
swift – 原因のわからないバグの特定方法について – スタック・オーバーフロー

エラーログを取ってみるとズラズラとログが表示されて、

という感じで、最後は
0x1ad277000 – 0x1ad2a7fff libclosured.dylib arm64 /usr/lib/closure/libclosured.dylib
で終わっていました。

よくわからんけど、/usr/lib/closure/libclosured.dylib このあたりが怪しいかと検索しまくり。

日本語のページでは全く引っからなかったけど、海外のサイトではcrashという文字とともにいくつか引っかかりました。
CFNetwork crash with iOS 11.3.1 |Apple Developer Forums
My app crash with Exception Type:  EXC_CRASH (S… |Apple Developer Forums
Crash in iOS 11.1 | GeoNet

などなど…。

英語はよくわからんが、総じて見ると、原因不明なんだけどOSの問題ちゃうん?って感じでした。

で、AppleDeveloperに電話で聞いても見たのですが、症状の再現はされるけれど、原因はわからんと。
こっちでは無理なので、テクニカルサポートかフォーラムで聞いてみてくれと。
どっちも英語やん。\(^o^)/オワタ

仕方なしに、コードを見直してみたり、App Store Connectを見直してみたり、
、、、してたら、App Store Connect のApp内課金のページですっごい違和感が!

あれ?課金コンテンツって審査用のスクリーンショットで必須だよね?/(^o^)\
でも、設定されてないよね。/(^o^)\

【Swift】ちょっと珍しいエラー?【libclosured.dylib】

メタデータが不足って書いてあると審査用のスクリーンショットがなかったりします。

よくよくアプリの設定を見たら、Xcodeでもin-App purchaceもオンになってないし、全然課金が動作する状態じゃなかった。/(^o^)\
Xcodeのin-App purchaceがオンになっててスクリーンショットがなかったりしたらリジェクトもされたんだろうけど、すべて後回しにして数ヶ月放置している間にそういうこともすっかり忘れていたようです。
そりゃ課金の設定無いのに、プロダクト情報取りに行ったらフリーズもするわ。^^;
しかし、よくアプリの審査通ったな。/(^o^)\

で、スクリーンショットを撮って、App内課金の設定もして、速攻で再度審査に提出しました。

まあはよ気づいてよかったよ。
こんなこともあるんだね。
うじゃうじゃ。

【Swift4】Google Analytics と eコマース?

SwiftでGoogle Analytics で eコマースを利用しようとしたが、ワケワカラン。
そもそもeコマースがわかってないんだが。
とりあえず課金があったらその情報を受け取れるようにしてみたい。

とりあえず、まずここの説明がSwiftに対応していない。(# ゚Д゚)
e コマース トラッキング – iOS SDK  |  iOS 向けアナリティクス  |  Google Developers

コピペだが、このコードがSwift化できれば良いんだと思う。

参考にしたのがこちら
ios – Issue with Google Analytics in Swift 2 or 3 – Stack Overflow
と、こちら
iOSアプリでもGoogleAnalyticsでがっつり計測する実装方法【総集編】 | Nagisaのすゝめ

なんだかんだイジって、
Xcodeに文句言われないように変更して出来たのがこの形。

とりあえず自分用。
うまくいかなくったってしーらないしーらない。
うじゃうじゃ。/(^o^)\

【Swift4】tabbarとnavigationControllerを使ってる時のマイナーな?戻り方。

Tabbar Controllerでつながった、タブAの画面とタブB1の画面があり、タブBからはnavigationControllerをつかってタブB2の画面に遷移できるとする。
画面B2に居る時にtabbarでタブAに移動して、またタブBに移動しようとすると、タブB2に移動してしまう。

一旦、タブAに移動してタブBに移動するとき、自動的にタブB1に移動するようにしたかった。

言葉にするとすごくわかりにくい。orz

結論から書くとタブB2の画面が消えたあとにnavigationControllerで戻る指示をすれば良い。

こんな感じで。
うじゃうじゃ。

【Swift4】UIScrollViewで電子書籍風に。

UIScrollViewを使って電子書籍風?な感じで見れるものを作ってみました。

参考サイト
[iPhone] UIScrollView ページ スクロール
【Swift】UIScrollViewの使い方。大きい部品をスクロールして見る。 | はじはじアプリ体験記
【Swift】UIScrollViewとUIPageControlを使ってページを移動する方法 | はじはじアプリ体験記
UIScrollView、UIKit座標計算系に関しての復習 – これが最後じゃないからね

基本条件
・表示させる画像ファイルを用意する。
・画像のサイズは多少、大小してもscrollViewの幅にリサイズ、画面中央に配置。
・漫画のように右から左へ見ていく。
・1画面1ページ。

UIScrollViewについて。
UIScrollViewはいろいろとサイズのプロパティがあってややこしい。

とりあえず参考サイトから真似てプロパティを説明する画像を作ってみた。
【Swift4】UIScrollViewで電子書籍風に。

UIScrollViewに使われるサイズは大きく分けて2つ。
frameとcontentSizeだ。
frameのサイズは画面に表示される「枠」のサイズ。
contentSizeが枠のなかに表示される「移動可能な領域」のサイズ。
イメージとしてはframeの上にcontentSizeが乗ってる感じだけど、
実際にはcontentSizeのうえにframeがあってそこから覗き込んでる感じなのでややこしく感じる。

frameには
frameの位置座標をあらわす(frame.origin.x , frame.origin.y)というプロパティと
frame.size.widthという幅と、
frame.size.heightという高さのプロパティを持っている。
frame.originはiPhoneの画面の起点からの距離というところに注意。

contentSizeは
contentOffset.x , contentOffset.yというscrollViewに対する位置情報と
contentSize.widthという幅と、
contentSize.heightという高さのプロパティを持っている。

contentInsetは今回使わないので割愛。

今回は電子書籍風ということでscrollViewのframeとcontentSizeの高さを揃えて、contentOffset.xの値が変動することによって画面が横スクロールするイメージです。
【Swift4】UIScrollViewで電子書籍風に。

ではまず、StoryboardでViewControllerを開き、ScrollViewを配置します。
【Swift4】UIScrollViewで電子書籍風に。

AutoLayoutで位置を決めて、Paging Enabledにチェックを入れます。これでscrollViewがページ単位で動くようになります。

次いで、Assetsに画像を放り込みます。
【Swift4】UIScrollViewで電子書籍風に。

コードの記述

・AutoLayoutの処理を待ってviwDidApearから処理を始めます。
・scrollViewのサイズが決まったら高さと幅を取得。
・scrollView幅に合わせて画像のサイズを変更してsubviewに貼っていく。
・subviewを配列に取り込んで順番を逆転。
・順にscrollViewの幅ずつずらしていく。
・scrollViewの幅×画像の数をcontentSizeの幅にする。
・contentSizeの高さはscrollViewの高さと同じ。
・scrollViewの初期位置を一番右の画像に持ってくる。

①の時点でのイメージはこんな感じ。
【Swift4】UIScrollViewで電子書籍風に。

contentSizeはまだ指定していないので存在しないか(0,0)なので画面は動きません。

画像の順番を並べ替えて右へずらしてframeを初期位置へ移動させて、
最終的に起動した時のイメージは②でこんな感じ。

【Swift4】UIScrollViewで電子書籍風に。

contentSizeの範囲をflameの幅で左右にページ移動します。
一応こんな感じでscrollViewが使えました。

うじゃうじゃ。

【Swift4】効果音のクラスを作ってみた。【AVAudioPlayer】

ずーーっと以前にSwiftで音を出すのはやってみた。
【Swift3】【AVAudioPlayer】音を出してみる。 | iPhoneアプリ備忘録

最近、ちょっとまた効果音を出したくて勉強し直してみた。
効果音を出すにはAudioServicesPlaySystemSoundを使う方法もあって、連打できたりするのは良いのですが、
iPhone側の音量で調節ができないという欠点もあり、AVAudioPlayerを使って連打も出来るようにクラスを作ってみた。

ちなみにクラスとか作るの初めてなのでなんか間違ってても生暖かく見守るか、優しく教えてもらえるとありがたいです。(-人-)

さて、参考にしたのはこちらのサイト。
ARC環境下でAVAudioPlayerを使い柔軟かつシンプルにサウンドを再生する方法

これをSwiftで書いてみたいと思います。

まず、AVAudioPlayerを使うにはAVFoundation.frameworkが必要です。
TARGET>Generalで追加しておきます。

音声ファイルも用意してプロジェクトナビゲータに放り込んでおく。
とりあえずファイル名は「hit.mp3」とする。

んでは、SEManagerというNSObjectのクラスを作ります。

これで音を鳴らすクラスが出来た。
インスタンスを配列に入れて削除する辺り、実はよく分かってない。/(^o^)\
do とか、try とか、throwsとかも理解していない。
動いてるから良しとしてほしい。(^_^;)

んで、音を鳴らして!っていう側。
ボタンアクションでSEManagerを呼び出します。

SEManagerに投げる音声ファイルでいろいろと音が鳴らせるので汎用性は高いように思います。
あ、インスタンスとか、オブジェクトとかよく理解できてませんので、なんかおかしい所あるかもしれません。
動いてるから良しとして(以下ry

ま、そんな感じで自分用の備忘録です。
うじゃうじゃ。

【Swift4】objective-cからSwiftのクラスを呼び出す。

おぶしーからすいふとに切り替えて暫く経ちますが、古いアプリなど丸っとスイフトに書き換えるのは面倒なので、
objective-cはそのままで、新規クラスはSwiftでと混在させてます。

んで、objective-cからSwiftのクラスを呼び出す時にちょっと詰まったんで備忘録。

参考サイト
Objective-CコードからSwiftのクラス/プロトコルを使う方法(フレームワーク開発編)
Objective-CベースのプロジェクトからSwiftのクラスを呼び出す
SwiftとObjective-Cの相互利用する際の注意

例えば、
hogehogeというアプリがあって、
higehige.h higehige.m というobjective-cのクラスが有って、
hagehage.swift というswiftのクラスがあるとする。

higehige.m で hagehage.swiftクラスを使いたいので、適当にインポートしてみた。

エラーが出た。(´・ω・`)ショボーン

ネットで調べて、-Swift.hを着けたら良いのね!(`・ω・´)シャキーン

あれ?(´・ω・`)

ムキー!なんで通らんのや!/(^o^)\

じっくり調べなおすと、、、「プロダクト名」-Swift.h なのか…。orz

これでよかったようです。/(^o^)\
クラス呼び出すんやからクラス名だと思うやん…。(´・ω・`)

ちなみに呼ばれる側は

のように@objcMembersをつけるか、メソッドの前に @objc をつけておくようです。

他にもハマりどころはありそうなので他サイトも参考に。
うじゃうじゃ。

2018/07/10追記
上記のようにswiftファイルをインポート出来るようになりました。
で、次の記事にあるSEManager.swiftで音を鳴らしたいのですが、
objective-cからSEManager.swiftのメソッドを呼び出そうとするとエラーが!!

SEManager.swiftのplaySoundメソッドは引数があるのでobjective-c側からはplaySoundWithSoundNameで呼び出します。
xcodeの変換サポートでも候補に出るし、問題なく認識していそうなのですが、どーやってもNo visibleのままです。

よくわからないまま試行錯誤を繰り返すこと丸一日、SEManager.swiftのplaySoundメソッドの中にある’throws’を消すと認識されました。
throws,do,try,catchというのはよく分かってないですがAVAudioPlayerを使う時にXcodeからつけろーと言われます。
このthrowsを消すと、別のswiftファイルからplaySoundメソッドを呼び出す所で黄色三角のエラーが出ますがビルドは出来ます。
なんとも明確な解決策が見いだせませんでしたが、とりあえず動いたので良しとしつつ、自分の無能を呪っときましょう。/(^o^)\

【Swift】レイアウトがずれる。【AutoLayout】追記あり。

原因が分かってからネットを検索すると情報はいっぱい出てくるんですけどね。
原因にたどり着くまでが長かった。orz
忘れると困るので備忘録。

参考サイト

http://rindatetu.hatenablog.jp/entry/2016/03/06/154946

症状としてはStoryboardでAutoLayoutで指定したスクロールビューがおかしい。
機種(画面サイズ)によって位置がずれる。

結果的にはAutoLayoutで指定したビューを元にviewDidLoadメソッドで更に描画指定をしようとしたからずれたようだ。

自分が理解しているviewControllerのライフサイクルは以下のような感じ。

・viewDidLoad
最初に一回だけ呼ばれる。
初期設定とか何でも放り込みがちだよね。

・viewWillAppear
開くたびに呼ばれる。
他の画面で設定したものを毎回画面に来る度に反映させたいときなどにつかう。

・viewDidAppear
画面の表示、レイアウトが終わった所で呼ばれる。

・viewWillDisappear
他の画面に遷移する直前に呼ばれる。

・viewDidDisappear
他の画面に遷移したあとに呼ばれる。

今回はAutoLayoutの処理が終わったあとに更に描画処理をする必要があったため、viewDidAppearに処理を書くことで対処できた。
しかし気づくまでに3日もかかったとか…。orz

追記
さらにその後問題が見つかった。
viewDidAppearにレイアウトの処理を書くと、毎回開くたびにレイアウトがやり直される。
今回はscrollViewで電子書籍風のページを作ったが、別のviewに行って戻ってくると最初のページに戻ってしまう。

この問題の解決方法がこちら
参考サイト
[Swift] viewDidLayoutSubviewsで初回だけ処理をしたい | 黒ごまのおむすび

よくわからないが lazy というのあり、これを使うと
初回一回のみの処理となるらしい。

まだよく理解できてないが、一応思ったとおりの動作になったので良しとしよう。
うじゃうじゃ。