iOSアプリケーションのサポートを簡単にします。 パート2-ロケーションとネットワーク

こんにちは、habrozhitel、



記事は、複数のバージョンを経て、さまざまな人によってさまざまな時期に書かれたアプリケーションのサポートをどのように扱うかについて説明しています。 他のiOS開発者にも役立つことを願っています。



  1. iOSアプリケーションのサポートを簡単にします。 パート1-Xcodeについていく
  2. iOSアプリケーションのサポートを簡単にします。 パート2-ロケーションとネットワーク
  3. iOSアプリケーションのサポートを簡単にします。 パート3-落下とログ


最初の記事では、再現しにくいバグの経験を共有しました。 この記事では、ネットワークまたは場所に関連するバグに対処する方法を説明します。 このトピックに興味がある人は、猫の下でお願いします。



最初の記事の熱心な読者は、私が長い間アウトソーシングで働いていたことを推測できました(私に終止符を打つ必要はありません)。 したがって、私の記事では、あなたから遠く離れた顧客がいる状況について説明します。



サブタイプ2-信じられないロケーション条件

「ここパリにいますが、データは表示されません」
多くのアプリケーションが場所に関連付けられており、すべてが順調です。しかし、クライアントのデータはそのように表示されず、彼はパリにいます...まあ、まあ、他に言えることはあります。 そして、私はシベリアにいます、そして、彼自身のために、データですべて大丈夫です。 どうする? 場所をシミュレートします。 そして、私たちのオプションを検討してください:

1)これは、シミュレーターでの位置の単純な置換です。 することは何もないので、適切なポイントに配置されます。 「IOSシミュレータ」→デバッグ→場所。

2)ポイントが少ない場合は、パスのシミュレーションを開始できます。pgxファイルがあり、それらは右側のアイコンを介してxcodeに追加されます



そして、場所はパスに沿ってあなたを移動しますが、...私の記憶が私に役立つなら、あなたはアプリケーションをXcodeにアタッチすることによってのみこれを行うことができ、ジャンプ間の時間を設定することはできません。 テスターは何をしますか? ケシに座って? 誰もがMACを購入した場合、良い会社です。 そして、常にXcodeアプリを接続しますか? また、大きな遅延が必要な場合は、Xcodeでできる以上のものが必要ですか?

3)ここで、 実行時の魔法の方法が突然助けになります。たとえば、 ここには多くのことが書かれていますが、なぜそれが便利になるのかは本当です...完全には明らかではありません。 ただし、場所の置換やナビゲーションの問題を解決するのに役立つオプションがあります。 FakeGPSUtilityは厳密に判断されるものではなく、何度か重宝し、重要な役割を果たしましたが、これはまだ自転車であり、根拠のない方向性を示すことはもうありません。 このプロジェクトは目標を達成します-場所を置き換えることができ、それらの間のジャンプは修正されません。 これは誰でも、クライアントでもXcodeは必要ありません。そして、私にとって最も重要なことは(二次的には)プロジェクトコードを変更せず、すべてがアプリケーションの起動時に置き換えられることです。 つまり、プロジェクトに添付し、プロジェクトコードを同じままにし、バグ/テストを修正して削除するか、必要な#defineを設定します。 便利なツールであるVoilaが手元にあり、このコードはテスト専用にリリースされることはありません。

iOS 8では、カードはシミュレーション中であっても位置(デバイスの実際の位置)を受け取り始めたため、手が届くとツールを終了します。

それまでの間、彼女はカードでこれを行うことができます。 赤いピンはNSLocationManagerデリゲートメソッドで飛ぶもので、残りはネイティブマップの動作です。 シミュレーションはオンでした-マップは進行中でした。



サブタイプ3-HTTP要求の問題

-エッジを接続すると、アプリケーションがうまく機能しません

-だからこそ、私はWiFiでテストし、なぜ自分自身を苦しめるのでしょう!

別のケースを考えてみましょう-問題は、ネットワークの不良が原因で現れました。 一般的に、単純に悪いインターネット接続をシミュレートして、アプリケーションの動作を確認すると便利です。WiFiを使用している場合や、ローカルホスト上のサービスを使用している間は、3Gでの動作がわかりません) そのため、興味のある方のために、 設定DeveloperNetwork Link Conditioner →デバイスを有効にして有効にする接続の程度を選択してください。 その後、アプリケーションの速度に関する視点を劇的に変更できます。

したがって、インターネットの速度を遅くすることはできますが、クライアント/テスターと同じ問題を取得するために特定の応答を中断する必要がある場合はどうでしょうか? その後、別の自転車を実行する必要があります(臭い臭い)。

FakeGPSUtilityと同様に、テストとバグの再生のために作業クラス内で何かを完了することに反対しています。コードはプロジェクト全体に追加されます。 NSURProtocolは私たちを助けます。 私に関しては、リクエストを中断する必要がある可能性が最も高い3つの場所はNSURLSessionTaskUIWebView、およびWKWebViewです。 他のネットワーク接続もありますが、ここでは私はあなたを助けません-私は何も良いアドバイスをしません、ただ座って、テストのためにプロジェクトコードを台無しにします。

