我在使用领域检索数据时遇到了问题。我想做的是缓存数据,以便我可以在用户首次加载应用程序或用户没有互联网连接时使用它。以下是我想做的逻辑。
来自fb api的请求 - > fb返回10个数据 - >显示返回的数据和缓存返回的数据 - >如果用户没有互联网连接显示缓存数据,或者用户有互联网连接获取新数据。
下面是我的代码:
FBVideo.h
#import <Realm/Realm.h>
@interface FBVideo : RLMObject
@property (nonatomic, strong) NSString *pageBefore;
@property (nonatomic, strong) NSString *pageAfter;
@property (nonatomic, strong) NSString *thumbnailsURI;
@property (nonatomic, strong) NSString *titleDescription;
@property NSString *id;
@end
FBVideo.m
#import "FBVideo.h"
@implementation FBVideo
+ (NSString *)primaryKey {
return @"id";
}
// Specify default values for properties
+ (NSDictionary *)defaultPropertyValues {
return @{@"pageBefore":@"", @"pageAfter":@"", @"thumbnailsURI":@"", @"titleDescription":@""};
}
+ (NSArray *)ignoredProperties {
return @[];
}
@end
PageVideosCVC.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import "FBVideo.h"
@interface PageVideosCVC : UICollectionViewController
@property (strong, nonatomic) NSMutableArray *videoArray;
@property (strong, nonatomic) NSString *pageID;
@property (strong, nonatomic) NSString *pageName;
@property (strong, nonatomic) MPMoviePlayerController *playerController;
@property (assign, nonatomic) CATransform3D initialTransformation;
@property (nonatomic, strong) NSMutableSet *shownIndexes;
//@property (strong, nonatomic) FBVideo *fbVideoRealm;
@end
PageVideosCVC.m
#import "PageVideosCVC.h"
#import "facebook.h"
#import "MBProgressHUD.h"
#import "Reachability.h"
#import <AFNetworking/AFNetworking.h>
#import <AVFoundation/AVFoundation.h>
#import <SDWebImage/UIImageView+WebCache.h>
#import <QuartzCore/QuartzCore.h>
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
@interface PageVideosCVC () <UICollectionViewDataSource,UICollectionViewDelegate> {
NSString *pageBefore;
NSString *pageAfter;
NSString *thumbnailsURI;
Reachability *internetReachable;
NSDictionary *videoInfoToSaveInRealm;
// RLMResults *videoResultsFrom
}
@end
@implementation PageVideosCVC
@synthesize videoArray;
static NSString * const reuseIdentifier = @"Cell";
- (void) viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
videoArray = [NSMutableArray array];
/* Make a card effect, rotate the angle of the collectionviewcell to -15
1) Start with an identity transform, which is a fancy math term for “do nothing.”
2) Call CATransform3DRotate to apply a rotation of -15 degrees (in radians), where the negative value indicates a clockwise rotation.
3) Apply the rotation around the axis 0.0, 0.0, 1.0; this represents the z-axis, where x=0, y=0, and z=1.
4) Applying just the rotation to the card isn’t enough, as this simply rotates the card about its center. To make it look like it’s tipped over on a corner, add a translation or shift where the negative values indicate a shift up and to the left.
*/
CGFloat rotationAngleDegrees = -15;
CGFloat rotationAngleRadians = rotationAngleDegrees * (M_PI/180);
CGPoint offsetPositioning = CGPointMake(-20, -20);
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, rotationAngleRadians, 0.0, 0.0, 1.0);
transform = CATransform3DTranslate(transform, offsetPositioning.x, offsetPositioning.y, 0.0);
_initialTransformation = transform;
_shownIndexes = [NSMutableSet set];
}
- (void)viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
navBar.barTintColor = UIColorFromRGB(0x266593);
// Altering the font style of the navigation bar title
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
shadow.shadowOffset = CGSizeMake(0, 1);
[[UINavigationBar appearance] setTranslucent:NO];
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], NSForegroundColorAttributeName,
shadow, NSShadowAttributeName,
[UIFont fontWithName:@"HelveticaNeue-CondensedBlack" size:21.0], NSFontAttributeName, nil]];
[self.view addSubview: navBar];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"Down Arrow.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(backButtonTapped:)];
// UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:@"Back"
// style:UIBarButtonItemStylePlain
// target:self
// action:@selector(backButtonTapped:)];
[cancelItem setTintColor:[UIColor whiteColor]];
// UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:@"Done"
// style:UIBarButtonItemStyleBordered
// target:self action:nil];
NSString *selectedPageName = [[NSString alloc] initWithFormat:@"%@", self.pageName];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:selectedPageName];
// navItem.rightBarButtonItem = doneItem;
navItem.leftBarButtonItem = cancelItem;
navBar.items = [NSArray arrayWithObjects: navItem,nil];
[UIBarButtonItem appearance].tintColor = [UIColor blueColor];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[self loadVideo:@"a" pagesID:self.pageID];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if ([pageBefore isEqual:pageBefore]) {
return videoArray.count;
}
return videoArray.count + 1;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [videoArray count] - 1) {
NSLog(@"page after : %@", pageAfter);
[self loadVideo:pageAfter pagesID:self.pageID];
}
if (![self.shownIndexes containsObject:indexPath]) {
[self.shownIndexes addObject:indexPath];
// Transform collectionviewcell layer
UIView *card = [(UICollectionViewCell*)cell contentView];
card.layer.transform = self.initialTransformation;
card.layer.opacity = 0.5;
[UIView animateWithDuration:0.5 animations:^{
card.layer.transform = CATransform3DIdentity;
card.layer.opacity = 1;
}];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
__weak typeof(self) weakSelf = self;
if (indexPath.row == [videoArray count]) {
NSLog(@"this is last cell, later make it UIActivityIndicatorView");
} else {
// RLMResults *objects;
//
// objects = [FBVideo allObjects];
// FBVideo *fbVideoRealm = objects[indexPath.row];
//
// UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
// NSURL *thumbnailImage = [NSURL URLWithString:fbVideoRealm.thumbnailsURI];
// [imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:@"placeholder.jpg"]];
//
// UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
// titleDescription.text = fbVideoRealm.titleDescription;
NSDictionary *videoData = weakSelf.videoArray[indexPath.row];
NSDictionary *videoThumbnails = [videoData valueForKey:@"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:@"data"][0];
thumbnailsURI = [thumbnailsData valueForKey:@"uri"];
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:thumbnailsURI];
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:@"placeholder.jpg"]];
UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
titleDescription.text = videoData[@"description"];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *videoSource = videoArray[indexPath.row];
NSURL *videoURL = [NSURL URLWithString:[videoSource valueForKey:@"source"]];
self.playerController = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[[self.playerController view] setFrame:[self.view bounds]]; // Frame must match parent view
[self.view addSubview:[self.playerController view]];
self.playerController.movieSourceType = MPMovieSourceTypeStreaming;
self.playerController.controlStyle = MPMovieControlStyleFullscreen;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doneButtonClick:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.playerController play];
// Play the video using AVPlayer iOS9 above
// AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// playerLayer.frame = self.view.bounds;
// [self.view.layer addSublayer:playerLayer];
// [player play];
}
- (void)doneButtonClick:(NSNotification*)aNotification{
NSNumber *reason = [aNotification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonUserExited) {
// Your done button action here
// [self dismissViewControllerAnimated:YES completion:nil];
NSLog(@"done button tapped");
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[self.playerController stop];
[self.playerController.view removeFromSuperview];
}
}
- (IBAction)backButtonTapped:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Helper Methods
- (void)loadVideo:(NSString*)currentPage pagesID:(NSString*)pagesID{
__weak typeof(self) weakSelf = self;
NSString *fbToken = [facebook currentFBAccessToken];
NSString *fbNextVideoURL = [NSString stringWithFormat:@"https://graph.facebook.com/v2.5/%@/videos?access_token=%@&pretty=0&fields=source,description,thumbnails.limit(1),length&limit=10&after=%@", pagesID, fbToken, currentPage];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:fbNextVideoURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *videoDict = [[NSDictionary alloc] initWithDictionary:responseObject];
if (responseObject != nil) {
[weakSelf.videoArray addObjectsFromArray:[videoDict valueForKeyPath:@"data"]];
pageBefore = [videoDict valueForKeyPath:@"paging.cursors.before"];
pageAfter = [videoDict valueForKeyPath:@"paging.cursors.after"];
// Caching pageBefore, pageAfter, thumbnailsURI, titleDescription data to REALM
for (videoInfoToSaveInRealm in weakSelf.videoArray) {
NSDictionary *videoThumbnails = [videoInfoToSaveInRealm valueForKey:@"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:@"data"][0];
[[RLMRealm defaultRealm] transactionWithBlock:^{
[FBVideo createOrUpdateInDefaultRealmWithValue:@{@"id": self.pageID, @"titleDescription": videoInfoToSaveInRealm[@"description"], @"thumbnailsURI": [thumbnailsData valueForKey:@"uri"], @"pageBefore": pageBefore, @"pageAfter": pageAfter}];
}];
[self retrieveDataFromRealm];
}
//NSLog(@"first product's image: %@", (FBVideo *)[FBVideo allObjects]);
// Update UICollectionView UI
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self.collectionView reloadData];
});
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (void)retrieveDataFromRealm {
RLMResults *objects;
objects = [FBVideo allObjects];
FBVideo *fbVideoRealm = [[FBVideo alloc] init];
for (fbVideoRealm in objects) {
// NSLog(@"realm object count : %d", (int)objects.count);
NSLog(@"realm description : %@", fbVideoRealm.titleDescription);
NSLog(@"realm thumbnails URi : %@", fbVideoRealm.thumbnailsURI);
NSLog(@"realm page before : %@", fbVideoRealm.pageBefore);
NSLog(@"realm page after : %@", fbVideoRealm.pageAfter);
};
}
@end
提前谢谢。
答案 0 :(得分:1)
您应该直接在Realm中存储Facebook API响应(不要立即显示),然后您可以按照Realm's "TableView" example中演示的模式使用RLMResults
支持您的UITableView,并且在数据更改时更新表。
由于您将始终以这种方式从Realm加载数据,因此您可以“免费”离线模式。