Am trying to display the timestamp a new post is made on a label but in don't seem to get around with it please help
Have tried using NSDate() but am getting an abort() error from the Appdelegate
You would need to add a property to the entity called creationDate and sets its value on insert.
#interface YourEntity : NSManagedObject
#property (nonatomic, copy) NSDate *creationDate;
#end
#implementation YourEntity
#dynamic creationDate;
- (void)awakeFromInsert
{
[super awakeFromInsert];
self.creationDate = [NSDate date];
}
#end
Then, just access the property when you need it.
Related
I'm using core data in Xcode 7 beta 6 and I just generated categories and managed object subclasses for each of my entities. The issue is that when I try to utilize the properties created from the attributes in my model, I get a "use of undeclared identifier" error. I was under the impression that I was supposed to put custom behavior in the managed object subclass that were generated, however I was not clear on how I could use the properties from the categories in the managed object subclass, so I placed the custom behavior in the categories as shown below. I feel like I'm merely missing an import statement, but I'm not sure. I understand I'm using beta software.
Core Data Model:
Thought+CoreDataProperties.h:
#import "Thought.h"
NS_ASSUME_NONNULL_BEGIN
#interface Thought (CoreDataProperties)
#property (nullable, nonatomic, retain) NSString *objectId;
#property (nullable, nonatomic, retain) id recordId;
#property (nullable, nonatomic, retain) Collection *parentCollection;
#property (nullable, nonatomic, retain) NSNumber *placement;
#property (nullable, nonatomic, retain) NSString *text;
#property (nullable, nonatomic, retain) NSString *extraText; // allows for extra description text to be set. Should be in smaller print than headline text and should only appear as an option in text != nil
#property (nullable, nonatomic, retain) NSSet<Photo *> *photos;
#property (nullable, nonatomic, retain) id location; // place a CLLocation here
#property (nullable, nonatomic, retain) id tags; // place an NSArray here
#property (nullable, nonatomic, retain) NSDate *creationDate;
#pragma mark - Initializers
/*!
#abstract this method converts a CKRecord into a Thought object
#discussion parentCollection will still be nil after this method executes
*/
-(nullable instancetype) initWithRecord: (nonnull CKRecord *) record;
/*!
#abstract this method converts a CKRecord into a Thought object. photos set is not populated
*/
-(nullable instancetype)initWithRecord: (nonnull CKRecord *) record collection: (nonnull Collection *) collection;
/*!
#abstract Creates a new Thought object with generic recordId, objectId, placement, and photos array
#discussion parentCollection will still be nil after this method executes
*/
-(nullable instancetype) init;
… other methods
#end
#interface Thought (CoreDataGeneratedAccessors)
- (void)addPhotosObject:(Photo *)value;
- (void)removePhotosObject:(Photo *)value;
- (void)addPhotos:(NSSet<Photo *> *)values;
- (void)removePhotos:(NSSet<Photo *> *)values;
#end
NS_ASSUME_NONNULL_END
Thought+CoreDataProperties.m:
#import "Thought+CoreDataProperties.h"
#implementation Thought (CoreDataProperties)
#dynamic creationDate;
#dynamic extraText;
#dynamic location;
#dynamic objectId;
#dynamic placement;
#dynamic recordId;
#dynamic tags;
#dynamic text;
#dynamic parentCollection;
#dynamic photos;
-(nullable instancetype) init {
self = [super init];
if (self) {
// THIS IS WHERE I GET MANY ERROR FOR USE OF UNDECLARED IDENTIFIER
_objectId = [IdentifierCreator createId];
_recordId = [[CKRecord alloc] initWithRecordType:THOUGHT_RECORD_TYPE zoneID:[[CKRecordZone alloc] initWithZoneName:ZONE_NAME].zoneID].recordID;
_photos = [NSArray new];
_placement = [NSNumber numberWithInt:0];
_creationDate = [NSDate date];
}
return self;
}
-(instancetype) initWithRecord:(nonnull CKRecord *)record {
self = [super init];
if (self) {
_objectId = [record objectForKey:OBJECT_ID_KEY];
_recordId = [record recordID];
_text = [record objectForKey:TEXT_KEY];
_extraText = [record objectForKey:EXTRA_TEXT_KEY];
_location = [record objectForKey:LOCATION_KEY];
_photos = [NSSet new];
_tags = [record objectForKey:TAGS_KEY];
_placement = [record objectForKey:PLACEMENT_KEY];
_creationDate = record.creationDate;
}
return self;
}
-(instancetype) initWithRecord:(CKRecord *)record collection:(Collection *)collection {
self = [self initWithRecord:record];
self.parentCollection = collection;
return self;
}
Thought.h:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Frameworks.h" // includes Frameworks I'm using and some string constants
#import "ForFundamentals.h" // includes mostly string constants
#import "Photo.h"
#import "Collection.h"
#class Collection, Photo;
NS_ASSUME_NONNULL_BEGIN
#interface Thought : NSManagedObject
// I think I should put method declarations here
#end
NS_ASSUME_NONNULL_END
#import "Thought+CoreDataProperties.h"
Thought.m:
#import "Thought.h"
#import "Collection.h"
#import "Photo.h"
#implementation Thought
// I think I should put method implementations here
#end
Subclasses of NSManagedObject do their initialization in awakeFromInsert or awakeFromFetch. Don't override init or implement initWith.... You have to wait until the object is instantiated, and alive within an NSManagedObjectContext, before you can set its properties.
Don't assign collection instances to your ivars corresponding to Core Data relationships (i.e. _photos, parentCollection. Core Data will do that for you when you insert or fetch the object.
Instead of your init methods, rethink your approach. Write a method insertInManagedObjectContext:withSKRecord. That method calls -insertNewObjectForEntityForName:#"Thought" inManagedObjectContext:foo, which returns an instance of Thought. Now, with that istance, set the objecgtID, recordID, etc–but with your accessors, not by directly banging the instance variables.
So it seems that although I can't use _name = #"string" syntax to set property values, I can use method syntax, like [self setName: #"string"]. This seems very strange to me. However, the method syntax does work in both the subclass and the category so I guess problem solved… for now.
UPDATE
I didn't understand #dynamic. This post helped clear it up. I can't use _propertyName because the accessor methods are dynamically created by core data.
I have below.
#interface MyViewController () {
NSDate *myCurrentDate;
}
#implementation MyViewController
-(void)viewDidLoad {
[super viewDidLoad];
myCurrentDate = [NSDate date];
}
- (IBAction) prevAction:(id)sender {
NSLog(#"myCurrentDate===%#", myCurrentDate); // here it says
myCurrentDate = [myCurrentDate dateByAddingTimeInterval:60*60*24*-1];
[self formatDateAndPostOnButton];
}
When I try to print current date as below, it crash saying BAD_EXCESS
NSLog(#"myCurrentDate===%#", myCurrentDate);
Below is the screenshot for the same.
I'm not using ARC in my project.
Any idea what is going wrong?
Since you are not using ARC, easiest way to retain objects is to use generated setters/getters.
Instead of:
#interface MyViewController () {
NSDate *myCurrentDate;
}
make
#interface MyViewController ()
#property(nonatomic, retain) NSDate* myCurrentDate;
#end
So it will keep NSDate retained. Right now your NSDate gets deallocated when the auto-release pool is drained.
You will need to use the getters/setters provided, however:
self.myCurrentDate = [self.myCurrentDate dateByAddingTimeInterval:60*60*24*-1];
Anyways I would recommend start using ARC to make your life simpler and avoid strange memory crashes.
I'm following a tutorial from Lynda regarding creating a UIDatePicker, and here's what my code looks like:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIDatePicker *datePicker;
...
#end
ViewController.m
#import "ViewController.h"
...
#implementation ViewController
...
- (IBAction)displayDate:(id)sender {
NSDate *chosen = [datePicker date];
...
}
#end
but for some reason XCode is giving me an error:
"unknown receiver 'datePicker'
Just a note, the datePicker is linked. Is there something that I'm missing?
Forget to #syntesize
Your UIPickerView to your .m file
and also your can access by UIPickerView by name _datePicker
In this case you have datePicker property which is accessible by self.datePicker, or instance variable (generated for you by compiler) _datePicker. You really want the former.
When using properties, you must call self first:
NSDate *chosen = [self.datePicker date];
Or
NSDate *chosen = [[self datePicker] date];
I have faced a problem I can not see the problem to. I am trying to pass a simple NSString to a child variable but it continues to return as null even when I use NSLog to show there is a string in the variable.
The variable finalDate will not pass to the child view.
Parent View
ChangeTimeViewController *ChangeTimeView = [[ChangeTimeViewController alloc] init];
NSLog(#"%#", date);
ChangeTimeView.finalDate = date;
[ChangeTimeView setDelegate:self];
[self.navigationController pushViewController:ChangeTimeView animated:YES];
Child View .H
#import <UIKit/UIKit.h>
#protocol ChangeTimeViewControllerDelegate;
#interface ChangeTimeViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>
#property (nonatomic, weak) id <ChangeTimeViewControllerDelegate> delegate;
#property (nonatomic) NSString *enteredTime;
#property (nonatomic, strong) UIPickerView *UIPicker;
#property (nonatomic, strong) NSString *finalDate;
#end
#protocol ChangeTimeViewControllerDelegate <NSObject>
- (void)childTimeViewController:(ChangeTimeViewController *)viewController didChooseValue:(NSString *)string;
#end
Child View .M
NSLog(#"%#", self->finalDate);
What you are doing is perfectly fine. You should insert the NSLog in the view(Did/Will)Appear or some similar method and you may use the self.finalDate notation to make sure you don't try to read some uninitialized ivar.
Note: properties synthesize ivars with _ as prefix (_finalDate is the correct storage unless you synthesized it it with some other name)
If you want to make sure that all input parameters are passed to the view controller, then create an init method for it. Similar to this:
- (id)initWithDate:(NSDate*)date delegate:(id)delegate
Pass NSString As ChangeTimeView.finalDate = #"This Is my Simple String"; and use/put NSLog in viewDidLoad method for show is it rich at nextViewController or not ?? Otherwise if your date (NSString) is proper then Your code is correct.
Check what is happening if you set like,
ChangeTimeView.finalDate = #"MyString";
and in view.m log NSLog(#"%#", self.finalDate);
I'm pretty new to Core Data, and objective-c. I have been up and down the Core Data documentation, and don't know what I'm doing wrong here.
At runtime, I'm getting the following error when adding the NSManagedObject "ReportItem" to the NSMutableSet "reports" in the NSManagedObject "RoomItem": NSUnknownKeyException', reason: '[<RoomItem 0x747c850> valueForUndefinedKey:]: the entity RoomItem is not key value coding-compliant for the key "reports"
The error is occurring inside of the "RoomList" store class in the "creatReportForRoom" method below, which is called upon viewWillDisapear in the UIViewController where the relevant data is entered:
- (ReportItem *)creatReportForRoom:(RoomItem *)currentRoom Report:(ReportItem *)report
{
NSDate *dateCreated = [NSDate date];
ReportItem *detailItem = [NSEntityDescription insertNewObjectForEntityForName:#"ReportItem" inManagedObjectContext:context];
[detailItem setDateReportCreated:dateCreated];
NSMutableSet *reports = [currentRoom mutableSetValueForKey:#"reports"];
[reports addObject:detailItem]; //error is occurring at this line
[allReports addObject:detailItem];
return detailItem;
}
The "RoomItem" NSManagedObject files are here:
RoomItem.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface RoomItem : NSManagedObject
#property (nonatomic, strong) NSString *building;
#property (nonatomic, strong) NSString *room;
#property (nonatomic, retain) NSString *imageKey;
#property (nonatomic, retain) UIImage *buildingImage;
#property (nonatomic, strong) UIImage *buildingThumbnail;
#property (nonatomic, strong) NSData *buildingThumbnailData;
#property (nonatomic) double objectIndex;
#property (nonatomic, strong) NSDate *dateCreated;
#property (nonatomic, retain) NSMutableSet *reports;
#end
RoomItem.m
#import "RoomItem.h"
#implementation RoomItem
#dynamic building, buildingThumbnail, buildingThumbnailData, objectIndex, room, dateCreated, imageKey, buildingImage, reports;
#end
I've including the "createItem" method were the RoomItem is created and stored, in case I'm doing something wrong there:
- (RoomItem *)createItem
{
double order;
//create new roomItem
//tracks what number item it's creating
if ([allItems count] == 0) {
order = 1.0;
}
else
{
order = [[allItems lastObject] objectIndex] + 1;
}
NSLog(#"Adding after %d items, order = %.2f", [allItems count], order);
RoomItem *detailItem = [NSEntityDescription insertNewObjectForEntityForName:#"RoomItem"
inManagedObjectContext:context];
[detailItem setObjectIndex:order];
[detailItem setDateCreated:[NSDate date]];
[allItems addObject:detailItem];
return detailItem;
}
Data Model with relationships:
Relationship Diagram:
Any advice on fixing this problem would be hugely appreciated. Please let me know if there's anything I failed to include that might help.
Thanks!
There is a discrepancy between the Core Data model shown in your image and your code.
In the model image, reports is a relationship from ReportItem to RoomItem.
Your code treats it as a relationship from RoomItem to ReportItem.
If the latter is what you want, then you have to name the relationships in the Core Data model editor correctly: reports as a relationship on RoomItem and roomReportsFor as the inverse relationship on ReportItem.
I also strongly recommend that you don't write the managed object subclass files yourself, but let it generate by Xcode: Select the entities in the Core Data model editor, and choose "Editor -> Create NSManagedObject Subclass ..." from the menu.
There is another error in your "RoomItem.h" file: The data type for to-many relationships is NSSet, not NSMutableSet.
Using the Xcode created managed object subclass files helps to avoid such inconsistencies and errors. You only have to remember to re-created the files after changes in the Core Data model.
(Just for the sake of completeness: There are also other tools to create the managed object subclasses, such as mogenerator, which some people recommend.)
This is a simplified version of what I think the relationships should look like:
reports: from RoomItem to ReportItem (to-many relationship),
room: from ReportItem to RoomItem (to-one relationship, inverse of reports).
I have experienced this as well when updating the Core Data model. In some cases it seems as the simulator holds on to the old model. This can usually be fixed by deleting the app from the simulator and clean/build.