I am creating an iOS app. Since I am a beginner, I started with checking out some tutorials. I started with creating an app with a Table View. The cells are dynamically filled through a database connection. This works fine.

However now I'm trying to define a push segue that opens a detail view for the cells. These also have to become filled dynamically with data. To achieve this, I started going through this tutorial and got it working up to "Passing Data Using Segue". In that step, you have to assign an identifier to your segue and fill in the prepareForSegue:sender: method.

I believe the implementation of my method causes the above error, because it isn't doing what it's supposed to. Looking up the error did not provide me with (understandable) answers since I fail to see how this problem has arisen.

Could someone please take a look at my code? Thanks in advance.

Main.storyboard: Main.storyboard

In case you might be wondering, I did add an identifier to my segue, named 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

Thanks again!

有帮助吗?

解决方案

This is the offending line:

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

You're trying to assign an object of type Event stored in the array, to an object of type NSString.

Since your string is defined with the copy modifier, the assignment tries to copy to object on the right side of the assignment (Event) but apparently this object doesn't conform to the NSCopying protocol, hence the error unrecognized selector... copyWithZone....

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top