我正在为iPad开发一个应用程序,用户可以在其中添加和删除UICollectionView中的项目。
这是我的整个ViewController代码:
#import "ProjectsViewController.h"
#import "DetailViewController.h"
#import "MasterViewController.h"
#import "MyManager.h"
@interface ProjectsViewController ()
{
// Declare variables
NSArray *projects;
NSString *selectedProject;
NSMutableArray *_objects;
BOOL deleteAlert;
int editedProjects;
}
@property (weak, nonatomic) IBOutlet UICollectionView *myCollectionView;
@end
@implementation ProjectsViewController
{
// Declare variables
NSString *deletedProject;
}
@synthesize prepareButton, aboutButton, createButton, editButton, editMode;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[_projectsCollectionView registerNib:[UINib nibWithNibName:@"Cell" bundle:nil] forCellWithReuseIdentifier:@"Cell"];
// Configure the style of the three big buttons
prepareButton.layer.cornerRadius = 7;
prepareButton.layer.borderWidth = 1;
prepareButton.layer.borderColor = [UIColor blueColor].CGColor;
aboutButton.layer.cornerRadius = 7;
aboutButton.layer.borderWidth = 1;
aboutButton.layer.borderColor = [UIColor blueColor].CGColor;
createButton.layer.cornerRadius = 7;
createButton.layer.borderWidth = 1;
createButton.layer.borderColor = [UIColor blueColor].CGColor;
editButton.layer.cornerRadius = 7;
editButton.layer.borderWidth = 1;
editButton.layer.borderColor = [UIColor blueColor].CGColor;
// (note - may prefer to use the tintcolor of the control)
// Set up projectsCollectionView
_projectsCollectionView.delegate = self;
_projectsCollectionView.dataSource = self;
#define saveNewProjects @"saveNewProjects"
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resaveProjects:) name:saveNewProjects object:_projectCellClass];
#define deleteProject @"deleteProject"
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deleteProjects:) name:deleteProject object:_projectCellClass];
}
- (void)resaveProjects:(NSNotification *)notification {
// Edit the edited projects and save all again
editedProjects = editedProjects - 1;
NSString *previousName;
NSString *newName;
// Create a MyManger instance
MyManager *sharedManager = [MyManager sharedManager];
// Set the new and old data from MyManager
previousName = sharedManager.oldProjectName;
newName = sharedManager.changedProjectName;
// Find that data in the _objects NSMutableArray
int projectIndex = [_objects indexOfObject:previousName];
[_objects removeObject:previousName];
[_objects insertObject:newName atIndex:projectIndex];
// Resave _objects
[[NSUserDefaults standardUserDefaults] setObject:_objects forKey:@"myProjects"];
// Change the associated subjects to the new key
// Get the subjects
NSMutableArray *projectSubjects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:previousName]];
// Remove the subjects for the previous key
[[NSUserDefaults standardUserDefaults] removeObjectForKey:previousName];
// Save the subjects with the new key
[[NSUserDefaults standardUserDefaults] setObject:projectSubjects forKey:newName];
}
- (void)deleteProjects:(NSNotification *)notification {
// Get the current project
NSString *currentProject = [[MyManager sharedManager] projectForDeletion];
[_objects removeObject:currentProject];
[_projectsCollectionView performBatchUpdates:^{
NSArray *selectedItemsIndexPaths = [_projectsCollectionView indexPathsForSelectedItems];
// Now delete the items from the collection view.
[_projectsCollectionView deleteItemsAtIndexPaths:selectedItemsIndexPaths];
} completion:nil];
// Subtract 1 from editedProjects
editedProjects = editedProjects - 1;
// Set deletedProject
deletedProject = currentProject;
// Save the new objects
[[NSUserDefaults standardUserDefaults] setObject:_objects forKey:@"myProjects"];
// Delete the associated subjects if any
[self deleteAssociatedSubjects];
// HERE
[_projectsCollectionView.collectionViewLayout invalidateLayout];
}
-(void)deleteAssociatedSubjects {
// Delete all the subjects inside this project
NSMutableArray *subjects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:deletedProject]];
int subjectsCount = [subjects count];
for (int i = 0; i < subjectsCount; i++) {
// Delete all the information associated with this subject
// Create 3 save keys
NSString *detailDescriptionKey = [NSString stringWithFormat:@"%@%@", subjects[i], @"-detailDescription"];
NSString *imageDescriptionKey = [NSString stringWithFormat:@"%@%@", subjects[i], @"-imageDescription"];
NSString *imageKey = [NSString stringWithFormat:@"%@%@", subjects[i], @"-image"];
NSString *notesKey = [NSString stringWithFormat:@"%@%@", subjects[i], @"-notes"];
// Delete the information from NSUserDefaults
[[NSUserDefaults standardUserDefaults] removeObjectForKey:deletedProject];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:detailDescriptionKey];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:imageDescriptionKey];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:imageKey];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:notesKey];
// Reload the UICollectionView
_objects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"myProjects"]];
[_projectsCollectionView.collectionViewLayout invalidateLayout];
}
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_objects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"myProjects"]];
[_projectsCollectionView.collectionViewLayout invalidateLayout];
// Put the _objects in the singleton objects
MyManager *sharedManager = [MyManager sharedManager];
sharedManager.objects = _objects;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UICollectionView Datasource
// 1
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
return _objects.count;
}
//
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 1;
}
// 3
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ProjectCell *cell = (ProjectCell *)[cv dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
// Get the amount of subjects
NSMutableArray *subjects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:_objects[indexPath.row
]]];
// Count the subjects
int subjectsCount = [subjects count];
// Set the text and integer value
cell.projectLabel.text = _objects[indexPath.row];
cell.projectCount.text = [NSString stringWithFormat:@"%i",subjectsCount];
// This helps on the animation
cell.layer.shouldRasterize = YES;
return cell;
}
- (IBAction)createButton:(id)sender {
if (editMode == YES) {
// Create a new project
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Edit mode is on" message:@"Please exit edit mode before trying to create a project" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alert show];
} else {
// Create a new project
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New project" message:@"Enter a name for the project" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Add", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (deleteAlert == YES) {
// Set deleteAlert to NO so that we don't mix this UIAlertView
// with the create project UIAlertView
deleteAlert = NO;
// Delete the selected project
} else {
// The user created a new project, add it
if (buttonIndex == 1) {
// Get the input text
NSString *newProject = [[alertView textFieldAtIndex:0] text];
// Initialize objects
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
// Add the new project
if (newProject.length == 0) {
// No input, tell the user
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Enter a name" message: @"Please enter a name first" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show];
} else {
// Check if the entered subject already exists
if ([_objects containsObject:newProject]) {
// The subject already exist, tell the user
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Already exists" message: @"This project already exist, sorry" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show];
} else {
// Ready to add the project, go ahead
[_objects insertObject:newProject atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[_projectsCollectionView insertItemsAtIndexPaths:@[indexPath]];
[[NSUserDefaults standardUserDefaults] setObject:_objects forKey:@"myProjects"];
}
}
} else {
}
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
// Get the tapped cell
ProjectCell *projectCell = (ProjectCell *)[collectionView cellForItemAtIndexPath:indexPath];
if (editMode == YES) {
if (editedProjects == 0) {
// Set deleteAlert to YES so that we don't mix this UIAlertView
// with the create project UIAlertView
deleteAlert = YES;
// Set editMode to YES for the selected cell
[projectCell editProject];
// Prepare the project cell
projectCell.projectTextField.text = projectCell.projectLabel.text;
// Set the firstProjectsViewController to YES
// indicating that the next tapped cell will be second in line
// in case the user decides to edit a new cell without closing this
if (projectCell.editMode == YES) {
// Do nothing
} else if (projectCell.editMode == NO) {
// Resave projects
[self resaveProjects:nil];
}
// Increase editedProjects with 1
editedProjects++;
} else if (editedProjects == 1) {
// Check if the tapped cell is being edited
if (projectCell.editMode == YES) {
// Set deleteAlert to YES so that we don't mix this UIAlertView
// with the create project UIAlertView
deleteAlert = YES;
// Set editMode to YES for the selected cell
[projectCell editProject];
// Prepare the project cell
projectCell.projectTextField.text = projectCell.projectLabel.text;
// Set the firstProjectsViewController to YES
// indicating that the next tapped cell will be second in line
// in case the user decides to edit a new cell without closing this
if (projectCell.editMode == YES) {
// Do nothing
} else if (projectCell.editMode == NO) {
// Resave projects
[self resaveProjects:nil];
}
// It decreases editedProjects with 1, code is "unlocated"
} else if (projectCell.editMode == NO) {
// Tell the user that only 1 project is editable at a time
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Can only edit 1" message:@"You can only edit 1 project at a time" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alert show];
}
}
} else {
// Set the open project
MyManager *sharedManager = [MyManager sharedManager];
sharedManager.openProject = nil;
sharedManager.openProject = @"";
sharedManager.openProject = _objects[indexPath.item];
// Open the selected project and dismiss this ViewController
[self dismissViewControllerAnimated:YES completion:nil];
}
}
- (void)selectedProject {
// The user opened a project - CODE NOT USED ATM
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; // assuming your split view controller in storyboard with name "Main" in project's main bundle
UISplitViewController *splitViewController = (UISplitViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@"splitVC"];
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
// Close the ProjectsViewController and open the selected project
[UIView transitionFromView:[[[[[UIApplication sharedApplication] delegate] window] rootViewController] view]
toView:splitViewController.view
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished) {
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:splitViewController];
}];
}
- (IBAction)editAction:(id)sender {
// Enter editMode leave editMode
if (editMode == YES) {
if (editedProjects == 0) {
// Disable editMode
editMode = NO;
[editButton setTitle:@" Edit " forState:UIControlStateNormal];
} else {
// The user is currently still editing a project, tell him/her
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Edit mode is on" message: @"It looks like you're still editing a project, please finish editing it by tapping on it before trying to exit edit mode" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
} else {
// Enable editMode
editMode = YES;
[editButton setTitle:@" Finish " forState:UIControlStateNormal];
}
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
这是行为:
有没有人知道为什么会发生这种情况以及如何解决这个问题?
非常感谢!
答案 0 :(得分:0)
所以最后一个else块成功地将newProject添加到NSUserDefaults,但是insertItemsAtIndexPaths
实际上没有做任何事情?
使用reloadData
的{{3}}每个{{0}}似乎与UICollectionView无关。也许您在viewWillAppear中的调用与其他更新_projectsCollectionView
的尝试存在冲突...可以将其更改为reloadSections
或invalidateLayout
,以查看是否解决了第一个问题。
对于显示的子视图,如何初始化单元格?这可能是你将editMode设置为&#34; YES&#34;当它应该是&#34; NO。&#34;如果它在出现时出现在单元格本身上的属性&amp;重用它可以使这些视图对另一个项目可见。上面的代码只显示IBAction用于结束编辑,而不是用于启动/切换它,因此很难分辨出这个错误的来源。
您还有以下代码:
-(void)editProject {
if (editMode == YES) {
// disable editMode and update the project cell
editMode = NO;
_projectTextField.hidden = YES;
_editModeLabel.hidden = YES;
_deleteButton.hidden = YES;
// Call editingfinished to save
[self editingFinished:nil]; ...
与调用[self editingFinished:nil];
完全相同
因为它包含完全相同的行。如果您在另一种方法中使用类似的if / else检查来开始编辑,则可能是子视图可见性变得棘手的地方。