Override `hash` as NSNumber - ios

Is it possible to override hash within a class as an NSNumber instead of a NSUInteger? Such as this:
#interface MyObject : NSObject
#property (nonatomic, readonly) NSNumber *hash;
#end
#implementation MyObject
#synthesize hash = _hash;
#end

No, hash is declared by the NSObject protocol and is expected to return an NSUInteger.
You could do something like this, though:
#interface MyObject : NSObject
#private
NSNumber *_hash;
#end
#implementation MyObject
- (NSUInteger)hash
{
return [_hash unsignedIntegerValue];
}
#end

Related

Objective-C accessing singleton's property causing EXC_BAD_ACCESS crash

I've got a singleton class KTTTeacherService that has a single property currentTeacher. This property is nil initially and is updated with the static method KTTTeacherService#updateCurrentTeacher. After currentTeacher is updated, when I try to access it, my app crashes with a EXC_BAD_ACCESS error.
KTTTeacherService.h
#import <Foundation/Foundation.h>
#import "KTTeacher.h"
#interface KTTTeacherService : NSObject
#property (nonatomic, assign) KTTeacher* currentTeacher;
+ (KTTTeacherService*)shared;
+ (KTTeacher*)currentTeacher;
+ (NSString*)apiKey;
+ (void)updateCurrentTeacher:(KTTeacher*) teacher;
- (KTTeacher*)retrieveCurrentTeacher;
#end
KTTTeacherService.m
#import "KTTTeacherService.h"
#import "KTTeacher.h"
static KTTTeacherService* _singleton = nil;
#implementation KTTTeacherService;
+ (KTTTeacherService*) shared {
if(_singleton == nil) {
_singleton = [[KTTTeacherService alloc] init];
}
return _singleton;
}
+ (KTTeacher*) currentTeacher {
KTTTeacherService* shared = [KTTTeacherService shared];
if(shared == nil) {
return nil;
}
return [shared retrieveCurrentTeacher];
}
+ (NSString*) apiKey {
KTTeacher* teacher = [KTTTeacherService currentTeacher];
return teacher == nil ? nil : teacher.apiKey;
}
+ (void) updateCurrentTeacher:(KTTeacher*) teacher {
[KTTTeacherService shared].currentTeacher = teacher;
}
- (KTTeacher*) retrieveCurrentTeacher {
return _currentTeacher;
}
#end
KTTeacher.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class KTClass, KTGroup, KTTeacherNote;
#interface KTTeacher : NSManagedObject
#property (nonatomic, strong) NSString * apiKey;
#property (nonatomic, strong) NSNumber * serverIdentifier;
#property (nonatomic, strong) NSString * firstName;
#property (nonatomic, strong) NSString * lastName;
#property (nonatomic, strong) NSString * photoPathOnServer;
#property (nonatomic, strong) NSString * username;
#property (nonatomic, strong) NSString * hashedPassword;
#property (nonatomic, strong) NSString * salt;
#property (nonatomic, strong) NSSet *classes;
#property (nonatomic, strong) NSSet *groups;
#property (nonatomic, strong) NSSet *notes;
#end
#interface KTTeacher (CoreDataGeneratedAccessors)
- (void)addClassesObject:(KTClass *)value;
- (void)removeClassesObject:(KTClass *)value;
- (void)addClasses:(NSSet *)values;
- (void)removeClasses:(NSSet *)values;
- (void)addNotesObject:(KTTeacherNote *)value;
- (void)removeNotesObject:(KTTeacherNote *)value;
- (void)addNotes:(NSSet *)values;
- (void)removeNotes:(NSSet *)values;
- (void)addGroupsObject:(KTGroup *)value;
- (void)removeGroupsObject:(KTGroup *)value;
- (void)addGroups:(NSSet *)values;
- (void)removeGroups:(NSSet *)values;
#end
KTTeacher.m
#import "KTTeacher.h"
#import "KTClass.h"
#import "KTTeacherNote.h"
#implementation KTTeacher
#dynamic apiKey;
#dynamic serverIdentifier;
#dynamic firstName;
#dynamic lastName;
#dynamic photoPathOnServer;
#dynamic username;
#dynamic hashedPassword;
#dynamic salt;
#dynamic classes;
#dynamic groups;
#dynamic notes;
#end
Where the crash happens:
KTTTeacherService* teacherService = [KTTTeacherService shared];
KTTeacher* currentTeacher = teacherService.currentTeacher;
Specifically here: teacherService.currentTeacher
Why is this happening? After doing some googling, I found some info about this error being caused by accessing references that have been garbage collected, but I don't understand why this variable would be garbage collected because the singleton keeps a reference.
Property written incorrectly. Use strong, weak, retain instead assign
property (nonatomic, assign) KTTeacher* currentTeacher;
I tried to reproduce the error and I could not. Create a project and put the classes KTTTeacherService, KTTeacher (empty class with the apiKey property) Everything works fine. Therefore you must have the error in the KTTeacher class.
In the viewDidLoad I have the following:
KTTTeacherService* teacherService = [KTTTeacherService shared];
// updateCurrentTeacher, for default is nil
KTTeacher *teacher = [[KTTeacher alloc] init];
[KTTTeacherService updateCurrentTeacher:teacher];
KTTeacher* currentTeacher = teacherService.currentTeacher
When you call currentTeacher method then, _currentTeacher (property) has a value now.

