"由于未捕获的异常终止应用程序' NSInvalidArgumentException'"

时间:2014-03-22 17:06:17

标签: ios objective-c uitableview segue

我正在创建一个iOS应用。由于我是初学者,我开始查看一些教程。 我开始创建一个Table View的应用。通过数据库连接动态填充单元格。这很好。

但是现在我正在尝试定义一个push segue来打开单元格的详细视图。这些也必须动态填充数据。为了达到这个目的,我开始通过this tutorial并开始研究“使用Segue传递数据”。在该步骤中,您必须为segue分配一个标识符并填写prepareForSegue:sender:方法。

我相信我的方法的实现会导致上述错误,因为它没有做到它应该做的事情。查看错误并没有为我提供(可理解的)答案,因为我没有看到这个问题是如何产生的。

有人可以看看我的代码吗?提前谢谢。

Main.storyboard: Main.storyboard

如果您可能想知道,我确实在我的segue中添加了一个名为showEventDetails的标识符。

EventsTableViewController.h

#import <UIKit/UIKit.h>
#import <sqlite3.h>

@interface EventsTableViewController : UITableViewController {
    NSMutableArray *EventsArray;
    sqlite3 *db;
}

@property (nonatomic, retain) NSMutableArray *EventsArray;
@property (nonatomic, strong) IBOutlet UITableView *eventTable;

-(NSMutableArray *) EventList;

@end

EventsTableViewController.m

#import "EventsTableViewController.h"
#import "TableCellViewController.h"
#import "Event.h"
#import <sqlite3.h>

@implementation EventsTableViewController
@synthesize EventsArray;
@synthesize eventTable;


- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [self EventList];
    [super viewDidLoad];

}

- (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];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    //Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //Return the number of rows in the section.
    return [self.EventsArray count];
}

- (NSMutableArray *) EventList
{
    EventsArray = [[NSMutableArray alloc] initWithCapacity:10];
    @try {
        NSFileManager *fileMgr = [NSFileManager defaultManager];
        NSString *dbPath = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:@"eventsDb.sqlite"];
        BOOL success = [fileMgr fileExistsAtPath:dbPath];
        if(!success) {
            NSLog(@"Cannot locate database file '%@'.", dbPath);
        }
        if (!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK)) {
            NSLog(@"An error has occured: %s", sqlite3_errmsg(db));
        }

        const char *sql = "SELECT * FROM events";
        sqlite3_stmt *sqlStatement;
        if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
            NSLog(@"Problem with prepare statement: %s", sqlite3_errmsg(db));
        }
        else {
            while (sqlite3_step(sqlStatement) == SQLITE_ROW) {
                Event *event = [[Event alloc] init];
                event.name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 1)];
                event.date = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 2)];
                event.starttime = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
                event.endtime = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
                event.location = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
                event.description = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 6)];
                event.favourite = sqlite3_column_int(sqlStatement, 7);
                [EventsArray addObject:event];
                event = nil;
            }
        }
        sqlite3_finalize(sqlStatement);
    }
    @catch (NSException *exception) {
        NSLog(@"Problem with prepare statement: %s", sqlite3_errmsg(db));
    }
    @finally {
        sqlite3_close(db);
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"EventCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    int rowCount = indexPath.row;

    Event *event = [self.EventsArray objectAtIndex:rowCount];
    cell.textLabel.text = event.name;
    cell.detailTextLabel.text= event.description;

    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showEventDetails"]) {
        NSIndexPath *indexPath = [self.eventTable indexPathForSelectedRow];
        TableCellViewController *destViewController = segue.destinationViewController;
        destViewController.eventName = [EventsArray objectAtIndex:indexPath.row];
    }
}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{

}

@end

TableCellViewController.h

#import <UIKit/UIKit.h>

@interface TableCellViewController : UIViewController

@property(nonatomic, copy) NSString *eventName;
@property(nonatomic, strong) IBOutlet UILabel * eventNameLabel;
@property(nonatomic, copy) NSString *eventDate;
@property(nonatomic, strong) IBOutlet UILabel * eventDateLabel;
@property(nonatomic, copy) NSString *eventStarttime;
@property(nonatomic, strong) IBOutlet UILabel * eventStarttimeLabel;
@property(nonatomic, copy) NSString *eventEndtime;
@property(nonatomic, strong) IBOutlet UILabel * eventEndtimeLabel;
@property(nonatomic, copy) NSString *eventLocation;
@property(nonatomic, strong) IBOutlet UILabel * eventLocationLabel;
@property(nonatomic, copy) NSString *eventDescription;
@property(nonatomic, strong) IBOutlet UILabel * eventDescriptionLabel;
@property(nonatomic, assign) NSInteger eventFavourite;
@property(nonatomic, strong) IBOutlet UILabel * eventFavouriteLabel;

@end

TableCellViewController.m

#import "TableCellViewController.h"

@interface TableCellViewController ()

@end

@implementation TableCellViewController

@synthesize eventName;
@synthesize eventNameLabel;
@synthesize eventDate;
@synthesize eventDateLabel;
@synthesize eventStarttime;
@synthesize eventStarttimeLabel;
@synthesize eventEndtime;
@synthesize eventEndtimeLabel;
@synthesize eventLocation;
@synthesize eventLocationLabel;
@synthesize eventDescription;
@synthesize eventDescriptionLabel;
@synthesize eventFavourite;
@synthesize eventFavouriteLabel;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Set the eventNameLabel with the name of the event
    eventNameLabel.text = eventName;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#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

再次感谢!

1 个答案:

答案 0 :(得分:2)

这是违规行:

destViewController.eventName = [EventsArray objectAtIndex:indexPath.row];

您尝试将存储在数组中的Event类型的对象分配给NSString类型的对象。

由于您的字符串是使用copy修饰符定义的,因此作业会尝试复制到作业右侧的对象(Event),但显然此对象并不符合NSCopying协议,因此错误unrecognized selector... copyWithZone...