It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have an existing project that I am adding the CoreData framework to but I'm running into some trouble. I've added CoreData to existing projects before but I'm not sure where I'm going wrong in this case.
I have added all of the necessary code to the AppDelegate.h and .m files. I have added the import statement to my .pch. I've created my data model file with all of the properties of my Lesson object. I've done everything I can think of but when my viewDidLoad method runs through, my managedObjectContext is still nil.
I've posted the code for my AppDelegate and my ViewController below. Hopefully someone can offer some advice regarding where I went wrong. Thank you :)
AppDelegate.h
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize managedObjectContext = __managedObjectContext;
#synthesize managedObjectModel = __managedObjectModel;
#synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
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:.
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"iLessonsPiano" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"iLessonsPiano.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "Lesson.h"
#import "PDFViewController.h"
#import "MediaPlayer/MediaPlayer.h"
#import "PracticeViewController.h"
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) NSManagedObjectContext* managedObjectContext;
// Array to hold all lessons.
#property (nonatomic, strong) NSMutableArray *lessonLibrary;
// Array to hold the purchased lessons.
#property (nonatomic,strong) NSMutableArray *purchasedLessons;
// Lesson detail display items.
#property (strong, nonatomic) IBOutlet UIImageView *coverArt;
#property (weak, nonatomic) IBOutlet UILabel *lessonTitle;
#property (weak, nonatomic) IBOutlet UILabel *lessonSubtitle;
#property (weak, nonatomic) IBOutlet UILabel *timingLabel;
#property (weak, nonatomic) IBOutlet UILabel *keySignatureLabel;
#property (weak, nonatomic) IBOutlet UIImageView *difficultyImage;
#property (weak, nonatomic) IBOutlet UITextView *descriptionTextView;
#property (weak, nonatomic) IBOutlet UIImageView *dividerImage;
#property (weak, nonatomic) IBOutlet UIImageView *detailBackgroundImage;
#property (weak, nonatomic) IBOutlet UIImageView *detailsImage;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
//Table Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// Variables and Methods for the Video Player
#property (strong, nonatomic) MPMoviePlayerViewController *player;
#end
ViewController.m
#import "ViewController.h"
#import "AppDelegate.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize coverArt;
#synthesize lessonTitle;
#synthesize lessonSubtitle;
#synthesize timingLabel;
#synthesize keySignatureLabel;
#synthesize difficultyImage;
#synthesize descriptionTextView;
#synthesize dividerImage;
#synthesize detailBackgroundImage;
#synthesize detailsImage;
#synthesize purchasedLessons;
#synthesize tableView;
#synthesize player;
#synthesize managedObjectContext;
#synthesize lessonLibrary;
//TABLE METHODS
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return purchasedLessons.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create a cell.
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"purchased"];
// Populate the cell with data.
Lesson *temp = [[Lesson alloc] init];
temp = [purchasedLessons objectAtIndex:indexPath.row];
cell.textLabel.text = temp.title;
cell.detailTextLabel.text = temp.subtitle;
// Return the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Determine what row is selected and retrieve the correct Lesson object.
Lesson *currentSelection = [[Lesson alloc] init];
int row = [indexPath row];
currentSelection = [purchasedLessons objectAtIndex:row];
if (currentSelection.purchaseStatus == 1) {
UIImage *tempCoverArt = [UIImage imageNamed:currentSelection.coverArtFilename];
UIImage *tempDifficulty = [UIImage imageNamed:currentSelection.difficultyImageFilename];
// Change the information in the details pane to the details for the current lesson.
[coverArt setImage:tempCoverArt];
lessonTitle.text = currentSelection.title;
lessonSubtitle.text = currentSelection.subtitle;
timingLabel.text = currentSelection.timing;
keySignatureLabel.text = currentSelection.keySignature;
[difficultyImage setImage:tempDifficulty];
descriptionTextView.text = currentSelection.lessonDescription;
}
}
//END TABLE METHODS
- (void)viewDidLoad
{
[super viewDidLoad];
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
// Song library
Lesson *Lesson0 = [[Lesson alloc] init];
Lesson0 = [NSEntityDescription insertNewObjectForEntityForName:#"Lesson" inManagedObjectContext:managedObjectContext];
Lesson0.productID = 0;
//Lesson0.purchaseStatus = 1;
Lesson0.title = #"Happy Birthday to You";
Lesson0.subtitle = #"Patty & Mildred Hill";
Lesson0.titleAndSubtitle = #"Happy Birthday to You - Patty & Mildred Hill";
Lesson0.coverArtFilename = #"beethoven.png";
Lesson0.timing = #"3/4";
Lesson0.keySignature = #"G";
Lesson0.difficultyImageFilename = #"easy.png";
Lesson0.lessonDescription = #"Originally, this song piece was called 'Good Morning to All' and was sung to and by children in school.";
Lesson0.sheetFilename = #"1_score";
Lesson0.midiFilename = #"happyBirthdayToYou";
Lesson0.materialsFilename = #"1_score";
Lesson0.roll = #"happyBirthdayToYou";
//Lesson0.startingIndicatorPosition = 175;
Lesson0.rollPositionArray = [NSArray arrayWithObjects: /* 0 */ [NSNumber numberWithInteger:0],
/* 1 */ [NSNumber numberWithInteger:0],
/* 2 */ [NSNumber numberWithInteger:0],
/* 3 */ [NSNumber numberWithInteger:-65],
/* 4 */ [NSNumber numberWithInteger:-100],
/* 5 */ [NSNumber numberWithInteger:-135],
/* 6 */ [NSNumber numberWithInteger:-185],
/* 7 */ [NSNumber numberWithInteger:-185],
/* 8 */ [NSNumber numberWithInteger:-241],
/* 9 */ [NSNumber numberWithInteger:-306],
/* 10 */ [NSNumber numberWithInteger:-341],
/* 11 */ [NSNumber numberWithInteger:-376],
/* 12 */ [NSNumber numberWithInteger:-426],
/* 13 */ [NSNumber numberWithInteger:-426],
/* 14 */ [NSNumber numberWithInteger:-483],
/* 15 */ [NSNumber numberWithInteger:-548],
/* 16 */ [NSNumber numberWithInteger:-582],
/* 17 */ [NSNumber numberWithInteger:-617],
/* 18 */ [NSNumber numberWithInteger:-666],
/* 19 */ [NSNumber numberWithInteger:-701],
/* 20 */ [NSNumber numberWithInteger:-737],
/* 21 */ [NSNumber numberWithInteger:-799],
/* 22 */ [NSNumber numberWithInteger:-834],
/* 23 */ [NSNumber numberWithInteger:-868],
/* 24 */ [NSNumber numberWithInteger:-918],
nil];
// Load in the CoreData library of Lessons
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Lesson" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *tempArray = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
lessonLibrary = [[NSMutableArray alloc] initWithArray:tempArray];
NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:#"subtitle" ascending:YES];
[lessonLibrary sortUsingDescriptors:[NSArray arrayWithObjects:desc, nil]];
// Load background images.
UIImage *detailsDivider = [UIImage imageNamed:#"detailsDividerImage.png"];
[dividerImage setImage:detailsDivider];
UIImage *detailsBackground = [UIImage imageNamed:#"detailsBackgroundImage.png"];
[detailBackgroundImage setImage:detailsBackground];
UIImage *detailsPanel = [UIImage imageNamed:#"detailsDisplayImage.png"];
[detailsImage setImage:detailsPanel];
// Load default cover art.
UIImage *defaultCoverArt = [UIImage imageNamed:#"coverArtDefault.png"];
[coverArt setImage:defaultCoverArt];
if (![managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
for (Lesson *lesson in lessonLibrary) {
[purchasedLessons addObject:lesson];
}
// purchasedLessons = [[NSMutableArray alloc] initWithObjects:Lesson0, nil];
}
- (void)viewDidUnload
{
[self setLessonTitle:nil];
[self setLessonSubtitle:nil];
[self setCoverArt:nil];
[self setTimingLabel:nil];
[self setKeySignatureLabel:nil];
[self setDifficultyImage:nil];
[self setDescriptionTextView:nil];
[self setDividerImage:nil];
[self setDetailBackgroundImage:nil];
[self setDetailsImage:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Segue to the materials screen.
if ([segue.identifier isEqualToString:#"materials"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected;
pdfViewController.fileToView = #"materials";
}
// Segue to the sheet screen.
else if ([segue.identifier isEqualToString:#"sheet"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected;
pdfViewController.fileToView = #"sheet";
}
// Segue to the practice screen.
else if ([segue.identifier isEqualToString:#"practice"]) {
PracticeViewController *practiceViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
practiceViewController.selectedLesson = selected;
}
}
#end
Lesson.h
#import <Foundation/Foundation.h>
#interface Lesson : NSObject
#property int purchaseStatus;
#property int productID;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *subtitle;
#property (nonatomic, strong) NSString *titleAndSubtitle;
#property (nonatomic, strong) NSString *coverArtFilename;
#property (nonatomic, strong) NSString *timing;
#property (nonatomic, strong) NSString *keySignature;
#property (nonatomic, strong) NSString *difficultyImageFilename;
#property (nonatomic, strong) NSString *lessonDescription;
#property (nonatomic, strong) NSString *materialsFilename;
#property (nonatomic, strong) NSString *sheetFilename; // PDF
#property (nonatomic, strong) NSString *midiFilename;
#property (nonatomic, strong) NSString *roll;
#property NSArray *rollPositionArray;
#property int startingIndicatorPosition;
#end
Lesson.m
#import "Lesson.h"
#implementation Lesson
#synthesize productID, coverArtFilename, title, subtitle, titleAndSubtitle, timing, keySignature, difficultyImageFilename, lessonDescription, materialsFilename, sheetFilename, midiFilename, purchaseStatus, roll, rollPositionArray, startingIndicatorPosition;
#end
I'm not sure what happened but I started over and got it to work on the second go around :) It may had had something to do with where my AppDelegate was looking for the model.
Related
I'm using a project find on github that lets me use NSFetchedResultsController and UICollectionView, the project is this
in my project i have a Core Data with two Entity, Element and Document, there is a relationship one to many between Element and Document, so an Element can have more Document, but a Document can have only one Element, then i do this in the AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
ElementViewController *elementView = [[ElementViewController alloc] initWithNibName:#"ElementViewController" bundle:nil];
elementView.managedObjectContext = self.managedObjectContext;
DocumentViewController *documentView = [[DocumentViewController alloc] initWithNibName:#"DocumentViewController" bundle:nil];
documentView.managedObjectContext = self.managedObjectContext;
elementView.documentView = documentView;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:elementView];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
this is the App delegate, then in ElementViewController i have a UICollectionView with NSFetchedResultsController, and all works ok, when i select a UICollectionViewCell i open the DocumentViewController:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.documentView.element = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self.navigationController pushViewController:self.documentView animated:YES];
}
then this is my DocumentViewController.h:
#import <UIKit/UIKit.h>
#import "Element.h"
#interface DocumentViewController : UIViewController <NSFetchedResultsControllerDelegate>
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
#property (strong, nonatomic) Element *element;
#end
And also here i have the NSFetchedResultsController, the filter in the predicate for the Element title:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Document" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"docDate" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"SUBQUERY(element, $b, $b.name == %#).#count > 0", self.element.name]];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
and then i have add also this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self reloadCollectionView];
[self addDocument];
}
- (void)reloadTableView
{
self.fetchedResultsController = nil; //Because not search every time for different Element
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Error in search %#, %#", error, [error userInfo]);
} else {
[self.collectionView reloadData];
}
}
then in the viewWillAppear there is the addDocument method:
- (void)addDocument
{
Document *document = (Document *)[NSEntityDescription
insertNewObjectForEntityForName:#"Document"
inManagedObjectContext:self.managedObjectContext];
[document setDocName:[title contents]];
[document setElement:self.element]; //here the app crash
}
and i receive these error:
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. Can't perform collection evaluate with non-collection object. with userInfo (null)
2013-01-25 10:28:56.392 App[383:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't perform collection evaluate with non-collection object.'
anyone can help me?
EDIT:
This is the NSManagedObjectClass:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Document;
#interface Element : NSManagedObject
#property (nonatomic, retain) NSString * dateFormat;
#property (nonatomic, retain) NSString * dateFormat2;
#property (nonatomic, retain) id img;
#property (nonatomic, retain) NSDate * imgDate;
#property (nonatomic, retain) NSString * imgUrl;
#property (nonatomic, retain) NSString * language;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * name2;
#property (nonatomic, retain) NSString * pathDocuments;
#property (nonatomic, retain) NSNumber * releaseDateWeek;
#property (nonatomic, retain) NSNumber * type;
#property (nonatomic, retain) NSSet *documents;
#end
#interface Element (CoreDataGeneratedAccessors)
- (void)addDocumentsObject:(Document *)value;
- (void)removeDocumentsObject:(Document *)value;
- (void)addDocuments:(NSSet *)values;
- (void)removeDocuments:(NSSet *)values;
#end
#interface ImageToDataTransformer : NSValueTransformer {
}
#end
Document.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Element;
#interface Document : NSManagedObject
#property (nonatomic, retain) NSDate * docDate;
#property (nonatomic, retain) id docImage;
#property (nonatomic, retain) NSString * docName;
#property (nonatomic, retain) NSString * docPath;
#property (nonatomic, retain) NSNumber * docSize;
#property (nonatomic, retain) NSString * docUrl;
#property (nonatomic, retain) NSNumber * isDownloading;
#property (nonatomic, retain) NSNumber * isStored;
#property (nonatomic, retain) NSNumber * pageNumber;
#property (nonatomic, retain) NSString * password;
#property (nonatomic, retain) NSNumber * progressBar;
#property (nonatomic, retain) Element *element;
#end
The problem looks to be that that in:
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"SUBQUERY(element, $b, $b.name == %#).#count > 0", self.element.name]];
'element' does not resolve to a collection (as required by SUBQUERY), but merely a single object.
See: http://developer.apple.com/library/Mac/#documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/Reference/NSExpression.html
I worked CoreData into my Tab Bar app and the CoreData functions are working (i.e. I can output information from it to the console). The problem is that my tab bar isn't working. When I run my app, it looks like this:
It looks as if the tab bar itself is showing up but there aren't any items and it isn't displaying the table view. My storyboard looks like this:
Here is the code for my AppDelegate:
AppDelegate.h
#import <UIKit/UIKit.h>
#import "JobsViewController.h"
#import "Job.h"
#import "Shift.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize managedObjectContext = __managedObjectContext;
#synthesize managedObjectModel = __managedObjectModel;
#synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSManagedObjectContext *context = [self managedObjectContext];
Job *job = [NSEntityDescription insertNewObjectForEntityForName:#"Job" inManagedObjectContext:context];
job.employer = #"Calder Centre";
job.jobTitle = #"Addictions Counsellor";
job.regularRate = 25.9f;
job.overtimeRate = 30.5f;
job.deduction1 = 0.1f;
job.deduction2 = 0.2f;
job.deduction3 = 0.3f;
job.deduction4 = 0.4f;
job.deduction1Name = #"CPP";
job.deduction2Name = #"IT";
job.deduction3Name = #"Union Dues";
job.deduction4Name = #"Other";
Shift *shift = [NSEntityDescription insertNewObjectForEntityForName:#"Shift" inManagedObjectContext:context];
shift.startDate = [NSDate date];
shift.endDate = [NSDate date];
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
// Test listing all FailedBankInfos from the store
NSFetchRequest *jobFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *jobEntity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:context];
[jobFetchRequest setEntity:jobEntity];
NSArray *fetchedJobs = [context executeFetchRequest:jobFetchRequest error:&error];
for (Job *job in fetchedJobs) {
NSLog(#"Employer: %#", job.employer);
NSLog(#"Title: %#", job.jobTitle);
}
NSFetchRequest *shiftFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *shiftEntity = [NSEntityDescription entityForName:#"Shift" inManagedObjectContext:context];
[shiftFetchRequest setEntity:shiftEntity];
NSArray *fetchedShifts = [context executeFetchRequest:shiftFetchRequest error:&error];
for (Shift *shift in fetchedShifts) {
NSLog(#"Start Date: %#", shift.startDate);
NSLog(#"End Date: %#", shift.endDate);
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UITabBarController *tabBarController = [[UITabBarController alloc]init];
self.window.rootViewController = tabBarController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Here is the view controller:
JobsViewController.h
#import <UIKit/UIKit.h>
#import "Job.h"
#import "Shift.h"
#interface JobsViewController : UITableViewController
#property (nonatomic, strong) NSManagedObjectContext* managedObjectContext;
#property (nonatomic, strong) NSArray *listOfJobs;
#end
JobsViewController.m
#import "JobsViewController.h"
#interface JobsViewController ()
#end
#implementation JobsViewController
#synthesize managedObjectContext, listOfJobs;
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Job" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
self.listOfJobs = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
self.title = #"Jobs";
}
#pragma mark - Table view data source
- (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 [listOfJobs count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"job";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
Job *job = [listOfJobs objectAtIndex:indexPath.row];
cell.textLabel.text = job.jobTitle;
cell.detailTextLabel.text = job.employer;
return cell;
}
This has nothing to do with core data.
You are using code from an app delegate template for a non-storyboard project, but you are using a storyboard. The code in your didFinishLaunching method is creating a new window and empty tab bar controller, which is overriding anything from your storyboard.
Get rid of everything after self.window =, except return YES;. This is code used in xib-based applications and is not necessary if you have a storyboard.
I have 3 classes
First -> MainViewController:
#interface MainViewController : UIViewController {
UtilityBadah *utility;
}
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
- (IBAction)option;
#end
#implementation MainViewController
#synthesize managedObjectContext = _managedObjectContext;
(IBAction)option{
UtilityBadah *util = [[UtilityBadah alloc] initWithContext:_managedObjectContext];
OptionController *ovc = [[OptionController alloc] init];
ovc.util = util;
ovc.managedObjectContext = _managedObjectContext;
[self.navigationController pushViewController:ovc animated:YES];
[util release];
[ovc release];
}
#end
Second -> UtilityBadah:
#interface UtilityBadah : NSObject {
NSManagedObjectContext *managedObjectContext;
NSString *kitab;
NSString *lagu;
NSString *font;
NSString *sizefont;
}
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain) NSString *kitab;
#property (nonatomic, retain) NSString *lagu;
#property (nonatomic, retain) NSString *font;
#property (nonatomic, retain) NSString *sizefont;
(id) initWithContext: (NSManagedObjectContext *) context;
#end
#implementation UtilityBadah
#synthesize managedObjectContext;
#synthesize kitab;
#synthesize lagu;
#synthesize font;
#synthesize sizefont;
-(id) initWithContext: (NSManagedObjectContext *) context {
NSError *err;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *enDesc = [NSEntityDescription entityForName:#"OptionDB" inManagedObjectContext:context];
[request setEntity:enDesc];
NSArray *arrData = [context executeFetchRequest:request error:&err];
for (OptionDB *data in arrData) {
lagu = data.lagu;
kitab = data.kitab;
font = data.font;
sizefont = data.sizefont;
}
return self;
}
Thrid -> OptionController:
#interface OptionController : UIViewController{
NSManagedObjectContext *managedObjectContext;
UtilityBadah *util;
}
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain) UtilityBadah *util;
#end
(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
bla..bla..
NSLog(#"value is %#",self.util.kitab);
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
i wonder why this piece of code:
NSLog(#"value is %#",self.util.kitab);
cause an error "Receiced signa: "EXC_BAD_ACCESS" ?
i wonder ther somthing wrong the way i passed the UtilityBadah object from MainViewController to my OptionController.
Many thanks for any answer.
P.S what is wrong with my xcode 4.2 error information, why it always show "Program received signal: "EXC BAD ACCESS"? cant it be informative?
i think your init method is wrong, try assigning self to [super init] at the start, and doing all your set up after checking that self != nil. this is the basic form of an init:
- (id)init
{
self = [super init];
if (self)
//do setup
return self;
}
also, you are using a subclass of NSObject and associating a managed object context to it, you should look into core data in more detail, you should be using NSManagedObjects
The property name in the OptionController is util not utility
If you want to access the utility property in the UtilityBadah class you will have to do:
self.util.utility
In the UtilityBadah class, initWithContext method, change the for loop as following
for (OptionDB *data in arrData) {
self.lagu = data.lagu;
self.kitab = data.kitab;
self.font = data.font;
self.sizefont = data.sizefont;
}
In your case, the value is not retained since you have assigned without accessing through the property.
You need to allocate those objects first. Here's how your initWithContext method should look like:
-(id) initWithContext: (NSManagedObjectContext *) context {
self = [super init];
if (self) {
NSError *err;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *enDesc = [NSEntityDescription entityForName:#"OptionDB" inManagedObjectContext:context];
[request setEntity:enDesc];
NSArray *arrData = [context executeFetchRequest:request error:&err];
for (OptionDB *data in arrData) {
self.lagu = [NSString stringWithString:data.lagu];
self.kitab = [NSString stringWithString:data.kitab];
self.font = [NSString stringWithString:data.font];
self.sizefont = [NSString stringWithString:data.sizefont];
}
}
return self;
}
I do webservice requests with a UISegmentedControl, when I change segmentedItem and request fast the application crashes with this message:
[Session started at 2011-05-12
10:58:50 +0200.] Terminating in
response to SpringBoard's termination.
[Session started at 2011-05-12
11:06:31 +0200.] GNU gdb
6.3.50-20050815 (Apple version gdb-1516) (Fri Feb 11 06:19:43 UTC
2011) Copyright 2004 Free Software
Foundation, Inc. GDB is free software,
covered by the GNU General Public
License, and you are welcome to change
it and/or distribute copies of it
under certain conditions. Type "show
copying" to see the conditions. There
is absolutely no warranty for GDB.
Type "show warranty" for details. This
GDB was configured as
"--host=i386-apple-darwin
--target=arm-apple-darwin".tty /dev/ttys001 Loading program into
debugger… Program loaded. target
remote-mobile
/tmp/.XcodeGDBRemote-239-58 Switching
to remote-macosx protocol mem 0x1000
0x3fffffff cache mem 0x40000000
0xffffffff none mem 0x00000000 0x0fff
none run Running… [Switching to thread
11779] [Switching to thread 11779]
sharedlibrary apply-load-rules all
continue Program received signal:
“SIGKILL”. warning: Unable to read
symbols for
/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.3
(8J2)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib
(file not found). kill quit
The Debugger has exited with status
0.(gdb)
Does anybody have an idea of how can I fix this?
Is this a problem because I'm not using NSOperationQueue?
And if so any suggestions how I can fix this would be very welcomed.
I can not find any memory leaks when running.
Next time I ran it this message got logged:
Program received signal: “EXC_BAD_ACCESS”.
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.3 (8J2)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
(gdb)
Here is the code for starting the connection:
Class header ServiceGetChildren:
#import <Foundation/Foundation.h>
#class Authentication;
#class AttendanceReportViewController;
#interface ServiceGetChildren : NSObject {
Authentication *authentication;
AttendanceReportViewController *attendanceReportViewController;
NSString *username;
NSString *password;
NSMutableString *authenticationString;
NSString *encodedLoginData;
NSMutableData *responseData;
NSMutableArray *childrensArray;
}
#property (nonatomic, retain) NSString *username;
#property (nonatomic, retain) NSString *password;
#property (nonatomic, retain) NSMutableString *authenticationString;
#property (nonatomic, retain) NSString *encodedLoginData;
#property (nonatomic, retain) NSMutableData *responseData;
#property (nonatomic, retain) NSMutableArray *childrensArray;
- (void)startService:(NSURL *)url :(NSString *)method withParent:(UIViewController *)controller;
#end
Class handling the request:
#import "ServiceGetChildren.h"
#import "JSON.h"
#import "Base64.h"
#import "AttendanceReportViewController.h"
#import "Authentication.h"
#implementation ServiceGetChildren
#synthesize appDelegate;
#synthesize username;
#synthesize password;
#synthesize authenticationString;
#synthesize encodedLoginData;
#synthesize responseData;
#synthesize childrensArray;
- (id) init {
if ((self = [super init])) {
}
return self;
}
- (void)startService:(NSURL *)url :(NSString *)method withParent:(UIViewController *)controller {
username = appDelegate.username;
password = appDelegate.password;
attendanceReportViewController = (AttendanceReportViewController *)controller;
Authentication *auth = [[Authentication alloc] init];
authenticationString = (NSMutableString*)[#"" stringByAppendingFormat:#"%#:%#", username, password];
encodedLoginData = [auth encodedAuthentication:authenticationString];
[auth release];
// Setup up the request with the url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url
cachePolicy: NSURLRequestReloadIgnoringCacheData
timeoutInterval: 20.0];
[request setHTTPMethod:method];
[request setValue:[NSString stringWithFormat:#"Basic %#", encodedLoginData] forHTTPHeaderField:#"Authorization"];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
// Display the network indicator when the connection request started
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// Check that the NSURLConnection was successful and then initialize the responseData
if(connection) {
NSLog(#"Connection made");
responseData = [[NSMutableData data] retain];
}
else {
NSLog(#"Connection could not be made");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Connection finished loading.");
// Dismiss the network indicator when connection finished loading
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Parse the responseData of json objects retrieved from the service
SBJSON *parser = [[SBJSON alloc] init];
NSString *jsonString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary *jsonData = [parser objectWithString:jsonString error:nil];
NSMutableArray *array = [jsonData objectForKey:#"Children"];
childrensArray = [NSMutableArray arrayWithArray:array];
// Callback to AttendanceReportViewController that the responseData finished loading
[attendanceReportViewController loadChildren];
[connection release];
[responseData release];
[jsonString release];
[parser release];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Connection failure.");
NSLog(#"ERROR%#", error);
// Dismiss the network indicator when connection failure occurred
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[connection release];
// Inform the user that the server was unavailable
}
- (void) dealloc {
[attendanceReportViewController release];
[super dealloc];
}
Class header for AttendanceReportViewController:
#import <UIKit/UIKit.h>
#class ServiceGetGroups;
#class ServiceGetChildren;
#class DetailViewController;
#interface AttendanceReportViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
ServiceGetGroups *serviceGetGroups;
ServiceGetChildren *serviceGetChildren;
DetailViewController *detailViewController;
UISegmentedControl *segmentedControl;
IBOutlet UIToolbar *groupsToolbar;
NSMutableArray *btnArray;
NSInteger index;
IBOutlet UITableView *theTableView;
IBOutlet UILabel *attendanceLabel;
IBOutlet UILabel *abscentLabel;
IBOutlet UILabel *totalLabel;
NSMutableDictionary *selectRequestDictionary;
NSMutableDictionary *selectNameDictionary;
NSMutableArray *groupsArray;
NSMutableArray *childrensArray;
NSDictionary *childrensDictionary;
NSURL *url;
}
#property (nonatomic, retain) ServiceGetGroups *serviceGetGroups;
#property (nonatomic, retain) ServiceGetChildren *serviceGetChildren;
#property (nonatomic, retain) DetailViewController *detailViewController;
#property (nonatomic, retain) IBOutlet UIToolbar *groupsToolbar;
#property (nonatomic, retain) IBOutlet UITableView *theTableView;
#property (nonatomic, retain) IBOutlet UILabel *attendanceLabel;
#property (nonatomic, retain) IBOutlet UILabel *abscentLabel;
#property (nonatomic, retain) IBOutlet UILabel *totalLabel;
#property (nonatomic, retain) UISegmentedControl *segmentedControl;
#property (nonatomic) NSInteger index;
#property (nonatomic, retain) NSMutableArray *btnArray;
#property (nonatomic, retain) NSMutableDictionary *selectRequestDictionary;
#property (nonatomic, retain) NSMutableDictionary *selectNameDictionary;
#property (nonatomic, retain) NSMutableArray *groupsArray;
#property (nonatomic, retain) NSMutableArray *childrensArray;
#property (nonatomic, retain) NSDictionary *childrensDictionary;
#property (nonatomic, retain) NSURL *url;
- (void)setupSegmentedControl;
- (void)requestGroups;
- (void)requestChildren:(NSNumber *)groupId;
- (void)loadGroups;
- (void)loadChildren;
#end
Class that the Uses the UISegmentedControl:
#import "JSON.h"
#import "AttendanceReportViewController.h"
#import "CustomCellViewController.h"
#import "DetailViewController.h"
#import "ServiceGetGroups.h"
#import "ServiceGetChildren.h"
#import "Group.h"
#import "Child.h"
#implementation AttendanceReportViewController
#synthesize serviceGetGroups;
#synthesize serviceGetChildren;
#synthesize detailViewController;
#synthesize segmentedControl;
#synthesize groupsToolbar;
#synthesize index;
#synthesize btnArray;
#synthesize theTableView;
#synthesize attendanceLabel;
#synthesize abscentLabel;
#synthesize totalLabel;
#synthesize selectRequestDictionary;
#synthesize selectNameDictionary;
#synthesize groupsArray;
#synthesize childrensArray;
#synthesize childrensDictionary;
#synthesize url;
#pragma mark -
#pragma mark View lifecycle
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
- (void)requestGroups {
NSURL *groupsURL = [NSURL URLWithString:#"http://services/groups"];
[serviceGetGroups startService:groupsURL :#"GET" withParent:self];
}
- (void)requestChildren:(NSNumber *)groupId {
NSLog(#"%#", groupId);
NSString *baseURL = #"http://services/group/";
NSString *method = [NSString stringWithFormat:#"%#%#", groupId, #"/children"];
NSString *theURL = [NSString stringWithFormat:#"%#%#", baseURL, method];
self.url = [NSURL URLWithString:theURL];
NSLog(#"%#", self.url);
[serviceGetChildren startService:self.url :#"GET" withParent:self];
}
- (void)loadGroups {
// Retrieve a array with dictionaries of groups from ServiceGetGroups
self.groupsArray = [[serviceGetGroups.groupsArray copy] autorelease];
// The array to hold segmentedItems for the segmentedControl, representing groups buttons
btnArray = [NSMutableArray arrayWithObjects: #"Alla", nil];
for (NSDictionary *groupDict in groupsArray) {
// Add each groups name to the btnArray as segmentedItems for the segmentedControl
[btnArray addObject:[groupDict objectForKey:#"Name"]];
}
// Create a new NSMutableDictionary with group names as keys and group id´s as values
// used for reference to segementedControl items to make request to serviceGetChildren
self.selectRequestDictionary = [NSMutableDictionary dictionary];
for (NSDictionary *dict in groupsArray) {
[selectRequestDictionary setObject:[dict objectForKey:#"Id"] forKey:[dict objectForKey:#"Name"]];
}
// Create a new NSMutableDictionary with group id´s as keys and group names as values
// used for retrieving a groupName from a passed id
self.selectNameDictionary = [NSMutableDictionary dictionary];
for (NSDictionary *dict in groupsArray) {
[selectNameDictionary setObject:[dict objectForKey:#"Name"] forKey:[dict objectForKey:#"Id"]];
}
[self setupSegmentedControl];
}
- (void)setupSegmentedControl {
// Setup the UISegmentedControl as groups buttons
segmentedControl = nil;
segmentedControl = [[UISegmentedControl alloc] initWithItems:btnArray];
segmentedControl.tintColor = [UIColor darkGrayColor];
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.frame = CGRectMake(0, 0, 300, 30);
// Setup the target and actions for the segmentedControl
[segmentedControl addTarget:self
action:#selector(selectGroup:)
forControlEvents:UIControlEventValueChanged];
// Add the UISegmentedControl as a UIBarButtonItem subview to the UIToolbar
UIBarButtonItem *segmentedItem = [[[UIBarButtonItem alloc] initWithCustomView:segmentedControl] autorelease];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
NSArray *groupsButtons = [NSArray arrayWithObjects:flexSpace, segmentedItem, flexSpace, nil];
[groupsToolbar setItems:groupsButtons];
[flexSpace release];
}
- (void)loadChildren {
// Retrieve a array with dictionaries of children from ServiceGetChildren
self.childrensArray = [[serviceGetChildren.childrensArray copy] autorelease];
// TODO create seperate method - Setup compilation bar values
int total = [childrensArray count];
totalLabel.text = [NSString stringWithFormat:#"%d", total];
[theTableView reloadData];
}
// Handles UIControlEventValueChanged for UISegmentedControl, retreives the name and id for a selected group
- (void)selectGroup:(UISegmentedControl *)theSegmentedControl {
NSString *selectedGroup = [segmentedControl titleForSegmentAtIndex: [segmentedControl selectedSegmentIndex]];
NSNumber *selectedId = [selectRequestDictionary objectForKey:selectedGroup];
// Persist the selectedSegmentIndex when view switches to detaildView
index = [segmentedControl selectedSegmentIndex];
// Request children based on the selected groupId
[self requestChildren:selectedId];
}
- (void)viewDidLoad {
[self requestGroups];
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
//self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [childrensArray count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
// Load from nib
CustomCellViewController *cell = (CustomCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCellView"
owner:nil
options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (CustomCellViewController *) currentObject;
break;
}
}
}
// Set up a children dictionary for easy retrieving specific values to display in the UITableView
childrensDictionary = [childrensArray objectAtIndex:indexPath.row];
NSNumber *idForName = [childrensDictionary valueForKey:#"GroupId"];
NSString *name = [NSString stringWithFormat:#"%# %#",
[childrensDictionary valueForKey:#"Firstname"],
[childrensDictionary valueForKey:#"Surname"]];
NSString *group = [NSString stringWithFormat:#"%#",
[selectNameDictionary objectForKey:idForName]];
cell.childNameLabel.text = name;
cell.groupNameLabel.text = group;
cell.scheduleLabel.text = #"Schema";
cell.deviationLabel.text = #"Avvikelse";
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push the detailedViewController.
if (detailViewController == nil) {
DetailViewController *_detailViewcontroller = [[DetailViewController alloc]
initWithNibName:#"DetailView" bundle:nil];
self.detailViewController = _detailViewcontroller;
[_detailViewcontroller release];
}
childrensDictionary = [childrensArray objectAtIndex:indexPath.row];
NSNumber *idForName = [childrensDictionary valueForKey:#"GroupId"];
NSString *group = [NSString stringWithFormat:#"%#",
[selectNameDictionary objectForKey:idForName]];
[self.detailViewController initWithDetailsSelected:childrensDictionary:group];
[self.navigationController pushViewController:detailViewController animated:YES];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
segmentedControl = nil;
}
- (void)dealloc {
[segmentedControl release];
[groupsArray release];
[childrensArray release];
[detailViewController release];
[super dealloc];
}
#end
OK here we go. First of all, I could not test the code, so I need your feedback.
The main problem with this class is, you only have one instance, which you reuse every time you hit the segmented control. This leads to creation of new instances of the NSURLConnection. So let's correct a bit in the header. I changed the NSString properties to copy. Have a look at this Q&A to know why, however this is not important for the improvement, just wanted to let you know.
I've removed Authentication *authentication; looked like you don't use it.
Added NSURLConnection as property so we keep a reference on it.
Header file
#class Authentication;
#class AttendanceReportViewController;
#interface ServiceGetChildren : NSObject {
AttendanceReportViewController *attendanceReportViewController;
NSString *username;
NSString *password;
NSMutableString *authenticationString;
NSString *encodedLoginData;
NSMutableData *responseData;
NSMutableArray *childrensArray;
NSURLConnection *connection;
}
#property (nonatomic, copy) NSString *username;
#property (nonatomic, copy) NSString *password;
#property (nonatomic, retain) NSMutableString *authenticationString;
#property (nonatomic, copy) NSString *encodedLoginData;
#property (nonatomic, retain) NSMutableData *responseData;
#property (nonatomic, retain) NSMutableArray *childrensArray;
#property (nonatomic, retain) NSURLConnection *connection
- (void)startService:(NSURL *)url :(NSString *)method withParent:(UIViewController *)controller;
#end
Next comes the Implementation file. I only altered the startService method and dealloc.
If you declare properties, use them :) Have a look at this Q&A for some explanations on synthesized properties.
Always release what you own, so I added release code in the dealloc.
Cancel the previous request!!! If there is none, the message is sent to nil, which causes no harm.
Implementation file
- (void)startService:(NSURL *)url:(NSString *)method withParent:(UIViewController *)controller
{
self.username = appDelegate.username;
self.password = appDelegate.password;
[connection cancel];
attendanceReportViewController = (AttendanceReportViewController *)controller;
Authentication *auth = [[Authentication alloc] init];
authenticationString = (NSMutableString *)[#"" stringByAppendingFormat:#"%#:%#", username, password];
self.encodedLoginData = [auth encodedAuthentication:authenticationString];
[auth release];
// Setup up the request with the url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:20.0];
[request setHTTPMethod:method];
[request setValue:[NSString stringWithFormat:#"Basic %#", encodedLoginData] forHTTPHeaderField:#"Authorization"];
self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
// Display the network indicator when the connection request started
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// Check that the NSURLConnection was successful and then initialize the responseData
if (connection) {
NSLog(#"Connection made");
self.responseData = [NSMutableData data];
} else {
NSLog(#"Connection could not be made");
}
}
...
- (void) dealloc
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[connection cancel];
[connection release];
[appDelegate release];
[responseData release];
[username release];
[password release];
[authenticationString release];
[encodedLoginData release];
[responseData release];
[childrensArray release];
[super dealloc];
}
Hope this helps for the next steps. However I think we will have to work a bit on the solution until it's final.
I'm getting the above error and have been looking at it all day, I'm getting no where fast. Anyone any ideas ? I'm new to IPhone Development. Code Below:
WorkoutAppDelegate.h...:
#import "WorkoutViewController.h"
#interface WorkoutAppDelegate : NSObject <UIApplicationDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
WorkoutViewController *viewController;
}
- (IBAction)saveAction:sender;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (nonatomic, readonly) NSString *applicationDocumentsDirectory;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet WorkoutViewController *viewController;
#end
WorkoutAppDelegate.m....:
#import "WorkoutAppDelegate.h"
#implementation WorkoutAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
viewController.managedObjectContext = [self managedObjectContext];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
/**
applicationWillTerminate: saves changes in the application's managed object context before the application terminates.
*/
- (void)applicationWillTerminate:(UIApplication *)application {
NSError *error;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort(); // Fail
}
}
}
/**
Performs the save action for the application, which is to send the save:
message to the application's managed object context.
*/
- (IBAction)saveAction:(id)sender {
NSError *error;
if (![[self managedObjectContext] save:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort(); // Fail
}
}
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"WorkoutCoreData.sqlite"]];
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
// Handle error
}
return persistentStoreCoordinator;
}
/**
Returns the path to the application's documents directory.
*/
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
- (void)dealloc {
[managedObjectContext release];
[managedObjectModel release];
[persistentStoreCoordinator release];
[viewController release];
[window release];
[super dealloc];
}
#end
WorkoutViewController.h...:
#import <UIKit/UIKit.h>
#import "Workout.h"
#protocol CreateWorkoutDelegate <NSObject>
-(void)didCancelWorkout;
-(void)didCreateWorkout:(NSString *)thisRoute
Type:(NSString *)thisType
Distance:(NSString *)thisDistance
Time:(NSString *)thisTime
Message:(NSString *)thisMessage;
#end
#interface WorkoutViewController : UIViewController {
// IBOutlet UIlabel *Speed;
// IBOutlet UIlabel *Calories;
IBOutlet UILabel *DBContents;
IBOutlet UITextField *route;
IBOutlet UITextField *type;
IBOutlet UITextField *distance;
IBOutlet UITextField *time;
IBOutlet UITextField *message;
IBOutlet UIButton *saveWorkout;
IBOutlet UIButton *cancelWorkout;
NSMutableArray *workoutArray;
id workoutDelegate;
Workout *currentWorkout;
NSManagedObjectContext *managedObjectContext;
}
//#property (retain,nonatomic) UILabel *Speed;
//#property (retain,nonatomic) UILabel *Calories;
#property (retain,nonatomic) UILabel *DBContents;
#property (retain,nonatomic) UITextField *route;
#property (retain,nonatomic) UITextField *type;
#property (retain,nonatomic) UITextField *distance;
#property (retain,nonatomic) UITextField *time;
#property (retain,nonatomic) UITextField *message;
#property (retain,nonatomic) NSMutableArray *workoutArray;
//#property (retain,nonatomic) UIButton *saveWorkout;
//#property (retain,nonatomic) UIButton *cancelWorkout;
#property (nonatomic, assign) id<CreateWorkoutDelegate> workoutDelegate;
#property (nonatomic, assign) NSManagedObjectContext *managedObjectContext;
-(IBAction)hideKeyboard;
-(IBAction)saveWorkout;
-(IBAction)cancelWorkout;
#end
WorkoutViewController.m...:
#import "WorkoutViewController.h"
#import "Workout.h"
#implementation WorkoutViewController
#synthesize workoutDelegate;
//#synthesize Speed;
//#synthesize Calories;
#synthesize route;
#synthesize type;
#synthesize distance;
#synthesize time;
#synthesize message;
#synthesize DBContents;
#synthesize workoutArray;
#synthesize managedObjectContext;
//#synthesize saveWorkout;
//#synthesize cancelWorkout;
-(IBAction)hideKeyboard {
}
-(IBAction)saveWorkout {
[workoutDelegate didCreateWorkout: route.text
Type: type.text
Distance: distance.text
Time: time.text
Message: message.text];
}
-(IBAction)cancelWorkout {
[self.workoutDelegate didCancelWorkout];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
-(void)viewDidLoad {
//Set images for Save & Cancel buttons.
UIImage *normalImage = [[UIImage imageNamed:#"whiteButton.png"]
stretchableImageWithLeftCapWidth:12.0
topCapHeight:0.0];
[saveWorkout setBackgroundImage:normalImage forState:UIControlStateNormal];
[cancelWorkout setBackgroundImage:normalImage forState:UIControlStateNormal];
UIImage *pressedImage = [[UIImage imageNamed:#"blueButton.png"]
stretchableImageWithLeftCapWidth:12.0
topCapHeight:0.0];
[saveWorkout setBackgroundImage:pressedImage forState:UIControlStateHighlighted];
[cancelWorkout setBackgroundImage:pressedImage forState:UIControlStateHighlighted];
//Fetch details from the database.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Workout" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSError *error;
self.workoutArray = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release];
//self.workoutArray = [[NSMutableArray alloc] init];
//self.DBContents.text = [self.workoutArray objectAtIndex:0];
[super viewDidLoad];
}
-(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.
}
-(void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void) didCreateWorkout:(NSString *)thisRoute
Type:(NSString *)thisType
Distance:(NSString *)thisDistance
Time:(NSString *)thisTime
Message:(NSString *)thisMessage {
// Add the new workout.
Workout *newWorkout = [NSEntityDescription
insertNewObjectForEntityForName:#"Workout"
inManagedObjectContext:self.managedObjectContext];
newWorkout.route = thisRoute;
newWorkout.type = thisType;
newWorkout.distance = thisDistance;
newWorkout.time = thisTime;
newWorkout.message = thisMessage;
[self.workoutArray addObject:newWorkout];
//[self dismissModalViewControllerAnimated:YES];
}
-(void)didCancelWorkout {
[self dismissModalViewControllerAnimated:YES];
}
-(void)dealloc {
// [Speed release];
// [Calories release];
[route release];
[type release];
[distance release];
[time release];
[message release];
// [saveWorkout release];
// [cancelWorkout release];
[workoutArray release];
[managedObjectContext release];
[super dealloc];
}
#end
I'm trying to save details that I key on the screen (WorkoutViewController.xib) and I click the save button and get the above error.
Thanks
Stephen
The error is saying that UiView does not know (does not implement) the method -(void)didCreateWorkout .......and really if you look where you have implemented this method, you will see it is in WorkoutViewController (WorkoutViewController.m), which is not an UIView (I presume you have only one implementation of didCreateWorkout in your project). You should double check how you set the workoutDelegate property. From the code you show us it should be an instance of WorkoutViewController.
Btw., because you are having the implementaion of the -(IBAction)saveWorkout also in WorkoutViewController the quick fix for this particular problem would be to change the code of your actions to:
-(IBAction)saveWorkout {
[self didCreateWorkout: route.text
Type: type.text
Distance: distance.text
Time: time.text
Message: message.text];
}
-(IBAction)cancelWorkout {
[self didCancelWorkout];
}
However, this quick fix will not fix the problem with the design you probably intended. You should think through who should implement CreateWorkoutDelegate and then properly set the workoutDelegate property.
On a different topic I noticed two things in your code, which you might to consider to change:
use self.property=nil instead of [ivar release] in your dealloc methods
NSString properties should have attribute copy (in order to protect yourself from NSMutableString instances)
Good luck! ;)