readwrite and readonly mutually exclusive

How can I go about achieving this
Property has to be readwrite for inner implementation in class
Property has to be readonly for external interaction to instances of the class
In Objective-C:
MyObject.h
#interface MyObject : NSObject
#property (nonatomic, readonly, strong) NSString *myProperty;
#end
MyObject.m
// Class extension
#interface MyObject ()
// Redeclare property read-write
#property (nonatomic, readwrite, strong) NSString *myProperty;
#end
#implementation MyObject
...
In Swift:
class MyObject {
private(set) var myProperty: String
...
Try like the following example
In your .h:
#property(nonatomic, retain, readonly) NSDate* theDate;
In your .m:
#interface TheClassName()
#property(nonatomic, retain, readwrite) NSDate* theDate;
#end

pass delegating object type as protocol method argument

I want to pass my delegating object as an argument with a declared type so I don't have to cast (if I pass (id)sender instead):
#protocol myObjectDelegate <NSObject>
- (void)myObjectAsArgument:(myObject *)object;
#end
#interface myObject : NSObject
// stuff...
#property (nonatomic, strong) id <myObjectDelegate> delegate;
#end
What would be the correct way of doing this? Like I said, I know I could do this:
- (void)myObjectAsArgument:(id)object;
And that would let me pass self in as argument, but I don't like using the cast syntax.
Thanks.
NOTE:
Apple does that too:
#protocol UITableViewDataSource <NSObject>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
#end
#interface UITableView : UIScrollView
#property (nonatomic, strong) id <UITableViewDataSource> dataSource;
#end
That's just one method from the UITableViewDataSource protocol and it's passing a UITableView type as argument. ;)
Since this is top Google search result, here's how to do it:
#class myObject; // just need this for compiling
#protocol myObjectDelegate <NSObject>
- (void)myObjectAsArgument:(myObject *)object;
#end
#interface myObject : NSObject
// stuff...
#property (nonatomic, strong) id <myObjectDelegate> delegate;
#end
You should do it this way:
- (void)myObjectAsArgument:(id<myObjectDelegate>)object;
with myObjectDelegate being the name of your protocol ;)

override property from superclass in subclass

I want to override an NSString property declared in a superclass. When I try to do it using the default ivar, which uses the the same name as the property but with an underscore, it's not recognised as a variable name. It looks something like this...
The interface of the superclass(I don't implement the getter or setter in this class):
//Animal.h
#interface Animal : NSObject
#property (strong, nonatomic) NSString *species;
#end
The implementation in the subclass:
//Human.m
#implementation
- (NSString *)species
{
//This is what I want to work but it doesn't and I don't know why
if(!_species) _species = #"Homo sapiens";
return _species;
}
#end
Only the superclass has access to the ivar _species. Your subclass should look like this:
- (NSString *)species {
NSString *value = [super species];
if (!value) {
self.species = #"Homo sapiens";
}
return [super species];
}
That sets the value to a default if it isn't currently set at all. Another option would be:
- (NSString *)species {
NSString *result = [super species];
if (!result) {
result = #"Home sapiens";
}
return result;
}
This doesn't update the value if there is no value. It simply returns a default as needed.
to access the superclass variables, they must be marked as #protected, access to such variables will be only inside the class and its heirs
#interface ObjectA : NSObject
{
#protected NSObject *_myProperty;
}
#property (nonatomic, strong, readonly) NSObject *myProperty;
#end
#interface ObjectB : ObjectA
#end
#implementation ObjectA
#synthesize myProperty = _myProperty;
#end
#implementation ObjectB
- (id)init
{
self = [super init];
if (self){
_myProperty = [NSObject new];
}
return self;
}
#end

no known class method for selector confusion

I know this is a newbie question, but I am all confused. How should I call class method from another class, or shouldn't I?
Here is my ClassA and CoreDataHelper:
#import <Foundation/Foundation.h>
#interface ClassA : NSObject {
}
#property (nonatomic, retain) NSString * sessionId;
#property (nonatomic, retain) NSString * token;
#property (nonatomic, retain) NSString * userid;
+ (void) pullOfflineDataWithContext:(NSManagedObjectContext *)managedObjectContext ;
#end
#import "ClassA.h"
#import "CoreDataHelper.h"
#implementation ClassA
+ (void) pullOfflineDataWithContext:(NSManagedObjectContext *)managedObjectContext {
// get Contacts, Accounts, Meetings into Core Data
bool asd =[CoreDataHelper insertAllObjectsForEntity:#"Contact" andContext:managedObjectContext initCoreData:jsonDict];
}
#end
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface CoreDataHelper : NSObject
//For inserting objects
+(BOOL)insertAllObjectsForEntity:(NSString*)entityName andContext:(NSManagedObjectContext *)managedObjectContext;
#end
You are calling a class method from another in the right way except the method signature is not the same as it is declared;
bool asd =[CoreDataHelper insertAllObjectsForEntity:#"Contact"
andContext:managedObjectContext
initCoreData:jsonDict];
The declaration of +insertAllObjectsForEntity:andContext: does not have the last one in the calling code above
+(BOOL)insertAllObjectsForEntity:(NSString*)entityName
andContext:(NSManagedObjectContext *)managedObjectContext;
Like:
[ClassName method];
Instead of:
[instance method];
In your example would be then:
[ClassA pullOfflineDataWithContext];

Resources