2012-03-01 15 views
17

オンとオフラインの両方で動作する必要があるアプリケーションにRestKitを使用したいと考えています。RestKit iOSアプリケーションのオンラインとオフラインのサポート

私はRestKitのしくみを誤解しているかもしれませんが、これは(かなり)簡単に実装できたと思いました。

次のように私は物事を設定スクラッチテストiOSアプリでは:CoreDataをサポートするために必要とされる

// setup the client 
NSString* URL = @"http://10.211.55.5:3000/api"; 
RKClient* client = [RKClient clientWithBaseURL:URL]; 
client.username = @"[email protected]"; 
client.password = @"password"; 

// setup caching 
client.cachePolicy = RKRequestCachePolicyLoadIfOffline | RKRequestCachePolicyLoadOnError | RKRequestCachePolicyTimeout; 
client.requestCache.storagePolicy = RKRequestCacheStoragePolicyPermanently; 

// setup managed object store 
RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:URL]; 
RKManagedObjectStore* objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"RestKitCoreDataTest.sqlite"]; 

// connect my cache implementation 
MyCache* cache = [[MyCache alloc] init]; 
objectStore.managedObjectCache = cache; 
objectManager.objectStore = objectStore; 

// setup mapping  
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]]; 
[userMapping mapKeyPath:@"id" toAttribute:@"identifier"]; 
[userMapping mapKeyPath:@"email" toAttribute:@"email"]; 
[userMapping mapKeyPath:@"firstname" toAttribute:@"firstname"]; 
[userMapping mapKeyPath:@"surname" toAttribute:@"surname"]; 
userMapping.primaryKeyAttribute = @"identifier"; 
[objectManager.mappingProvider setMapping:userMapping forKeyPath:@""]; 

// setup routes 
RKObjectRouter* router = [objectManager router]; 
[router routeClass:[User class] toResourcePath:@"https://stackoverflow.com/users/:identifier"]; 

ユーザーオブジェクトが実装されます。

@interface User : NSManagedObject 

@property (nonatomic, retain) NSNumber * identifier; 
@property (nonatomic, retain) NSString * email; 
@property (nonatomic, retain) NSString * firstname; 
@property (nonatomic, retain) NSString * surname; 

@end 

@implementation User 

@dynamic identifier; 
@dynamic email; 
@dynamic firstname; 
@dynamic surname; 

@end 

ここMyCacheというのです。私がresourcePathをチェックするのは煩わしいことではない。なぜなら、これは試してみることに過ぎず、とにかく1つのパスしか持たないからだ。

@implementation MyCache 
- (NSArray*)fetchRequestsForResourcePath:(NSString*)resourcePath 
{ 
    NSFetchRequest* fetchRequest = [User fetchRequest]; 
    return [NSArray arrayWithObject:fetchRequest]; 
} 

-(BOOL)shouldDeleteOrphanedObject:(NSManagedObject *)managedObject 
{ 
    return true; 
} 
@end 

私は、パス "/ API /ユーザー/ 123" で、サーバーへのコールは、ID 123を持つユーザーを取得するために行います。

User* user = [User object]; 
user.identifier = [NSNumber numberWithInt:123]; 
RKObjectManager* manager = [RKObjectManager sharedManager]; 
[manager getObject:user delegate:self]; 

これが正常に動作します。しかし、MacでWi-Fiを切断すると、上記のコードはsqliteデータベースからユーザーを取得しません。

私は、デリゲートのobjectLoader:didFailWithErrorに代わりに次のエラーが表示されます。