NSURLSessionTask
その応答を中断するには、プロトコルをすべてのNSURLSessionConfigurationに分類する必要があります。
- (NSArray *)protocolClasses
      
      



そして、MyURLProtocolで配列を返すだけです。 アプリケーションが他のプロトコルを使用する場合は、それらも追加します(ヘッダーをドラッグしないようにするために、NSClassFromStringを使用できます)。 もっと複雑なロジックとプロトコルがどこにでもあるわけではなく、常に使用されているわけではない場合は、自分のせいにしなければなりません。
ここでの冗談はコードです
 static char kAssociatedObjectKey; - (NSArray *)protocolClasses { NSMutableArray *result = objc_getAssociatedObject(self, &kAssociatedObjectKey); if (result == nil) { result = [self customeProtocolsArray]; objc_setAssociatedObject(self, &kAssociatedObjectKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return result; } - (void)setProtocolClasses:(NSArray *)protocolClasses { NSMutableArray *result = [self customeProtocolsArray]; if (protocolClasses.count > 0) { [result addObjectsFromArray:protocolClasses]; } objc_setAssociatedObject(self, &kAssociatedObjectKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSMutableArray *)customeProtocolsArray { return [NSMutableArray arrayWithObject:[MyURLProtocol class]]; }
      
      



しかし、bacgkoundセッションではこれは機能しません。 証拠



UIWebView
まだ簡単です-クラスを登録するだけです。 たとえば、次のように:
 - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [NSURLProtocol registerClass:[MyURLProtocol class]]; return YES; }
      
      







Wkwebview
しかし、ここではすべてが悪いので、外部から交換することはできません。プロジェクトコードでこのために松葉杖を貼り付ける必要があります。



そして、実際には、プロトコル自体
 @implementation MyURLProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { #if !defined(STAGE_SERVER) || !STAGE_SERVER return NO; #endif NSString *urlString = [[request URL] absoluteString]; NSRange randge = [urlString rangeOfString:@"http://yandex.ru"]; if (randge.location == 0) { return YES; } return NO; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } + (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b { return NO; } - (void)startLoading { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSError *error = [NSError errorWithDomain:@"MyErrorDomain" code:42 userInfo:@{ NSLocalizedDescriptionKey: @"We fail it!"}]; [self.client URLProtocol:self didFailWithError:error]; }); } - (void)stopLoading { // stop request if you can } @end
      
      







4番目のサブタイプ-テストには特定の/古い応答が必要です

昨日、不正な動作が再現されたとのことですが、今日はうまくいかず、サービスは同じ答えを得られません。 ジャンルの法則によれば、この状況はリリースの初日に繰り返されるので、今ではすべてがうまくいっていると言うことです。 そして、いくつかの理由でサーバー側のチームに影響を与えることはできません。彼らは別の都市にいる、あなたは彼らを知らない、彼らは休暇中です。

この状況では、NSURLProtocolがあなたを再び助けようと急いでいます。 +(BOOL)canInitWithRequest:(NSURLRequest *)リクエストを変更するだけで、リクエストが必要なときに正しいデータを取得できます。

これは、希望する応答をシミュレートするためにMyURLProtocolがどのように見えるかです。

Myurlprotocol
 @implementation MyURLProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { NSString *urlString = [[request URL] absoluteString]; NSRange randge = [urlString rangeOfString:@"http://localhost:1984/oldresponse"]; if (randge.location == 0) { return YES; } return NO; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } + (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b { return NO; } - (void)startLoading { NSString *path = [[NSBundle mainBundle] pathForResource:@"unexistd_response" ofType:@"json"]; NSData *data = [NSData dataWithContentsOfFile:path]; [self.client URLProtocol:self didLoadData:data]; [self.client URLProtocol:self didFailWithError:nil]; } - (void)stopLoading { // stop request if you can } @end
      
      







ここでは、ファイルシステムからunexistd_response.jsonを読み取りますが、稼働中のマシンにリダイレクトを行い、そのマシンで小さなサービスを選択して、そのマシンから回答を取得することを禁止する人はいません。 これは、時間がある場合やプロジェクトに奇妙なファイルを入れたくない場合に最適なオプションです。たとえ一時的であってもテスト用であってもです。

個人的には、プロジェクトの開始時に動作するNSURLProtocolを作成することがよくあります。これは、多くの場合、サービスが計画と参照条件のみに含まれているためですが、実際にはありません。 しかし、すでにアプリケーションが正常に動作しているかのように、データを受信し、それらに応じてユーザーにコンテンツを表示するように書きたいと思います。 私は自分で#define STAGE_SERVER 1を作成し、作業サービスを提供するまでローカルファイルを操作します。 開発者が家を出て、コンピューターをオフにしたとき、彼らは私を救います。コンピューターはまた、開発者サーバーでした(何度も繰り返された、とんでもなくばかげた状況)。



おわりに



今日は、問題がhttpリクエストまたは場所に非常に密接に関連しているケースを調べました。 NSURLProtocolFakeGPSUtilityは今日の記事のヒーローであり、不正確なアプリケーションの動作のテストと再現を大幅に簡素化します。



All Articles