mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-23 20:31:13 +08:00
Refactored models and cleaned up controllers pretty thoroughly. Moved to higher level abstractions for permissions and such
This commit is contained in:
@@ -6,13 +6,22 @@
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Three20/Three20.h>
|
||||
#import "DBUser.h"
|
||||
#import "DBLoginOrSignUpViewController.h"
|
||||
|
||||
@interface DBAuthenticatedTableViewController : TTTableViewController <DBLoginOrSignupViewControllerDelegate> {
|
||||
BOOL _requiresLoggedInUser;
|
||||
NSNumber* _requiredUserID;
|
||||
DBUser* _requiredUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* The User who we must be logged in as to edit the specified content
|
||||
*/
|
||||
@property (nonatomic, retain) DBUser* requiredUser;
|
||||
|
||||
/**
|
||||
* Presents the Login controller if the current User is not authenticated
|
||||
*/
|
||||
- (void)presentLoginViewControllerIfNecessary;
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,39 +11,25 @@
|
||||
|
||||
@implementation DBAuthenticatedTableViewController
|
||||
|
||||
@synthesize requiredUser = _requiredUser;
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:DBUserDidLoginNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
[super loadView];
|
||||
|
||||
// Check if we are authenticated. If not, pop in login view controller.
|
||||
if (_requiresLoggedInUser) {
|
||||
BOOL isAuthenticated = NO;
|
||||
if (_requiredUserID &&
|
||||
[[DBUser currentUser] isLoggedIn] &&
|
||||
[[DBUser currentUser].userID isEqualToNumber:_requiredUserID]) {
|
||||
isAuthenticated = YES;
|
||||
// TODO: Move this isAuthenticated logic into the model!
|
||||
} else if (_requiredUserID == nil &&
|
||||
[[DBUser currentUser] isLoggedIn]) {
|
||||
isAuthenticated = YES;
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
// Register for login succeeded notification. populate view.
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidLogin:) name:DBUserDidLoginNotification object:nil];
|
||||
|
||||
DBLoginOrSignUpViewController* loginViewController = (DBLoginOrSignUpViewController*)TTOpenURL(@"db://login");
|
||||
loginViewController.delegate = self;
|
||||
}
|
||||
- (void)presentLoginViewControllerIfNecessary {
|
||||
if (NO == [[DBUser currentUser] isLoggedIn]) {
|
||||
// Register for login succeeded notification. populate view.
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidLogin:) name:DBUserDidLoginNotification object:nil];
|
||||
|
||||
DBLoginOrSignUpViewController* loginViewController = (DBLoginOrSignUpViewController*) TTOpenURL(@"db://login");
|
||||
loginViewController.delegate = self;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)userDidLogin:(NSNotification*)note {
|
||||
// check to ensure the user that logged in is allowed to acces this controller.
|
||||
if (_requiredUserID && [[DBUser currentUser].userID isEqualToNumber:_requiredUserID]) {
|
||||
// Check to ensure the User who logged in is allowed to access this controller.
|
||||
if ([[DBUser currentUser] isEqual:self.requiredUser]) {
|
||||
[self invalidateModel];
|
||||
} else {
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
self.autoresizesForKeyboard = YES;
|
||||
self.tableViewStyle = UITableViewStyleGrouped;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -139,6 +140,7 @@
|
||||
} else if (textField == _passwordConfirmationField) {
|
||||
[self loginOrSignup];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -153,7 +155,6 @@
|
||||
}
|
||||
|
||||
- (void)user:(DBUser*)user didFailLoginWithError:(NSError*)error {
|
||||
// TTAlert([error localizedDescription]);
|
||||
[[[[UIAlertView alloc] initWithTitle:@"Error"
|
||||
message:[error localizedDescription]
|
||||
delegate:nil
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DBAuthenticatedTableViewController.h"
|
||||
#import "DBPost.h"
|
||||
#import "DBTopic.h"
|
||||
|
||||
@interface DBPostTableViewController : DBAuthenticatedTableViewController <RKObjectLoaderDelegate, TTTextEditorDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
|
||||
DBPost* _post;
|
||||
DBTopic* _topic;
|
||||
|
||||
TTTextEditor* _bodyTextEditor;
|
||||
TTImageView* _currentAttachmentImageView;
|
||||
@@ -21,4 +19,15 @@
|
||||
UIImage* _newAttachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Post we are viewing
|
||||
*/
|
||||
@property (nonatomic, readonly) DBPost* post;
|
||||
|
||||
/**
|
||||
* Three20 URL dispatched intializer. Used to create a new Post against a Topic with
|
||||
* the specified primary key value.
|
||||
*/
|
||||
- (id)initWithTopicID:(NSString*)topicID;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,9 +9,12 @@
|
||||
#import "DBPostTableViewController.h"
|
||||
#import <Three20/Three20+Additions.h>
|
||||
#import "DBUser.h"
|
||||
#import "DBTopic.h"
|
||||
|
||||
@implementation DBPostTableViewController
|
||||
|
||||
@synthesize post = _post;
|
||||
|
||||
- (id)initWithPostID:(NSString*)postID {
|
||||
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
|
||||
_post = [[DBPost objectWithPrimaryKeyValue:postID] retain];
|
||||
@@ -22,8 +25,10 @@
|
||||
|
||||
- (id)initWithTopicID:(NSString*)topicID {
|
||||
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
|
||||
// TODO: Why are we using topic ID here?
|
||||
_topic = [[DBTopic objectWithPrimaryKeyValue:topicID] retain];
|
||||
DBTopic* topic = [[DBTopic objectWithPrimaryKeyValue:topicID] retain];
|
||||
_post = [[DBPost object] retain];
|
||||
_post.topicID = topic.topicID;
|
||||
_post.topic = topic;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -31,53 +36,44 @@
|
||||
|
||||
- (void)dealloc {
|
||||
TT_RELEASE_SAFELY(_post);
|
||||
TT_RELEASE_SAFELY(_topic);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// TODO: Move this into the model
|
||||
- (BOOL)isNewRecord {
|
||||
return [[_post postID] intValue] == 0;
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
TT_RELEASE_SAFELY(_bodyTextEditor);
|
||||
|
||||
[[TTNavigator navigator].URLMap removeURL:@"db://updateAttachment"];
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
[super loadView];
|
||||
|
||||
self.tableViewStyle = UITableViewStyleGrouped;
|
||||
self.autoresizesForKeyboard = YES;
|
||||
self.variableHeightRows = YES;
|
||||
|
||||
[[TTNavigator navigator].URLMap from:@"db://updateAttachment" toObject:self selector:@selector(updateAttachment)];
|
||||
|
||||
if (nil == _post) {
|
||||
_post = [[DBPost object] retain];
|
||||
_post.topicID = _topic.topicID;
|
||||
}
|
||||
|
||||
_requiresLoggedInUser = YES;
|
||||
|
||||
[super loadView];
|
||||
[[TTNavigator navigator].URLMap from:@"db://updateAttachment" toObject:self selector:@selector(updateAttachment)];
|
||||
|
||||
_bodyTextEditor = [[TTTextEditor alloc] initWithFrame:CGRectMake(0, 0, 300, 120)];
|
||||
_bodyTextEditor.font = [UIFont systemFontOfSize:12];
|
||||
_bodyTextEditor.autoresizesToText = NO;
|
||||
_bodyTextEditor.delegate = self;
|
||||
_bodyTextEditor.text = _post.body;
|
||||
|
||||
// Ensure we are authenticated
|
||||
NSLog(@"All the users are: %@", [DBUser allObjects]);
|
||||
[self presentLoginViewControllerIfNecessary];
|
||||
}
|
||||
|
||||
- (void)createModel {
|
||||
// TODO: Move this into the model: [self.currentUser canModifyObject:_post]
|
||||
BOOL isAuthorizedUser = [[DBUser currentUser].userID isEqualToNumber:_post.userID] || [self isNewRecord];
|
||||
|
||||
BOOL isAuthorizedUser = [[DBUser currentUser] canModifyObject:_post];
|
||||
NSMutableArray* items = [NSMutableArray array];
|
||||
|
||||
// Attachment item.
|
||||
if (isAuthorizedUser) {
|
||||
[items addObject:[TTTableControlItem itemWithCaption:@"" control:(UIControl*)_bodyTextEditor]];
|
||||
|
||||
if (_newAttachment) {
|
||||
// has new attachment. show it. allow update.
|
||||
[items addObject:[TTTableImageItem itemWithText:@"Tap to Replace Image" imageURL:@"" defaultImage:_newAttachment URL:@"db://updateAttachment"]];
|
||||
@@ -96,7 +92,7 @@
|
||||
[items addObject:[TTTableImageItem itemWithText:@"" imageURL:url URL:nil]];
|
||||
}
|
||||
|
||||
if ([self isNewRecord]) {
|
||||
if ([self.post isNewRecord]) {
|
||||
self.title = @"New Post";
|
||||
[items addObject:[TTTableButton itemWithText:@"Create" delegate:self selector:@selector(createButtonWasPressed:)]];
|
||||
} else {
|
||||
@@ -108,8 +104,9 @@
|
||||
self.title = @"Post";
|
||||
}
|
||||
}
|
||||
|
||||
NSString* byLine = @"";
|
||||
if (![self isNewRecord]) {
|
||||
if (![self.post isNewRecord]) {
|
||||
NSString* username = (isAuthorizedUser ? @"me" : _post.username);
|
||||
byLine = [NSString stringWithFormat:@"posted by %@", username];
|
||||
}
|
||||
@@ -126,19 +123,19 @@
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)createButtonWasPressed:(id)sender {
|
||||
_post.body = _bodyTextEditor.text;
|
||||
_post.newAttachment = _newAttachment;
|
||||
[[RKObjectManager sharedManager] postObject:_post delegate:self];
|
||||
self.post.body = _bodyTextEditor.text;
|
||||
self.post.newAttachment = _newAttachment;
|
||||
[[RKObjectManager sharedManager] postObject:self.post delegate:self];
|
||||
}
|
||||
|
||||
- (void)updateButtonWasPressed:(id)sender {
|
||||
_post.body = _bodyTextEditor.text;
|
||||
_post.newAttachment = _newAttachment;
|
||||
[[RKObjectManager sharedManager] putObject:_post delegate:self];
|
||||
self.post.body = _bodyTextEditor.text;
|
||||
self.post.newAttachment = _newAttachment;
|
||||
[[RKObjectManager sharedManager] putObject:self.post delegate:self];
|
||||
}
|
||||
|
||||
- (void)destroyButtonWasPressed:(id)sender {
|
||||
[[RKObjectManager sharedManager] deleteObject:_post delegate:self];
|
||||
[[RKObjectManager sharedManager] deleteObject:self.post delegate:self];
|
||||
}
|
||||
|
||||
#pragma mark UIImagePickerControllerDelegate methods
|
||||
@@ -156,18 +153,20 @@
|
||||
#pragma mark RKObjectLoaderDelegate methods
|
||||
|
||||
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
|
||||
// TODO: RKLog helpers?
|
||||
NSLog(@"Loaded Objects: %@", objects);
|
||||
NSLog(@"Status Code: %d", objectLoader.response.statusCode);
|
||||
// Post notification telling view controllers to reload.
|
||||
// TODO
|
||||
// TODO: Generalize this notification
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kObjectCreatedUpdatedOrDestroyedNotificationName object:objects];
|
||||
// dismiss.
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
|
||||
[[[[UIAlertView alloc] initWithTitle:@"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease] show];
|
||||
[[[[UIAlertView alloc] initWithTitle:@"Error"
|
||||
message:[error localizedDescription]
|
||||
delegate:nil
|
||||
cancelButtonTitle:@"OK"
|
||||
otherButtonTitles:nil] autorelease] show];
|
||||
}
|
||||
|
||||
#pragma mark TTTextEditorDelegate methods
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
* Displays a table of Posts within a given Topic
|
||||
*/
|
||||
@interface DBPostsTableViewController : DBResourceListTableViewController {
|
||||
// TODO: Just use a Topic
|
||||
NSString* _topicID;
|
||||
DBTopic* _topic;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,17 +6,21 @@
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <RestKit/Three20/Three20.h>
|
||||
#import "DBPostsTableViewController.h"
|
||||
#import "DBPost.h"
|
||||
#import <RestKit/Three20/Three20.h>
|
||||
#import "DBUser.h"
|
||||
|
||||
@implementation DBPostsTableViewController
|
||||
|
||||
@synthesize topic = _topic;
|
||||
|
||||
- (id)initWithTopicID:(NSString*)topicID {
|
||||
if (self = [super initWithStyle:UITableViewStylePlain]) {
|
||||
_topicID = [topicID retain];
|
||||
_topic = [[DBTopic objectWithPrimaryKeyValue:topicID] retain];
|
||||
|
||||
self.title = @"Posts";
|
||||
|
||||
_resourcePath = RKMakePathWithObject(@"/topics/(topicID)/posts", self.topic);
|
||||
[_resourcePath retain];
|
||||
_resourceClass = [DBPost class];
|
||||
@@ -25,7 +29,7 @@
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_topicID release];
|
||||
[_topic release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -33,12 +37,9 @@
|
||||
[super loadView];
|
||||
|
||||
self.variableHeightRows = YES;
|
||||
|
||||
UIBarButtonItem* newItem = [[[UIBarButtonItem alloc]
|
||||
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
|
||||
target:self
|
||||
action:@selector(addButtonWasPressed:)] autorelease];
|
||||
self.navigationItem.rightBarButtonItem = newItem;
|
||||
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
|
||||
target:self
|
||||
action:@selector(addButtonWasPressed:)] autorelease];
|
||||
}
|
||||
|
||||
- (void)addButtonWasPressed:(id)sender {
|
||||
@@ -47,9 +48,8 @@
|
||||
}
|
||||
|
||||
- (void)createModel {
|
||||
if (nil == [DBTopic objectWithPrimaryKeyValue:_topicID]) {
|
||||
// TODO: Cleanup???
|
||||
// this topic was deleted or something.
|
||||
if (nil == self.topic) {
|
||||
// No topic was found -- must have been deleted. Pop the view controller
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
return;
|
||||
}
|
||||
@@ -66,23 +66,19 @@
|
||||
NSMutableArray* topicItems = [NSMutableArray arrayWithCapacity:2];
|
||||
|
||||
[topicItems addObject:[TTTableTextItem itemWithText:self.topic.name]];
|
||||
// only add edit item if there is no current user (lazy login) or
|
||||
// the current user id == topic user id.
|
||||
NSNumber* topicUserId = self.topic.userID;
|
||||
// if topicUserId is nil, the topic has no user for some reason (perhaps they got deleted).
|
||||
// TODO: Permissions pattern
|
||||
if ([DBUser currentUser] == nil ||
|
||||
(topicUserId && [[DBUser currentUser].userID isEqualToNumber:topicUserId])) {
|
||||
NSString* editURL = [NSString stringWithFormat:@"db://topics/%@/edit", _topicID];
|
||||
|
||||
// Add edit item if there is no current User to trigger lazy login or if the User owns the Topic
|
||||
if (NO == [[DBUser currentUser] isLoggedIn] || [[DBUser currentUser] canModifyObject:self.topic]) {
|
||||
NSString* editURL = RKMakePathWithObject(@"db://topics/(topicID)/edit", self.topic);
|
||||
[topicItems addObject:[TTTableTextItem itemWithText:@"Edit" URL:editURL]];
|
||||
}
|
||||
|
||||
for (DBPost* post in model.objects) {
|
||||
NSString* url = [NSString stringWithFormat:@"db://posts/%@", post.postID];
|
||||
NSString* URL = RKMakePathWithObject(@"db://posts/(postID)", post);
|
||||
NSString* imageURL = post.attachmentPath;
|
||||
TTTableImageItem* item = [TTTableImageItem itemWithText:post.body
|
||||
imageURL:imageURL
|
||||
URL:url];
|
||||
URL:URL];
|
||||
[postItems addObject:item];
|
||||
}
|
||||
|
||||
@@ -95,8 +91,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (DBTopic*)topic {
|
||||
return [DBTopic objectWithPrimaryKeyValue:_topicID];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,4 +15,9 @@
|
||||
DBTopic* _topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Topic that is being viewed
|
||||
*/
|
||||
@property (nonatomic, readonly) DBTopic* topic;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,10 +12,22 @@
|
||||
|
||||
@implementation DBTopicViewController
|
||||
|
||||
@synthesize topic = _topic;
|
||||
|
||||
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
|
||||
if (self = [super initWithNavigatorURL:URL query:query]) {
|
||||
_topic = [[DBTopic object] retain];
|
||||
_topic.name = @"";
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithTopicID:(NSString*)topicID {
|
||||
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
|
||||
_topic = [[DBTopic objectWithPrimaryKeyValue:topicID] retain];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -29,19 +41,15 @@
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
self.tableViewStyle = UITableViewStyleGrouped;
|
||||
|
||||
if (nil == _topic) {
|
||||
_topic = [[DBTopic object] retain];
|
||||
_topic.name = @"";
|
||||
}
|
||||
|
||||
_requiresLoggedInUser = YES;
|
||||
if (![_topic isNewRecord]) {
|
||||
_requiredUserID = _topic.userID;
|
||||
}
|
||||
|
||||
[super loadView];
|
||||
|
||||
self.tableViewStyle = UITableViewStyleGrouped;
|
||||
|
||||
if (![self.topic isNewRecord]) {
|
||||
// Ensure we are logged in as the User who created the Topic
|
||||
self.requiredUser = self.topic.user;
|
||||
}
|
||||
[self presentLoginViewControllerIfNecessary];
|
||||
|
||||
_topicNameField = [[UITextField alloc] initWithFrame:CGRectZero];
|
||||
_topicNameField.placeholder = @"topic name";
|
||||
@@ -50,10 +58,10 @@
|
||||
- (void)createModel {
|
||||
NSMutableArray* items = [NSMutableArray array];
|
||||
|
||||
_topicNameField.text = _topic.name;
|
||||
_topicNameField.text = self.topic.name;
|
||||
[items addObject:[TTTableControlItem itemWithCaption:@"Name" control:_topicNameField]];
|
||||
|
||||
if ([_topic isNewRecord]) {
|
||||
if ([self.topic isNewRecord]) {
|
||||
self.title = @"New Topic";
|
||||
[items addObject:[TTTableButton itemWithText:@"Create" delegate:self selector:@selector(createButtonWasPressed:)]];
|
||||
} else {
|
||||
@@ -61,23 +69,24 @@
|
||||
[items addObject:[TTTableButton itemWithText:@"Update" delegate:self selector:@selector(updateButtonWasPressed:)]];
|
||||
[items addObject:[TTTableButton itemWithText:@"Delete" delegate:self selector:@selector(destroyButtonWasPressed:)]];
|
||||
}
|
||||
|
||||
self.dataSource = [TTListDataSource dataSourceWithItems:items];
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)createButtonWasPressed:(id)sender {
|
||||
_topic.name = _topicNameField.text;
|
||||
[[RKObjectManager sharedManager] postObject:_topic delegate:self];
|
||||
self.topic.name = _topicNameField.text;
|
||||
[[RKObjectManager sharedManager] postObject:self.topic delegate:self];
|
||||
}
|
||||
|
||||
- (void)updateButtonWasPressed:(id)sender {
|
||||
_topic.name = _topicNameField.text;
|
||||
[[RKObjectManager sharedManager] putObject:_topic delegate:self];
|
||||
self.topic.name = _topicNameField.text;
|
||||
[[RKObjectManager sharedManager] putObject:self.topic delegate:self];
|
||||
}
|
||||
|
||||
- (void)destroyButtonWasPressed:(id)sender {
|
||||
[[RKObjectManager sharedManager] deleteObject:_topic delegate:self];
|
||||
[[RKObjectManager sharedManager] deleteObject:self.topic delegate:self];
|
||||
}
|
||||
|
||||
#pragma mark RKObjectLoaderDelegate methods
|
||||
@@ -93,7 +102,11 @@
|
||||
}
|
||||
|
||||
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
|
||||
[[[[UIAlertView alloc] initWithTitle:@"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease] show];
|
||||
[[[[UIAlertView alloc] initWithTitle:@"Error"
|
||||
message:[error localizedDescription]
|
||||
delegate:nil
|
||||
cancelButtonTitle:@"OK"
|
||||
otherButtonTitles:nil] autorelease] show];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DBResourceListTableViewController.h"
|
||||
|
||||
@interface DBTopicsTableViewController : DBResourceListTableViewController {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Three20/Three20+Additions.h>
|
||||
#import "DBTopicsTableViewController.h"
|
||||
#import "DBTopic.h"
|
||||
#import <Three20/Three20+Additions.h>
|
||||
#import "DBUser.h"
|
||||
|
||||
@implementation DBTopicsTableViewController
|
||||
@@ -17,6 +17,7 @@
|
||||
if (self = [super initWithNavigatorURL:URL query:query]) {
|
||||
self.title = @"Topics";
|
||||
_tableTitleHeaderLabel.text = @"Recent Topics";
|
||||
|
||||
_resourcePath = [@"/topics" retain];
|
||||
_resourceClass = [DBTopic class];
|
||||
}
|
||||
@@ -27,19 +28,21 @@
|
||||
[super createModel];
|
||||
|
||||
UIBarButtonItem* item = nil;
|
||||
NSLog(@"Updating model for Topics table! Current User is: %@", [DBUser currentUser]);
|
||||
if ([[DBUser currentUser] isLoggedIn]) {
|
||||
item = [[[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleBordered target:self action:@selector(logoutButtonWasPressed:)] autorelease];
|
||||
item = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleBordered target:self action:@selector(logoutButtonWasPressed:)];
|
||||
}
|
||||
self.navigationItem.leftBarButtonItem = item;
|
||||
[item release];
|
||||
|
||||
UIButton* newButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage* newButtonImage = [UIImage imageNamed:@"add.png"];
|
||||
[newButton setImage:newButtonImage forState:UIControlStateNormal];
|
||||
[newButton addTarget:self action:@selector(addButtonWasPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[newButton setFrame:CGRectMake(0, 0, newButtonImage.size.width, newButtonImage.size.height)];
|
||||
|
||||
UIBarButtonItem* newItem = [[UIBarButtonItem alloc] initWithCustomView:newButton];
|
||||
self.navigationItem.rightBarButtonItem = newItem;
|
||||
[newItem release];
|
||||
}
|
||||
|
||||
- (void)addButtonWasPressed:(id)sender {
|
||||
@@ -47,25 +50,22 @@
|
||||
}
|
||||
|
||||
- (void)logoutButtonWasPressed:(id)sender {
|
||||
NSLog(@"Current user is: %@", [DBUser currentUser]);
|
||||
[[DBUser currentUser] logout];
|
||||
}
|
||||
|
||||
- (void)didLoadModel:(BOOL)firstTime {
|
||||
[super didLoadModel:firstTime];
|
||||
|
||||
RKRequestTTModel* model = (RKRequestTTModel*)self.model;
|
||||
|
||||
NSMutableArray* items = [NSMutableArray arrayWithCapacity:[model.objects count]];
|
||||
|
||||
for(DBTopic* topic in model.objects) {
|
||||
for (DBTopic* topic in model.objects) {
|
||||
NSString* topicPostsURL = RKMakePathWithObject(@"db://topics/(topicID)/posts", topic);
|
||||
[items addObject:[TTTableTextItem itemWithText:topic.name URL:topicPostsURL]];
|
||||
}
|
||||
|
||||
NSLog(@"Items: %@", items);
|
||||
// Ensure that the datasource's model is still the RKRequestTTModel;
|
||||
// Otherwise isOutdated will not work.
|
||||
// TODO: Better fix for this?
|
||||
TTListDataSource* dataSource = [TTListDataSource dataSourceWithItems:items];
|
||||
dataSource.model = model;
|
||||
self.dataSource = dataSource;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// DBContentObject.h
|
||||
// DiscussionBoard
|
||||
//
|
||||
// Created by Blake Watters on 1/20/11.
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <RestKit/RestKit.h>
|
||||
#import <RestKit/CoreData/CoreData.h>
|
||||
#import "DBUser.h"
|
||||
|
||||
/**
|
||||
* Abstract superclass for content models in the Discussion Board. Provides
|
||||
* common property & method definitions for the system
|
||||
*/
|
||||
@interface DBContentObject : RKManagedObject {
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Common content properties
|
||||
|
||||
/**
|
||||
* A timestamp of when the object was created
|
||||
*/
|
||||
@property (nonatomic, retain) NSDate* createdAt;
|
||||
|
||||
/**
|
||||
* A timestamp of when the object was last modified
|
||||
*/
|
||||
@property (nonatomic, retain) NSDate* updatedAt;
|
||||
|
||||
/**
|
||||
* The numeric primary key of the User who created this object
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* userID;
|
||||
|
||||
/**
|
||||
* The username of the User who created this object
|
||||
*/
|
||||
@property (nonatomic, readonly) NSString* username;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Common relationships
|
||||
|
||||
/**
|
||||
* The User who created this object within the Discussion Board.
|
||||
* This is a Core Data relationship to the User object with the
|
||||
* primary key value contained in the userID property
|
||||
*/
|
||||
@property (nonatomic, retain) DBUser* user;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Returns YES when the object does not have a primary key
|
||||
* for the remote system. This indicates that the object is unsaved
|
||||
*/
|
||||
- (BOOL)isNewRecord;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// DBContentObject.m
|
||||
// DiscussionBoard
|
||||
//
|
||||
// Created by Blake Watters on 1/20/11.
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import "DBContentObject.h"
|
||||
|
||||
@implementation DBContentObject
|
||||
|
||||
@dynamic userID;
|
||||
@dynamic createdAt;
|
||||
@dynamic updatedAt;
|
||||
@dynamic user;
|
||||
|
||||
/**
|
||||
* Instructs RestKit to map nested objects to the Core Data
|
||||
* relationship specified
|
||||
*/
|
||||
+ (NSDictionary*)elementToRelationshipMappings {
|
||||
return [NSDictionary dictionaryWithObject:@"user" forKey:@"user"];
|
||||
}
|
||||
|
||||
- (BOOL)isNewRecord {
|
||||
return [[self primaryKeyValue] intValue] == 0;
|
||||
}
|
||||
|
||||
- (NSString*)username {
|
||||
return self.user.username;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -10,12 +10,13 @@
|
||||
#import <RestKit/CoreData/CoreData.h>
|
||||
#import "DBUser.h"
|
||||
#import "DBTopic.h"
|
||||
#import "DBContentObject.h"
|
||||
|
||||
/**
|
||||
* The Post models an individual piece of content posted to
|
||||
* a Topic by a User within the Discussion Board.
|
||||
*/
|
||||
@interface DBPost : RKManagedObject {
|
||||
@interface DBPost : DBContentObject {
|
||||
UIImage* _newAttachment;
|
||||
}
|
||||
|
||||
@@ -46,33 +47,17 @@
|
||||
*/
|
||||
@property (nonatomic, retain) DBTopic* topic;
|
||||
|
||||
/**
|
||||
* The User who created this Post. This is a Core Data relationship
|
||||
* to the User object with the primary key value contained in the userID property
|
||||
*/
|
||||
@property (nonatomic, retain) DBUser* user;
|
||||
|
||||
/**
|
||||
* The numeric primary key to the Topic this Post was made to
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* topicID;
|
||||
|
||||
/**
|
||||
* The numeric primary key to the User this Post was created by
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* userID;
|
||||
|
||||
/**
|
||||
* The numeric primary key identifying this Post in the remote backend. This
|
||||
* is the value used to uniquely identify this Post within the object store.
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* postID;
|
||||
|
||||
/**
|
||||
* The username of the User who created this Post
|
||||
*/
|
||||
@property (nonatomic, retain) NSString* username;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark File Attachment properties
|
||||
|
||||
@@ -106,9 +91,4 @@
|
||||
*/
|
||||
@property (nonatomic, retain) UIImage* newAttachment;
|
||||
|
||||
/**
|
||||
* Returns true if the record has not yet been saved/synced with the server.
|
||||
*/
|
||||
- (BOOL)isNewRecord;
|
||||
|
||||
@end
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
@"attachment_path", @"attachmentPath",
|
||||
@"attachment_updated_at", @"attachmentUpdatedAt",
|
||||
@"body", @"body",
|
||||
@"user_login", @"username",
|
||||
nil];
|
||||
}
|
||||
|
||||
@@ -100,8 +99,4 @@
|
||||
return params;
|
||||
}
|
||||
|
||||
- (BOOL)isNewRecord {
|
||||
return [[self postID] intValue] == 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,15 +6,13 @@
|
||||
// Copyright 2011 Two Toasters. All rights reserved.
|
||||
//
|
||||
|
||||
#import <RestKit/RestKit.h>
|
||||
#import <RestKit/CoreData/CoreData.h>
|
||||
#import "DBUser.h"
|
||||
#import "DBContentObject.h"
|
||||
|
||||
/**
|
||||
* Models a Topic in the Discussion Board. Users can
|
||||
* create Post's on Topics to have discussions.
|
||||
*/
|
||||
@interface DBTopic : RKManagedObject {
|
||||
@interface DBTopic : DBContentObject {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,30 +20,8 @@
|
||||
*/
|
||||
@property (nonatomic, retain) NSString* name;
|
||||
|
||||
/**
|
||||
* A timestamp of when the object was created
|
||||
*/
|
||||
@property (nonatomic, retain) NSDate* createdAt;
|
||||
|
||||
/**
|
||||
* A timestamp of when the object was last modified
|
||||
*/
|
||||
@property (nonatomic, retain) NSDate* updatedAt;
|
||||
|
||||
/**
|
||||
* The username of the User who created this Topic
|
||||
*/
|
||||
@property (nonatomic, retain) NSString* username;
|
||||
|
||||
#pragma mark Relationship properties
|
||||
|
||||
/**
|
||||
* The User who created this Topic within the Discussion Board.
|
||||
* This is a Core Data relationship to the User object with the
|
||||
* primary key value contained in the userID property
|
||||
*/
|
||||
@property (nonatomic, retain) DBUser* user;
|
||||
|
||||
/**
|
||||
* The collection of Post objects that belong to this Topic. This is
|
||||
* a Core Data relationship to the collection of Posts objects
|
||||
@@ -58,14 +34,4 @@
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* topicID;
|
||||
|
||||
/**
|
||||
* The numeric primary key of the User who created this Topic
|
||||
*/
|
||||
@property (nonatomic, retain) NSNumber* userID;
|
||||
|
||||
/**
|
||||
* Returns true if the record has not yet been saved/synced with the server.
|
||||
*/
|
||||
- (BOOL)isNewRecord;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
|
||||
@dynamic topicID;
|
||||
@dynamic name;
|
||||
@dynamic userID;
|
||||
@dynamic createdAt;
|
||||
@dynamic updatedAt;
|
||||
@dynamic username;
|
||||
@dynamic user;
|
||||
@dynamic posts;
|
||||
|
||||
#pragma mark RKObjectMappable methods
|
||||
@@ -27,12 +22,11 @@
|
||||
*/
|
||||
+ (NSDictionary*)elementToPropertyMappings {
|
||||
return [NSDictionary dictionaryWithKeysAndObjects:
|
||||
@"id",@"topicID",
|
||||
@"name",@"name",
|
||||
@"user_id",@"userID",
|
||||
@"created_at",@"createdAt",
|
||||
@"updated_at",@"updatedAt",
|
||||
@"user_login", @"username",
|
||||
@"id", @"topicID",
|
||||
@"name", @"name",
|
||||
@"user_id", @"userID",
|
||||
@"created_at", @"createdAt",
|
||||
@"updated_at", @"updatedAt",
|
||||
nil];
|
||||
}
|
||||
|
||||
@@ -60,8 +54,4 @@
|
||||
return @"topicID";
|
||||
}
|
||||
|
||||
- (BOOL)isNewRecord {
|
||||
return [[self topicID] intValue] == 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import <RestKit/CoreData/CoreData.h>
|
||||
|
||||
// Declared here and defined below
|
||||
@class DBContentObject;
|
||||
@protocol DBUserAuthenticationDelegate;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -86,6 +87,14 @@
|
||||
*/
|
||||
- (void)logout;
|
||||
|
||||
/**
|
||||
* Example of implementing a simple client side permissions system on top of
|
||||
* the data model. Any managed object that has a user relationship will be compared
|
||||
* to self to determine if update operations are permitted. Unsaved objects can be modified
|
||||
* as well.
|
||||
*/
|
||||
- (BOOL)canModifyObject:(DBContentObject*)object;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "DBUser.h"
|
||||
#import "DBContentObject.h"
|
||||
|
||||
// Constants
|
||||
static NSString* const kDBUserCurrentUserIDDefaultsKey = @"kDBUserCurrentUserIDDefaultsKey";
|
||||
@@ -182,6 +183,16 @@ static DBUser* currentUser = nil;
|
||||
return self.singleAccessToken != nil;
|
||||
}
|
||||
|
||||
- (BOOL)canModifyObject:(DBContentObject*)object {
|
||||
if ([object isNewRecord]) {
|
||||
return YES;
|
||||
} else if ([self isLoggedIn] && [self isEqual:object.user]) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
_delegate = nil;
|
||||
[_password release];
|
||||
|
||||
@@ -57,7 +57,9 @@ static NSString* const kDBAccessTokenHTTPHeaderField = @"X-USER-ACCESS-TOKEN";
|
||||
objectManager.objectStore.managedObjectCache = [[DBManagedObjectCache new] autorelease];
|
||||
|
||||
// Set Up Mapper
|
||||
// TODO: Comment
|
||||
RKObjectMapper* mapper = objectManager.mapper;
|
||||
[mapper registerClass:[DBUser class] forElementNamed:@"user"];
|
||||
[mapper registerClass:[DBTopic class] forElementNamed:@"topic"];
|
||||
[mapper registerClass:[DBPost class] forElementNamed:@"post"];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user