mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-02 22:42:45 +08:00
244 lines
6.6 KiB
Objective-C
244 lines
6.6 KiB
Objective-C
//
|
|
// RKObjectLoaderTTModel.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 2/9/10.
|
|
// Copyright 2010 Two Toasters
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#import "RKObjectLoaderTTModel.h"
|
|
#import "RKManagedObjectStore.h"
|
|
#import "NSManagedObject+ActiveRecord.h"
|
|
#import "../Network/Network.h"
|
|
|
|
|
|
static NSTimeInterval defaultRefreshRate = NSTimeIntervalSince1970;
|
|
static NSString* const kDefaultLoadedTimeKey = @"RKRequestTTModelDefaultLoadedTimeKey";
|
|
|
|
@interface RKObjectLoaderTTModel (Private)
|
|
|
|
@property (nonatomic, readonly) NSString* resourcePath;
|
|
|
|
- (void)clearLoadedTime;
|
|
- (void)saveLoadedTime;
|
|
- (void)modelsDidLoad:(NSArray*)models;
|
|
- (void)load;
|
|
|
|
@end
|
|
|
|
|
|
@implementation RKObjectLoaderTTModel
|
|
|
|
@synthesize objects = _objects;
|
|
@synthesize objectLoader = _objectLoader;
|
|
@synthesize refreshRate = _refreshRate;
|
|
|
|
+ (NSDate*)defaultLoadedTime {
|
|
NSDate* defaultLoadedTime = [[NSUserDefaults standardUserDefaults] objectForKey:kDefaultLoadedTimeKey];
|
|
if (defaultLoadedTime == nil) {
|
|
defaultLoadedTime = [NSDate date];
|
|
[[NSUserDefaults standardUserDefaults] setObject:defaultLoadedTime forKey:kDefaultLoadedTimeKey];
|
|
}
|
|
|
|
return defaultLoadedTime;
|
|
}
|
|
|
|
+ (NSTimeInterval)defaultRefreshRate {
|
|
return defaultRefreshRate;
|
|
}
|
|
|
|
+ (void)setDefaultRefreshRate:(NSTimeInterval)newDefaultRefreshRate {
|
|
defaultRefreshRate = newDefaultRefreshRate;
|
|
}
|
|
|
|
+ (id)modelWithObjectLoader:(RKObjectLoader*)objectLoader {
|
|
return [[[self alloc] initWithObjectLoader:objectLoader] autorelease];
|
|
}
|
|
|
|
- (id)initWithObjectLoader:(RKObjectLoader*)objectLoader {
|
|
self = [self init];
|
|
if (self) {
|
|
NSAssert(_objectLoader.isLoading == NO, @"Cannot use an object loader that is being sent");
|
|
NSAssert(_objectLoader.isLoaded == NO, @"Cannot use an object loader that is already loaded");
|
|
_objectLoader = [objectLoader retain];
|
|
_objectLoader.delegate = self;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// NSObject
|
|
|
|
- (id)init {
|
|
self = [super init];
|
|
if (self) {
|
|
self.refreshRate = [RKObjectLoaderTTModel defaultRefreshRate];
|
|
_cacheLoaded = NO;
|
|
_objects = nil;
|
|
_isLoaded = NO;
|
|
_isLoading = NO;
|
|
_emptyReloadAttempted = NO;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
|
|
[_objects release];
|
|
_objects = nil;
|
|
[_objectLoader release];
|
|
_objectLoader = nil;
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// TTModel
|
|
|
|
- (NSString*)resourcePath {
|
|
return self.objectLoader.resourcePath;
|
|
}
|
|
|
|
- (BOOL)isLoaded {
|
|
return _isLoaded;
|
|
}
|
|
|
|
- (BOOL)isLoading {
|
|
return _isLoading;
|
|
}
|
|
|
|
- (BOOL)isLoadingMore {
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL)isOutdated {
|
|
NSTimeInterval sinceNow = [self.loadedTime timeIntervalSinceNow];
|
|
if (![self isLoading] && !_emptyReloadAttempted && _objects && [_objects count] == 0) {
|
|
_emptyReloadAttempted = YES;
|
|
|
|
// TODO: Returning YES from here causes the view to enter an infinite
|
|
// loading state if you switch data sources
|
|
// return YES;
|
|
return NO;
|
|
}
|
|
return (![self isLoading] && (-sinceNow > _refreshRate));
|
|
}
|
|
|
|
- (void)cancel {
|
|
[[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
|
|
[self didCancelLoad];
|
|
}
|
|
|
|
- (void)invalidate:(BOOL)erase {
|
|
// TODO: Note sure how to handle erase...
|
|
[self clearLoadedTime];
|
|
}
|
|
|
|
- (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {
|
|
RKRequestCachePolicy policy = self.objectLoader.cachePolicy;
|
|
if (!(cachePolicy & TTURLRequestCachePolicyDisk)) {
|
|
self.objectLoader.cachePolicy = RKRequestCachePolicyNone;
|
|
}
|
|
[self load];
|
|
self.objectLoader.cachePolicy = policy;
|
|
}
|
|
|
|
- (NSDate*)loadedTime {
|
|
NSDate* loadedTime = [[NSUserDefaults standardUserDefaults] objectForKey:self.resourcePath];
|
|
if (loadedTime == nil) {
|
|
return [RKObjectLoaderTTModel defaultLoadedTime];
|
|
}
|
|
return loadedTime;
|
|
}
|
|
|
|
|
|
|
|
#pragma mark RKModelLoaderDelegate
|
|
|
|
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
|
|
_isLoading = NO;
|
|
[self saveLoadedTime];
|
|
[self modelsDidLoad:objects];
|
|
}
|
|
|
|
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
|
|
_isLoading = NO;
|
|
[self didFailLoadWithError:error];
|
|
}
|
|
|
|
- (void)objectLoaderDidLoadUnexpectedResponse:(RKObjectLoader*)objectLoader {
|
|
_isLoading = NO;
|
|
|
|
// TODO: pass error message?
|
|
NSError* error = [NSError errorWithDomain:RKRestKitErrorDomain code:RKRequestUnexpectedResponseError userInfo:nil];
|
|
[self didFailLoadWithError:error];
|
|
}
|
|
|
|
#pragma mark RKRequestTTModel (Private)
|
|
|
|
// TODO: Can we push this load time into RKRequestCache???
|
|
- (void)clearLoadedTime {
|
|
[[NSUserDefaults standardUserDefaults] removeObjectForKey:self.resourcePath];
|
|
}
|
|
|
|
- (void)saveLoadedTime {
|
|
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.resourcePath];
|
|
}
|
|
|
|
- (void)modelsDidLoad:(NSArray*)models {
|
|
[models retain];
|
|
[_objects release];
|
|
_objects = nil;
|
|
|
|
_objects = models;
|
|
_isLoaded = YES;
|
|
|
|
[self didFinishLoad];
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// public
|
|
|
|
- (void)load {
|
|
Class managedObjectClass = NSClassFromString(@"NSManagedObject");
|
|
RKManagedObjectStore* store = [RKObjectManager sharedManager].objectStore;
|
|
NSArray* cacheFetchRequests = nil;
|
|
if (store.managedObjectCache) {
|
|
cacheFetchRequests = [store.managedObjectCache fetchRequestsForResourcePath:self.resourcePath];
|
|
}
|
|
|
|
// Reset in case we are reusing the object loader (model was reloaded).
|
|
[self.objectLoader reset];
|
|
|
|
if (!store.managedObjectCache || !cacheFetchRequests || _cacheLoaded) {
|
|
_isLoading = YES;
|
|
[self didStartLoad];
|
|
[self.objectLoader send];
|
|
} else if (cacheFetchRequests && !_cacheLoaded && managedObjectClass) {
|
|
NSArray* objects = [managedObjectClass objectsWithFetchRequests:cacheFetchRequests];
|
|
if ([objects count] > 0 && NO == [self isOutdated]) {
|
|
_cacheLoaded = YES;
|
|
[self modelsDidLoad:objects];
|
|
} else {
|
|
_isLoading = YES;
|
|
[self didStartLoad];
|
|
[self.objectLoader send];
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|