2012-03-01 11:44:09.402 RestKitCoreDataTest[1989:fb03] error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x6b89aa0 {NSErrorFailingURLStringKey=http://10.211.55.5:3000/api/users/123, NSErrorFailingURLKey=http://10.211.55.5:3000/api/users/123, NSLocalizedDescription=The request timed out., NSUnderlyingError=0x6b81ac0 "The request timed out."} 

私はタイムアウトがありますときにキャッシュをして、使用することを指定するのおかげであると考え:「RKRequestCachePolicyTimeout」、私が期待しているだろうユーザーはローカルキャッシュから検索されます。

キャッシュには、IDが123のユーザーレコードがZUSERテーブルに、ZIDENTIFIER列に123が含まれています。

これを機能させるための手順がありますか? がタイムアウトした後にキャッシュがヒットしたときに、 を処理する必要があるか、または呼び出される別のデリゲートメソッドですか?あるいは、RestKitを使って「すぐに」入手できるものではないものをやろうとしていますか?

乾杯。

+0

こんにちは、私はRestKit 0.20.1と同じことをしようとしています - これに関するすべてのアップデート?あなたはこれを手に入れましたか?あなたがチェックした答えはあなたの質問に答えていないようです...ありがとう! – Diego

+1

私は、私がオンラインかオフラインかをチェックするために到達可能性クラスを使用するJulianの提案を取ったので、以下の答えが正しいと確認しました。その後、私はRestKitをオンライン通信に使い、CoreDataを自分でオフラインストレージとして使用しました。 – dbarros

+0

OKありがとう!私はこれを一元管理しようと考えています - これを行うには、HTTPオペレーションキューを作成して、それが毎回同期を必要とする(おそらく定期的に)解析する方が良いと思います。 – Diego

答えて

6

クライアントがオフラインであるかどうかを判断するには、到達可能性クラスを使用することがあります。インターネット接続が必要なすべてのプロジェクトでこの偉大なクラスを頻繁に使用します。

通知者を特定のホストに開始するだけです。あなたのすべてのviewControllerでは、NSNotificationCenterにメソッドを登録するだけで、BOOL isOnlineなどを設定する必要があります。

この練習をすると、スムーズな「オフライン」メッセージでアプリをオーバーレイするような美しいものをアプリで実行できます。私のプロジェクトの1から相続人一例ログイン画面から

https://gist.github.com/1182373

EDIT

(このコードの量のために申し訳ありませんが、これは私の完全な実装である):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    //// Some stuff //// 
    [[Reachability reachabilityWithHostname:@"apple.com"] startNotifier]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil]; 
} 
- (void)reachabilityChanged:(NSNotification *)note 
{ 
    if ([[note object] isReachable]) { 
     CAKeyframeAnimation *scale = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; 
     [scale setValues:[NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:0.0], nil]]; 
     [scale setDuration:0.3]; 
     [scale setRemovedOnCompletion:NO]; 

     [[offlineView layer] setTransform:CATransform3DMakeScale(0, 0, 1.0)]; 
     [[offlineView layer] addAnimation:scale forKey:@"scale"]; 
     [[offlineView layer] setTransform:CATransform3DIdentity]; 

     [UIView animateWithDuration:0.3 animations:^{ 
      [offlineView setAlpha:0]; 
     } completion:^(BOOL finished){ 
      if (finished) { 
       [offlineView removeFromSuperview]; 
      } 
     }]; 

     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES]; 
    } 
    else { 
     CGRect screenFrame = CGRectMake(0, 0, 320, 480); 

     offlineView = [[UIView alloc] initWithFrame:screenFrame]; 
     [offlineView setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.7]]; 
     [offlineView setAlpha:0]; 

     offlineLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)]; 
     [offlineLabel setFont:[UIFont fontWithName:@"Verdana" size:30.0]]; 
     [offlineLabel setBackgroundColor:[UIColor clearColor]]; 
     [offlineLabel setTextAlignment:UITextAlignmentCenter]; 
     [offlineLabel setTextColor:[UIColor whiteColor]]; 
     [offlineLabel setCenter:[offlineView center]]; 
     [offlineLabel setText:@"OFFLINE"]; 

     [offlineView addSubview:offlineLabel]; 
     [[self window] addSubview:offlineView]; 

     [UIView animateWithDuration:0.3 animations:^{ 
      [offlineView setAlpha:1.0]; 
     }]; 

     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES]; 
    } 
} 
+0

私はこの方法を使いましたが、私はあなたに警告します。通知センターはnotifを「ランダム」な順序で配信します。したがって、1つのViewControllerがそれを取得し、後で別のViewControllerを使用すると、アプリケーションで不一致が発生します。たぶんあなたは2つのnotifの間で動くでしょう:ViewControllerで "online"を見て、もう一つは "offline"を参照してください... 私は、AppDelegateという1つのクラスしか登録しておらず、クラス。すべてのクラスについて一貫したビューが表示されるようになりました。 – malaba

+0

@malaba - あなたはまったく正しい!私はAppDelegateからの到達可能性を管理しています。 –

+2

あなたは 'RKReachabilityDidChangeNotification'に登録し、' RKReachabilityObserver'でRestKitを使うことができます。 – malaba

0

RestKitのバージョンを確認してください。 RestKitの新しいバージョンでは、キャッシュされたデータを管理対象オブジェクトストアから取得するアプローチが少し変更されています。 私はこのマシンにこの例はありません。しかし、もう少し助けが必要な場合(これはかなり古い質問ですので)返信してください。

関連する問題