断言失败第二次添加/删除
Posted
技术标签:
【中文标题】断言失败第二次添加/删除【英文标题】:Assertion failure second time adding/deleting 【发布时间】:2014-05-21 18:45:10 【问题描述】:我有一个奇怪的问题:我在一个包含按钮的 SplitViewController 中有一个 DetailViewController。这个按钮有一个到 NavigationController 和 UITableViewController 的 Popover segue,它充当记事本。我第一次打开弹出窗口时,记事本效果很好,正如预期的那样。但是,如果我关闭弹出框然后重新打开它,添加或删除注释时它会失败。应用重启后功能恢复。
添加代码归咎:
[_objects insertObject:newNote atIndex:0];
删除被指责的代码:
[_objects removeObjectAtIndex:indexPath.row];
几乎整个 NotesViewController.m 类:
#import "NotesTableViewController.h"
@interface NotesTableViewController ()
NSMutableArray *_objects;
BOOL firstRun;
@end
@implementation NotesTableViewController
@synthesize openSubject;
- (id)initWithStyle:(UITableViewStyle)style
self = [super initWithStyle:style];
if (self)
// Custom initialization
return self;
- (void)awakeFromNib
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
[super awakeFromNib];
- (void)viewDidLoad
[super viewDidLoad];
// Load the notes data
// Create the key
NSString *partOfKey = @"-notes";
NSString *notesKey = [NSString stringWithFormat:@"%@%@", openSubject, partOfKey];
// Do any additional setup after loading the view, typically from a nib
self.navigationItem.leftBarButtonItem = self.editButtonItem;
// Register a class or nib file using registerNib:forCellReuseIdentifier
// o registerClass:forCellReuiseIdentifier: method before calling this method
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
// Load the _objects from NSUserdefaults
_objects = nil;
_objects = [[NSUserDefaults standardUserDefaults] objectForKey:notesKey];
if (openSubject.length == 0)
// There's currently no subject open, write it in the navigationbar
// Prompt = open subject
// Title = notes header
self.navigationItem.prompt = @"No subject selected";
self.navigationItem.title = @"My Notes";
else
// Open the subject
// Prompt = notes header
// Title = open subject
self.navigationItem.prompt = openSubject;
self.navigationItem.title = @"My notes";
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (IBAction)addNote:(id)sender
// Create a new note
if (openSubject.length == 0)
// The openSubject is nil, can't add a subject - tell the user
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"No subject" message: @"Please select a subject prior to adding a note" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show];
else
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New note" message:@"Enter a note" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Add", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
// The user created a new subject, add it
if (buttonIndex == 1)
// Get the input text
NSString *newNote = [[alertView textFieldAtIndex:0] text];
// Check if the note already exist
if ([_objects containsObject:newNote])
// Tell the user this note already exists
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Already exists" message: @"This note already exist, sorry" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
else
// The note doesn't exist, add it
// Initialize objects
if (!_objects)
_objects = [[NSMutableArray alloc] init];
// Add
[_objects insertObject:newNote atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
// Save the new _objects
[self saveObjects];
-(void)saveObjects
// Create the key
NSString *partOfKey = @"-notes";
// Save the new objects
NSString *notesKey = [NSString stringWithFormat:@"%@%@", openSubject, partOfKey];
[[NSUserDefaults standardUserDefaults] setObject:_objects forKey:notesKey];
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// Return the number of rows in the section.
return _objects.count;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSString *object = _objects[indexPath.row];
cell.textLabel.text = [object description];
return cell;
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
调试器输出:
2014-05-21 20:43:14.564 myApp[263:60b] viewDidAppear 2014-05-21 20:43:15.093 myApp [263:60b] viewDidAppear 2014-05-21 20:43:29.741 myApp[263:60b] * 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[__NSCFArray insertObject:atIndex:]: 发送到不可变对象的变异方法” * 首先抛出调用栈: (0x2d95bfd3 0x38440ccf 0x2d95bf15 0x2d8cfa93 0xf6e29 0x3038eb29 0x3038e7fb 0x3029605f 0x30348377 0x301f76f5 0x3017055b 0x2d9272a5 0x2d924c49 0x2d924f8b 0x2d88ff0f 0x2d88fcf3 0x32789663 0x301db16d 0xf9411 0x3894dab7) libc++abi.dylib:以 NSException 类型的未捕获异常终止 (lldb)
请帮我解决这个问题,我不知道。
提前致谢
【问题讨论】:
【参考方案1】:当您从 NSUserDefaults 取回数组时,它会返回一个不可变数组。您需要获取 mutableCopy 或执行 _objects = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:notesKey]];
Here's a link of this answered
【讨论】:
你先生让我很开心!谢谢 - 不知道这给我带来了多大的困扰:)以上是关于断言失败第二次添加/删除的主要内容,如果未能解决你的问题,请参考以下文章