I am using a Core Data to save a UIImage that i get from my UIImagePickerController (source type = image library). I then Place or rather want to place the photo in a UICollectionViewCell, Please help and check to see what I am doing wrong.
Here is my UIImagePickerController it is called by a delegate.
-(void)requestAddScreen {
_picker = [[UIImagePickerController alloc] init];
_picker.delegate = self;
_picker.allowsEditing = NO;
_picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:_picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:#"Screen" inManagedObjectContext:context];
Screen* newScreen = [[Screen alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:context];
NSData *imageData = UIImagePNGRepresentation(image);
newScreen.image = imageData;
[_project addProjectScreensObject:newScreen];
NSError *error;
[context save:&error];
if (![context save:&error]) {
NSLog(#"Whoops %# %#", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:_picker completion:^{
[_collectionView reloadData];
}];
}
And Here is my ViewWillAppear meted. this is where I fetch the data from Core Data, id it Correct?
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:nil];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"EMO-KIT"];
[fetch setPredicate:predicate];
NSError *error;
NSArray *array = [context executeFetchRequest:fetch error:&error];
if (array.count == 1) {
_project = array[0];
} else {
_project = [NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:context];
[_project setValue:#"EMO-KIT" forKey:#"name"];
}
NSArray* screens = [[_project projectScreens] array];
NSIndexPath *bottomIndexPath=[NSIndexPath indexPathForRow:screens.count inSection:0];
[self.collectionView scrollToItemAtIndexPath: bottomIndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
}
You can convert UIImage to NSData and save into Core Data as below
Saving
NSData * imageData = UIImagePNGRepresentation(image);
[newsObj setValue:imageData forKey:#"Image"];
Retrieving
UIImage *image = [UIImage imageWithData:[screenObj valueForKey:#"Image"]];
Hope it helps you..
Related
Since I get into a requirement of saving NSDictionary offline and populate the table from it when the user is offline.
This is the code I have so far:
Everytime the resulting NSDictionary was getting as nil
I have made this attribute set as transformable
+ (void) insertIntoCoredata :(NSString *) table : (NSString *) attribute : (NSArray *) dic {
AppDelegate *appDelegate =(AppDelegate*)
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
appDelegate.managedObjectContext;
NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:dic];
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:table
inManagedObjectContext:context];
[object setValue:myData forKey:attribute];
NSError *error;
if (![context save:&error]) {
NSLog(#"Failed to save - error: %#", [error localizedDescription]);
}
}
+ (id) getFromCoredata :(NSString *) table : (NSString *) attribute {
AppDelegate *appDelegate =(AppDelegate*)
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
appDelegate.managedObjectContext;
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:table
inManagedObjectContext:context];
[fetch setEntity:entityDescription];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetch error:&error];
if([fetchedObjects count] == 1)
return [fetchedObjects objectAtIndex:0];
else
return nil;
}
What went wrong with this code.
I am developing iOS app, which fetch data from Web Services and save it to local database and uses it various views as needed. The data is fetch from Web Service and save to database correctly. But while accessing data from NSManagedObject it show FAULT and the consequent NSDictionary shows null Values
The code follows:-
-(void)SaveData:(NSInteger)menuId categoryID:(NSInteger)catID caption:(NSString *)title parentID:(NSInteger)parentID
{
BBAppDelegate *appDelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *userobj = [NSEntityDescription insertNewObjectForEntityForName:tableName
inManagedObjectContext:context];
[userobj setValue:[NSNumber numberWithInt:menuId] forKey:#"id"];
[userobj setValue:[NSNumber numberWithInt:catID] forKey:#"catid"];
[userobj setValue:[NSNumber numberWithInt:parentID] forKey:#"parentid"];
[userobj setValue:title forKey:#"caption"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
NSLog(#"app dir: %#",[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
}
-(NSArray *)fetchedData{
BBAppDelegate *appdelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *readData = [[NSFetchRequest alloc] init];
[readData setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription
entityForName:tableName inManagedObjectContext:context];
[readData setEntity:entity];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:readData error:&error];
// for (Test *test in array)
// {
// NSLog(#"Test: %# ", test.text);
// }
NSLog(#"%#",results);
return results;
}
-(void)removeData{
BBAppDelegate *appdelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *delData = [[NSFetchRequest alloc]init];
[delData setEntity:[NSEntityDescription entityForName:tableName inManagedObjectContext:context]];
[delData setIncludesPropertyValues:NO];
NSError *error = nil;
NSArray *result = [context executeFetchRequest:delData error:&error];
for (NSManagedObject *value in result) {
[context deleteObject:value];
}
NSError *saveError = nil;
[context save:&saveError];
}
-(void)table:(NSString *)nameTable{
tableName =nameTable;
}
- (instancetype)initWithTableName:(NSString *)tablename
{
[self table:tablename];
return self;
}
-(NSMutableArray *)buldMenu{
NSArray *array = [self fetchedData];
return [self getmenus:0 arr:array];
}
-(NSMutableArray *)getmenus:(NSInteger)parentID arr: (NSArray *)array
{
NSMutableArray *aray = [[NSMutableArray alloc]init];
for (NSManagedObject *dic in array) {
if (dic.faultingState != 0) {
NSLog(#"%lu",(unsigned long)dic.faultingState);
//return nil;
}
NSArray *keys = [[[dic entity] attributesByName] allKeys];
NSLog(#"%#",keys);
NSDictionary *dict = [dic dictionaryWithValuesForKeys:keys];
NSLog(#"%#",dic);
NSLog(#"%#",dict);
NSInteger pID = [[dict objectForKey:#"parentid"]integerValue];
if (pID == parentID) {
BBMenuEntry *entryMenu = [[BBMenuEntry alloc]init];
entryMenu.menuID = [[dict objectForKey:#"id"]integerValue];
entryMenu.catID = [[dict objectForKey:#"catid"]integerValue];
entryMenu.caption = [dict objectForKey:#"caption"];
entryMenu.subMenus = [self getmenus:entryMenu.menuID arr:array];
[aray addObject:entryMenu];
}
}
return aray;
}
I am Using core data as my data base. Inside my UITableView I have a button to add projects , But at this moment I only Use it to add names. But the names I add do not display on the tableview.
I think my problem is that I need to repopulate my projectArray, how and where do I do that.
Here is my code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_projectArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Project* project = _projectArray[indexPath.row];
static NSString *cellID = #"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
cell.textLabel.text = project.name;
cell.detailTextLabel.text = #"prooo";
self.tableView.delegate = self;
self.tableView.dataSource = self;
return cell;
}
Here is my button code:
- (IBAction)addProjectButton:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Enter new project name."
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
UITextField *textField = [alert textFieldAtIndex:0];
textField.placeholder = #"Project Name";
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != alertView.cancelButtonIndex) {
UITextField *field = [alertView textFieldAtIndex:0];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
NSManagedObject *object =[NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:context];
[object setValue:field.text forKey:#"name"];
NSError *error;
[context save:&error];
if (![context save:&error]) {
NSLog(#"Whoops %# %#", error, [error localizedDescription]);
}
[self.tableView reloadData];
} else {
NSLog(#"cancel");
}
}
And here is my ViewWillAppear Code , where I fetch info:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:nil];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
}
There are many things you can do. To make it a good code, I will suggest write a method that reloads your array. Like this
-(void) reloadArray
{
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
}
Then replace your viewDidAppear like this -
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:nil];
[self reloadArray];
}
Also in your numberOfSectionsInTableView: method, make this change -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
[self reloadArray];
return 1;
}
And it should do the magic...
Have you set the dataSource and delegate properties of tableView?
self.tableView.delegate = self;
self.tableView.dataSource = self;
Change This :
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
To:
_projectArray = [[NSMutableArray alloc]init];
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSManagedObject *object = nil;
NSError *error;
NSArray *result = [context executeFetchRequest:fetch error:&error];
for (int i = 0; i < [result count]; i ++) {
object = [result objectAtIndex:i];
[_projectArray setObject:[object valueForKey:#"name"]
}
Error is below:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an entity named 'Contacts' in this model.'
Code of fetching data from photo library:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
UIImage *img = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
NSError *error;
NSManagedObjectContext *context;
context = [self managedObjectContext];
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"Contacts" inManagedObjectContext:context];
NSData *data=UIImageJPEGRepresentation(img,0.0);
[object setValue:data forKey:#"image"];
[context save:nil];
[self fetchData];
}
My fetch() method coding.
-(void)fetchData{
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Contacts"
inManagedObjectContext:context]];
NSError * error = nil;
NSArray * objects = [context executeFetchRequest:request error:&error];
if ([objects count] > 0) {
NSManagedObject *object = objects[0];
data1 = [object valueForKey:#"image"];
image2 = [[UIImage alloc]initWithData:data1];
imgviewofprofilepic.image=image2;
}}
And coding of NSManagedObjectContext()
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
Once again, since Core Data is new to me, I need assistance. Basically, I need to edit a specific Core Data object from a view outside the tableview, save it, and reload the tableview. I can manage reloading the tableview, but I cannot figure out how to find the specific Core Data object for that indexPath entry. I don't have any code because I cannot find anything to suit my purpose.
Detail (Editor)
-(IBAction)cancel:(id)sender{
NSLog(#"Sent!");
// [self dismissViewControllerAnimated:YES completion:nil];
// [self.view.superview removeFromSuperview];
OweDetails *details = info.details;
[info setValue:oField.text forKey:#"name"];
info.name = oField.text;
[UIView animateWithDuration:0.5
delay:1.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.master = [[MasterViewController alloc]init];
[self dismissSemiModalViewController:self];
[self.master.tableView reloadData];
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
Master (TableView)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"I tapped myself!");
OweInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
self.tdModal = [[TDSemiModalViewController alloc]init];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
FooterViewController *fvc = [[FooterViewController alloc]init];
OweDetails *details = info.details;
[self.tdModal setDetailItem:info.name];
[self.tdModal setMoneyItem:details.money];
// [self.view addSubview:test.view];
self.tdModal.managedObjectContext = self.managedObjectContext;
self.tdModal.managedObjectContext = self.managedObjectContext;
OweInfo *info2 = (OweInfo *)[nameArray objectAtIndex:indexPath.row];
self.tdModal.info = info2;
[self presentSemiModalViewController:self.tdModal];
}
If you're using an NSFetchedResultsController, ask it for the objectAtIndexPath:.
AppDelegate* appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext* context = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"YOUR_ENTITY_NAME" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SOME_PREDICATE_USED_TO_UNIQUELY_IDENTIFY_YOUR_INDEXPATH ==%#", #"VALUE"];
[fetchRequest setPredicate:predicate];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
NSError* error;
NSArray* array = [context executeFetchRequest:request error:&error];
if (error)
{
NSLog(#"Error fetching data. %#", error);
return nil;
}
if (array.count != 1)
{
NSLog(#"Invalid number (%d) of objects found", array.count);
return nil;
}
return [array objectAtIndex:0];
Edit: This is in response to you asking about more details.
The code above can be its own function. I will give you a simple example of how you can use it.
-- In the VC where you have the table and are displaying the data
1: Let us assume your entity is called MyEntity and that it has an integer unique identifier field called myEntityUniqueId.
2: In your cellForRowAtIndexPath, you would write:
cell.tag = myCurrentEntity.myEntityUniqueId
-- Now lets go to your other VC where you want to retrieve the instance of MyEntity represented by the cell that was tapped.
1: Write the function:
-(void) findMyEntityForId:(int) tappedUniqueId
{
AppDelegate* appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext* context = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"MyEntity" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"myEntityUniqueId ==%d", tappedUniqueId];
[fetchRequest setPredicate:predicate];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
NSError* error;
NSArray* array = [context executeFetchRequest:request error:&error];
if (error)
{
NSLog(#"Error fetching data. %#", error);
return;
}
if (array.count != 1)
{
NSLog(#"Invalid number (%d) of objects found", array.count);
return;
}
MyEntity* foundResult = [array objectAtIndex:0]; // <-- This is the instance you are looking for.
}
2: Now call the above function with the correct argument.
I haven't tested the code but it should be fine.