如何在切换 ViewController 时保留 UITableView 内容
我在这里和其他网站上查看了许多代码示例,但我找不到与这种特定情况相关的示例,所以我想我会尝试询问。
我的应用程序使用启用了自动引用计数 (ARC) 的实用程序应用程序模板(主视图和反面视图)。
在另一面视图上,我有一个空的 UITableView,其中有一个导航栏,其中有一个“完成”按钮,可让您返回主视图和一个“添加”按钮。单击“添加”按钮会创建一个空行并激活 UIImagePicker。从 UIImagePicker 选择照片后,该照片将传递到新单元格的 imageView 中。
我的问题是,在向表中添加新行后,当我切换到主视图然后返回到翻转视图时,表再次为空。
我认为这与我如何将图像写入 NSMutableArray 有关。
如果有人知道如何防止 UITableView 在切换视图时被擦除,那就太棒了。
提前致谢,
斯蒂芬
AppDelegate.h
#import <UIKit/UIKit.h>
@class MainViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) MainViewController *mainViewController;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "MainViewController.h"
@implementation AppDelegate
@synthesize window = _window;
@synthesize mainViewController = _mainViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.mainViewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end
MainViewController.h
#import "FlipsideViewController.h"
@interface MainViewController : UIViewController <FlipsideViewControllerDelegate>
- (IBAction)showInfo:(id)sender;
@end
MainViewController.m
#import "MainViewController.h"
@implementation MainViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
}
@end
FlipsideViewController.h
#import <UIKit/UIKit.h>
@class FlipsideViewController;
@protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
@end
@interface FlipsideViewController : UIViewController <UIActionSheetDelegate, UIAlertViewDelegate, UIImagePickerControllerDelegate,UINavigationControllerDelegate>
{
NSMutableArray *dataArray;
IBOutlet UITableView *tableView;
IBOutlet UIBarButtonItem *addPhotoButton;
UITableViewCell *addedCell;
UIImage *image;
UIImagePickerController *imagePicker;
}
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, strong) IBOutlet UITableView *tableView;
@property (nonatomic, strong) IBOutlet UIBarButtonItem *addPhotoButton;
@property (nonatomic, strong) UITableViewCell *addedCell;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIImagePickerController *imagePicker;
@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;
- (IBAction)addPhoto:(id)sender;
- (IBAction)done:(id)sender;
@end
FlipsideViewController.m
#import "FlipsideViewController.h"
#import "MainViewController.h"
@implementation FlipsideViewController
@synthesize delegate = _delegate;
@synthesize dataArray, tableView, addPhotoButton, addedCell, image, imagePicker;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataArray = [[NSMutableArray alloc] init];
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.allowsEditing = NO;
self.imagePicker.delegate = self;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
#pragma mark - UITableView delegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellID = @"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.showsReorderControl = YES;
}
return cell;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Actions
- (IBAction)addPhoto:(id)sender
{
[self presentModalViewController:self.imagePicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
// AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
// appDelegate.pickerImage = img;
image = img;
[self dismissModalViewControllerAnimated:YES];
[self.tableView beginUpdates];
[self.dataArray addObject:@""];
NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:(self.dataArray.count - 1) inSection:0]];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
addedCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:(self.dataArray.count - 1) inSection:0]];
addedCell.imageView.image = image;
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
[self.dataArray removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
@end
I've looked over many code samples here and on other sites but I couldn't find examples relevant to this particular situation and so I thought I would try asking.
My application is using the utility application template (a main view and a flipside view) with Automatic Reference Counting (ARC) enabled.
On the flipside view, I have an empty UITableView with a navigation bar with a "Done" button that returns you to the main view and an "Add" button. Clicking the "Add" button creates an empty row and activates the UIImagePicker. After selecting a photo from the UIImagePicker, that photo is passed into the new cell's imageView.
My problem is that, after adding a new row to the table, when I switch to the main view then back to the flipside view, the table is empty again.
I think this has to do with how I am writing the images to my NSMutableArray.
If anyone knows how I can keep the UITableView from getting wiped when switching views, that would be fantastic.
Thanks in advance,
Stephen
AppDelegate.h
#import <UIKit/UIKit.h>
@class MainViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) MainViewController *mainViewController;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "MainViewController.h"
@implementation AppDelegate
@synthesize window = _window;
@synthesize mainViewController = _mainViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.mainViewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end
MainViewController.h
#import "FlipsideViewController.h"
@interface MainViewController : UIViewController <FlipsideViewControllerDelegate>
- (IBAction)showInfo:(id)sender;
@end
MainViewController.m
#import "MainViewController.h"
@implementation MainViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
}
@end
FlipsideViewController.h
#import <UIKit/UIKit.h>
@class FlipsideViewController;
@protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
@end
@interface FlipsideViewController : UIViewController <UIActionSheetDelegate, UIAlertViewDelegate, UIImagePickerControllerDelegate,UINavigationControllerDelegate>
{
NSMutableArray *dataArray;
IBOutlet UITableView *tableView;
IBOutlet UIBarButtonItem *addPhotoButton;
UITableViewCell *addedCell;
UIImage *image;
UIImagePickerController *imagePicker;
}
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, strong) IBOutlet UITableView *tableView;
@property (nonatomic, strong) IBOutlet UIBarButtonItem *addPhotoButton;
@property (nonatomic, strong) UITableViewCell *addedCell;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIImagePickerController *imagePicker;
@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;
- (IBAction)addPhoto:(id)sender;
- (IBAction)done:(id)sender;
@end
FlipsideViewController.m
#import "FlipsideViewController.h"
#import "MainViewController.h"
@implementation FlipsideViewController
@synthesize delegate = _delegate;
@synthesize dataArray, tableView, addPhotoButton, addedCell, image, imagePicker;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataArray = [[NSMutableArray alloc] init];
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.allowsEditing = NO;
self.imagePicker.delegate = self;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
#pragma mark - UITableView delegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellID = @"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.showsReorderControl = YES;
}
return cell;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Actions
- (IBAction)addPhoto:(id)sender
{
[self presentModalViewController:self.imagePicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
// AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
// appDelegate.pickerImage = img;
image = img;
[self dismissModalViewControllerAnimated:YES];
[self.tableView beginUpdates];
[self.dataArray addObject:@""];
NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:(self.dataArray.count - 1) inSection:0]];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
addedCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:(self.dataArray.count - 1) inSection:0]];
addedCell.imageView.image = image;
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
[self.dataArray removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你需要问自己问题,因为这是一个逻辑问题。
如何在
MainViewController
中创建FlipsideViewController
?您是否每次都创建一个新的,如果是或否,原因是什么?
您如何保持数据的活力?
至少有 3 或 4 种方式可能发生这种情况,主要是在我们的 MainViewController 中。
如果这些问题对您没有帮助,请发布 MainViewController 代码。
问题与对象的生命周期有关
如果您认为用户会经常访问您的 FlipsideView,您可以创建它一次并将其保留在 MainView 的属性中。
如果没有,您可以将数组缓存在 MainView 中,并在创建后立即将其传递到 Flipside。
(在这两种情况下,如果您希望在应用程序启动之间保持持久性,则需要将可变数组保存到磁盘。如果将其保存到磁盘,它也可能是直接进入磁盘以获取信息的 Flipside)
我建议任何新的 Apple 程序员都需要学习和理解
retain
和release
的内存管理。因为 ARC 并不神奇,它代表
自动引用计数
。如果您了解retain
和release
的工作原理,您将更好地了解 ARC 的工作原理,并能够清楚地看到对象的生命周期。(实际上 ARC 正在幕后执行
retain
和release
)You need to ask yourself questions, because this is a logic problem.
how do you create your
FlipsideViewController
in theMainViewController
?Are you creating a new one each time, if yes or no what are the reason for that?
How are you keeping alive the data?
There is a least 3 or 4 ways that could happen, and principally it would be in our MainViewController.
If those question don't help you, please post the MainViewController code.
The problem is about life cycle of your objects
If you think that the user will ofter go to your FlipsideView you could create it once and keep it in a property of your MainView.
If not you could cache the Array in the MainView and pass it to the Flipside just after creating it.
(In both case if you want to have persistence between application launches you will need to save your mutable array to disk. And if you save it to disk it also could be the Flipside that goes directly to disk to fetch the information)
I would suggest any new Apple programmer to study and understand the memory management of the
retain
andrelease
.Because ARC is no magic and it's stand for
Automatic Reference Counting
. If you understand how theretain
andrelease
work, you will have a better understanding of how ARC works and be able to clearly see the life cycle of your objects.(And actually ARC is doing
retain
andrelease
under the hood)您需要将选择信息保存在独立于翻转视图的某个持久位置。当您返回到 Flipview 时,首先检查是否有保存的选择,然后根据该选择加载表格。
You need to save the selection information in some persistent location independent of the flipview. When you come back to the flipview first check if there is a saved selection and then load your table based on that.