I have a class which should hold some data:
the header:
#import <Foundation/Foundation.h>
#class Behandler, Tag;
#interface OeffnungsZeit2 : NSObject
#property (nonatomic, retain) NSNumber * offen_stunde;
#property (nonatomic, retain) NSNumber * offen_minute;
#property (nonatomic, retain) NSNumber * geschlossen_stunde;
#property (nonatomic, retain) NSNumber * geschlossen_minute;
#property (nonatomic, retain) Tag *tag;
#property (nonatomic, retain) Behandler *behandler;
-(void)setTag:(Tag *)tag;
-(Tag *)getTag;
-(void)setBehandler:(Behandler *)behandler;
-(Behandler *)getBehandler;
#end
the main file:
#import "OeffnungsZeit2.h"
#import "Behandler.h"
#import "Tag.h"
#implementation OeffnungsZeit2
#dynamic offen_stunde;
#dynamic offen_minute;
#dynamic geschlossen_stunde;
#dynamic geschlossen_minute;
-(void)setTag:(Tag *)tag{
self.tag = tag;
}
-(Tag*)getTag{
return self.tag;
}
-(void)setBehandler:(Behandler *)behandler{
self.behandler = behandler;
}
-(Behandler*)getBehandler{
return self.behandler;
}
#end
When I try to access it, somewhere in these lines:
NSArray *tage = [self fetchTageWithNummer:openDay];
Tag *tag = [tage objectAtIndex:0];
// create an OeffnungsZeit2 object and add it to our array
OeffnungsZeit2 *oeffnungsZeit2 = [[OeffnungsZeit2 alloc] init];
[oeffnungsZeit2 setTag:tag];
oeffnungsZeit2.offen_stunde = [NSNumber numberWithInt:[openHours intValue]];
oeffnungsZeit2.offen_minute = [NSNumber numberWithInt:[openMins intValue]];
oeffnungsZeit2.geschlossen_stunde = [NSNumber numberWithInt:[closeHours intValue]];
oeffnungsZeit2.geschlossen_minute = [NSNumber numberWithInt:[closeMins intValue]];
[self.oeffnungsZeiten addObject:oeffnungsZeit2];
I am getting an ECX_BAD_ACCESS error.
Can anyone hint me, why this is wrong? I am pretty new to iOS, and never wrote a class which holds data...
It looks like you are getting a stack overflow error when your getters/setters call themselves. For example, this code
-(void)setTag:(Tag *)tag{
self.tag = tag;
}
is infinite recursion, because self.tag = tag is another syntax for writing [self setTag:tag].
If you are using the latest Xcode, all you need to do is dropping the declarations and definitions of the getters and setters for tag and behandler that you have added manually. The compiler will generate the code that is equivalent, but has no infinite recursion.
Note: there are legitimate cases when you need to access the variable that "backs" an automatically generated property. By convention, the name of that variable is the name of the property prefixed with an underscore. You can override this in the #synthesize directive for the property.
Related
I have a problem in Xcode.I am trying to copy one NSString into other one but is not working.
The original NSString pageTitle is on the RestViewController:
This is my RestViewContoller.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
#property (nonatomic, strong) Restaurant *DetailModal;
#property (nonatomic, strong) NSString *pageTitle;
#property (nonatomic, strong) NSString *pageDescription;
#end
The NSString I want to save the data is on the RestViewController:
#property (nonatomic, strong) Restaurant *DetailModal;
but is a Restaurant class type.
My Restaurant class is:
Restaurant.h:
#import <Foundation/Foundation.h>
#interface Restaurant : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *desc;
#property (nonatomic, copy) NSString *image;
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image;
#end
Restaurant.m:
#import "Restaurant.h"
#implementation Restaurant
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image {
self = [super init];
if (self != nil) {
self.title = title;
self.desc = description;
self.image = image;
}
return self;
}
#end
And finally the place where I want to copy this NSStrings is my RestViewController.m:
#import "RestViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RestViewController ()
#end
#implementation RestViewController
- (void)viewDidLoad {
[super viewDidLoad];
_pageTitle = #"Test";
_DetailModal.title = _pageTitle;
NSLog(#"_DetailModal.title: %#", _DetailModal.title);
}
#end
The problem is when I see the result of the
NSLog(#"_DetailModal.title: %#", _DetailModal.title);on the console,
it puts me:2016-11-21 11:42:05.407 MadEat[3667:104028]
_DetailModal.title: (null)
What can I do? I know I have a low level of Xcode, but I need your help please. Thank you very much.
Initailize the instance of DataModel First.
Then proceed with assignment
_DetailModal = [[DetailModal alloc] init:_pageTitle descripiton:#"Desc" image:#"image"];
There is a instance method defined already to do the task.
After this also you can alter the value by
_DetailModal.title = #"title_of_yours"
If you have to use detailmodal, you must alloc the restaurant class object (detailmodal). Then only the objects can be used.
detailmodal=[[restaurant alloc]init];
detailmodal.title=_pagetitle;
Before you can use a object, you have to create it first.
DetailModal *detailModal = [DetailModal new];
That way the object will be created and values stored to the class properties will be reserved.
Try:
_DetailModal.title = [[NSString alloc] initWithString: _pageTitle];
(Did not test this)
plz chek you _DetailModal is not nil
if it's nil then
first you need to alloc the memory for you DetailModal Class object
like this
DetailModal *detailModal = [DetailModal new];
then after set the value you want
detailModal.title = _pageTitle;
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 the class LearnfestItem.h :
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface LearnfestItem : NSObject
#property (strong, nonatomic) NSString * itemId;
#property (strong, nonatomic) NSString * itemTitle;
#property (strong, nonatomic) NSString * itemDescription;
#property (strong, nonatomic) NSString * itemContent;
#property (strong, nonatomic) NSString * itemType;
#property (strong, nonatomic) UIImage * itemImage;
#property (strong, nonatomic) NSDate * itemRegistered;
-(id)initWithData:(NSDictionary *)data andImage:(UIImage *)image;
#end
& Object.m :
#import "LearnfestItem.h"
#import "Defaults.h"
#implementation LearnfestItem
-(id)init
{
self = [self initWithData:nil andImage:nil];
return self;
}
-(id)initWithData:(NSDictionary *)data andImage:(UIImage *)image
{
self = [super init];
self.itemId = data[ITEM_ID];
self.itemTitle = data[ITEM_TITLE];
self.itemDescription = data[ITEM_DESCRIPTION];
self.itemContent = data[ITEM_CONTENT];
self.itemType = data[ITEM_TYPE];
self.itemImage = image;
self.itemRegistered = data[ITEM_REGISTERED];
return self;
}
#end
In my UIViewController I have a UITableView that creates a NSMutableArray of LearnfestItems within the cellForRowAtIndexPath method:
LearnfestItem * createLearnfestItem = [[LearnfestItem alloc] initWithData:learnfestItemDictionary andImage:learnfestItemImage];
NSLog(#"Insert learnfest item with id: %# at index %li", createLearnfestItem.itemId, (long)row);
[self.learnfestItemObjects insertObject:createLearnfestItem atIndex:row];
On didSelectRowAtIndexPath I want to receive the LearnfestItem from the NSMutableArray I do this by calling:
self.selectedLearnfestItem = [self.learnfestItemObjects objectAtIndex:indexPath.row];
Then I want to send it to another view controller to present the data I do this in the prepareForSegue segement:
LearnfestItemViewController * learnfestVC = [segue destinationViewController];
NSLog(#"Sending learnfest item with id: %#", self.selectedLearnfestItem.itemId);
learnfestVC.item = self.selectedLearnfestItem;
When I try to access my LearnfestItem's properties within cellForRowAtIndexPath. All I get is null... and so forth in my other table view delegate methods.. Can anyone spot what i'm doing wrong? Thanks
Code you show is missing all error and validity checking. When using NSAssert() and item.length/item.count checks, you will know what's going on.
However, based on your code I'd suggest two things:
All objects which also have mutable version should use "copy" properties. Now you have "strong" pointer to data received via init method, but if you reset the originally given data variable to point elsewhere (e.g. reusing one data variable inside for loop to init multiple items), then... I don't know what your LearnfestItem item properties will point to.
Make sure your LearnfestItemViewController *item is a copy, too.
My guess is that everything is initialised correctly, but the data disappears afterwards.
For example:
#property (nonatomic, copy) NSString * itemId; // Safe
#property (nonatomic, strong) NSString * itemId; // Not safe
When your property class has mutable variations (e.g. NSString vs. NSMutableString vs. MyMutableString), copy is safer. Using strong will create a pointer to original data, which could have been a mutable instance and could be modified afterwards. Using strong will always point to original data, even after it has been changed.
Second part:
learnfestVC.item = self.selectedLearnfestItem;
Your LearnfestItemViewController contains some property related to LearnfestItem class. Make sure it's a copy, too. When using segues, the calling object quite often just disappears. Make sure your new controller has local copy of all needed data (or use a protocol delegate, but that's a longer discussion)
Adding error and data validity checking will make your task a lot easier. Instead of trying to figure out afterwards why something doesn't work, you'll get notifications when something isn't as you're expecting.
Here's quick and dirty "maintenance" for your code. What you should get out of this is some ideas what to check, where and how. In normal situations this is overkill, but now you have a mysterious problem and need to find it. It can be hard and monotonous work.
#import Foundation;
#import UIKit;
#interface LearnfestItem : NSObject
#property (copy, nonatomic) NSString *itemId;
#property (copy, nonatomic) NSString *itemTitle;
#property (copy, nonatomic) NSString *itemDescription;
#property (copy, nonatomic) NSString *itemContent;
#property (copy, nonatomic) NSString *itemType;
#property (strong, nonatomic) UIImage *itemImage;
#property (strong, nonatomic) NSDate *itemRegistered;
- (instancetype)initWithData:(NSDictionary *)data andImage:(UIImage *)image;
#end
Object.m :
#import "Defaults.h"
#import "LearnfestItem.h"
#implementation LearnfestItem
- (instancetype)init
{
self = [self initWithData:nil andImage:nil];
return self;
}
- (instancetype)initWithData:(NSDictionary *)data andImage:(UIImage *)image
{
NSAssert(data.length, #"My Assert: missing data");
NSAssert(image, #"My Assert: missing image");
if ((self = [super init]))
{
// TODO: nil ok, if doesn't exist?
_itemId = data[ITEM_ID];
_itemTitle = data[ITEM_TITLE];
_itemDescription = data[ITEM_DESCRIPTION];
_itemContent = data[ITEM_CONTENT];
_itemType = data[ITEM_TYPE];
_itemImage = image;
_itemRegistered = data[ITEM_REGISTERED];
}
return self;
}
#end
"(original text) In my UIViewController I have a UITableView that creates a NSMutableArray of LearnfestItems within the cellForRowAtIndexPath method:"
NSAssert(learnfestItemDictionary.count, #"My Assert: missing dict");
NSAssert(learnfestItemImage, #"My Assert: missing image");
LearnfestItem *createLearnfestItem = [[LearnfestItem alloc] initWithData:learnfestItemDictionary andImage:learnfestItemImage];
NSLog(#"Insert learnfest item with id: %# at index %#", createLearnfestItem.itemId, #(row));
NSAssert(createLearnfestItem, #"My Assert: missing item");
NSAssert(self.learnfestItemObjects.count > row, #"My Assert: learnfestItemObjects");
self.learnfestItemObjects[row] = createLearnfestItem;
"(original text) On didSelectRowAtIndexPath I want to receive the LearnfestItem from the NSMutableArray I do this by calling:"
NSAssert(self.learnfestItemObjects.count > indexPath.row, #"My Assert: learnfestItemObjects");
self.selectedLearnfestItem = self.learnfestItemObjects[indexPath.row];
"(original text) Then I want to send it to another view controller to present the data I do this in the prepareForSegue segment:"
LearnfestItemViewController *learnfestVC = (LearnfestItemViewController *)[segue destinationViewController];
NSLog(#"Sending learnfest item with id: %#", self.selectedLearnfestItem.itemId);
learnfestVC.item = self.selectedLearnfestItem;
I am trying to create a class in with properties defined in the header. Was planning to populate the object in a for loop. Here is the header, what could I be doing wrong? Am I defining this class wrong?
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<UIPickerViewDataSource,
...
#end
#interface PickerObject : NSObject
{
NSString *minutes;
NSNumber *label;
}
#end
In the viewDidLoad I get message saying property minutes not found.
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int x = 0; x < total; x++)
{
PickerObject *myObject = [[PickerObject alloc] init];
myObject.minutes = x;
myObject.label = #"%# minutes",x;
[_pickerData addObject:myObject];
//[_pickerData addObject:[NSNumber numberWithInt:x]];
[arr addObject:[NSNumber numberWithInt:x]];
}
Here is a screenshot of the error depicting property not found
To access object variables using the dot '.' operator in Objective-C, you need a setter method. The easiest way to achieve this is by defining a property instead, like this:
#interface PickerObject : NSObject
{
}
#property (nonatomic, strong) NSString *minutes;
#property (nonatomic, strong) NSNumber *label;
#end
The object variables, setter- and getter methods you need will be synthesised automatically.
I'm trying to pass a custom class between views. I have set a property for that class but when i access the property, the attributes return always null:
firstview.m:
- (void)initNextEventView{
NSDate *eventDate = [eventDatePicker date];
NSString *eventName = eventNameTextfield.text;
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
[[self navigationController] pushViewController:locView animated:YES];
}
LocateEventVC.h (2. view):
#interface LocateEventViewController : UIViewController<MKMapViewDelegate, UISearchBarDelegate, BSForwardGeocoderDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *imageBackground;
#property (strong, nonatomic) EventDTO *eventDTO;
so when i log a attribute of eventDTO it returns null..
any help would be great
EDIT 1 (2. view):
Thats how I log:
NSLog(#"name on 2. view: %#", eventDTO.name);
self.eventDTO.place = tmpEventPlace;
// init friends view!
//passing to next view
EventMembersViewController *members = [[EventMembersViewController alloc]init];
members.eventDTO = self.eventDTO;
EventDTO.h
#interface EventDTO : NSObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) UserDTO * creatorIsAppUser;
#property (nonatomic, retain) ContactDTO * creatorIsNotAppUser;
#property (nonatomic, retain) NSString * description;
#property (nonatomic, retain) NSDate * date;
#property (nonatomic, readwrite) NSInteger *eventID;
#property (nonatomic, retain) CustomPlacemark * place;
#property (nonatomic, retain) NSMutableArray *invitedMembers;
#property (nonatomic, retain) NSMutableArray *acceptedMembers;
- (NSNumber*)getLatidude;
- (NSNumber*)getLongitude;
EventDTO.m
#synthesize place, date, eventID, name, acceptedMembers, description, invitedMembers;
- (NSNumber*)getLatidude{
return [NSNumber numberWithDouble:place.coordinate.latitude];
}
- (NSNumber*)getLongitude{
return [NSNumber numberWithDouble:place.coordinate.longitude];
}
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
When you initiating locView, the object eventDTO doesn't exists. You have to initiate a new eventDTO right there, e.g.:
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
YourClass *eventDTO = [[YourClass alloc] init];
locView.eventDTO = eventDTO;
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
or directly in the -initmethod of your LocateEventViewController by adding
-(id)init {
...
self.eventDTO = [[YourClassHere alloc] init];
...
}
Please see this post for a full explanation. In short, you're going about it wrong:
Passing Data between View Controllers
Are you sure that the property eventDTO is set or allocated before accessing eventName and eventDate?
My guess is that eventDTO itself is nil. Calling method or accessing properties on nil objects is allowed in Objective-C. It does not crash as it would do in C++ or Java, it simply does nothing and returns nil if ht method has a return value.
I guess the property eventDTO is not properly initialized and it is nil itself.
Sending message to nil is legal in Objective-C, it simply fails silently and returns nil. It's a common pitfall when learning Objetive-C. And accessing property is just a syntactic sugar of sending messages.
BTW, "empty object" in Objective-C is represented by nil, not null, NULL or NO, although they are all zero.