Coding convention for space after pointer * [duplicate] - objective-c

This question already has an answer here:
Convention for pointer *
(1 answer)
Closed 9 years ago.
In Cocoa, what's the best convention on writing the * for pointer?
#property (nonatomic, retain) MyClass * instance;
or
#property (nonatomic, retain) MyClass *instance;
I noticed that the auto-generated code for Core Data, puts the *instance by relationship, but * instance by property:
#property (nonatomic, retain) NSDate * send;
#property (nonatomic, retain) NSString * text;
#property (nonatomic, retain) User *user;
#property (nonatomic, retain) User *userManager;

It's better to use
char *examplea;
For cases like such:
Say you'd like to include multiple pointer variables in one line like so, you'd need to do so like this:
char *examplea, *exampleb;

Almost all of the Objective-C code I've already read does it like this:
#property (nonatomic, retain) MyClass *instance
Personally, I also think it looks the cleanest/best that way

Related

Assigned to Readonly Property Objective-C

I am writing a unit test to test a method that updates a checklist. The checklist has these properties:
typedef NS_ENUM (NSUInteger, ChecklistStatus) { Pending, Completed };
#protocol IChecklistItem <NSObject>
#property (nonatomic, assign, readonly) NSInteger Id;
#property (nonatomic, copy, readonly) NSString *Description;
#property (nonatomic, assign, readonly)BOOL IsCompleted;
#property (nonatomic, assign, readwrite) ChecklistStatus Status;
#property (nonatomic, strong, readwrite) NSDate *CompletedDate;
#property (nonatomic, copy, readwrite) NSString *CompletedByUserId;
#property (nonatomic, assign, readonly) NSInteger RoleId;
#property (nonatomic, assign, readonly) NSInteger GroupId;
#property (nonatomic, strong, readonly) NSArray<IChecklistNote> *Notes;
- (void)sortNotes;
#end
However, in my unit test, as I am trying to validate,
checklistItem.Description = #"hello";, I get the error"Assignment to readonly property"
Why is this so?
heres the rest of my test method:
- (void)testUpdateChecklist {
NSString *testChecklistId = #"1";
NSString *testPatientDescription = #"Descriptive Description";
// What other properties do I need here?
XCTAssertNotNil(_service);
__block CCChecklistItem *checklistItem = nil;
SignalBlocker *blocker = [[SignalBlocker alloc] initWithExpectedSignalCount:1];
id delegate = OCMProtocolMock(#protocol(ChecklistServiceDelegate));
OCMExpect([delegate didCompleteUpdateChecklistItem:[OCMArg checkWithBlock:^BOOL(id obj) {
checklistItem = obj;
XCTAssertNotNil(checklistItem);
[blocker signal];
return true;
}]]);
[_service updateChecklistItem:checklistItem delegate:delegate];
[blocker waitWithTimeout:5.0f];
OCMVerifyAll(delegate);
NSString *originalDescription = checklistItem.Description;
checklistItem.Description = #"hello";
}
EDITED QUESTION:
So when I change the property from above to ReadWrite, I get this error in CChecklistItem
#interface CCChecklistItem ()
#property (nonatomic, assign, readwrite) NSInteger Id;
#property (nonatomic, copy, readwrite) NSString *Description;
#property (nonatomic, assign, readwrite) NSInteger RoleId;
#property (nonatomic, assign, readwrite) NSInteger GroupId;
#property (nonatomic, strong, readwrite) NSMutableArray<IChecklistNote> *Notes;
#end
`Illegal redeclaration of readwrite property in class extension 'CChecklistItem'
Your property is set to readonly as seen here:
#property (nonatomic, copy, readonly) NSString *Description;
Change it to:
#property (nonatomic, copy) NSString *Description;
or if you want to be consistent with the other properties (though overly explicit, IMO):
#property (nonatomic, copy, readwrite) NSString *Description;
Changing scope visibility only to satisfy tests is not encouraged. The easiest solution in your case would be to take advantage of wonderful KVO which Objective-C gives you.
Translated to your original question it would be something like:
[checklistItem setValue:#"hello" forKey:#"Description"]
No need to change access modifiers and your tests will be fine.
Your property is declared readonly in the protocol that the class CChecklistItem conforms. When that property is then synthersized it will create the backing variable and a getter method -(NSString *)description; but no setter method, since it is readonly. So redeclaring it as readwright in your anonymous category, that i'm guessing is declared in your test file to expose private methods to the test case, won't work since there still is no setter method for the property. Further more, even if you decide to try to make your own setter in the implementation of a category on your class you can't since there is no way to access the variable _description that is only exposed in the CChecklistItem.m file.
Depending on what you need to do with your test it might work to stub the getter - (NSString *)description; and return your #"hello" string when that method is called instead of trying to set the actual value to the backing variable.

NSDictionary: Comparing NSDictionaries

There are two of files. Lets call them fileOne and fileTwo
Each has several NSMutableDictionary properties with identical names. To list a few:
#property (retain, nonatomic) NSMutableDictionary * lunchStartTimeObject;
#property (retain, nonatomic) NSMutableDictionary * lunchLocationNameObject;
#property (retain, nonatomic) NSMutableDictionary * lunchLocationAddressObject;
#property (retain, nonatomic) NSMutableDictionary * activity1NameObject;
#property (retain, nonatomic) NSMutableDictionary * activity1StartTimeObject;
#property (retain, nonatomic) NSMutableDictionary * activity1LocationNameObject;
#property (retain, nonatomic) NSMutableDictionary * activity1CommentsFieldObject;
#property (retain, nonatomic) NSMutableDictionary * activity1LocationAddressObject;
#property (retain, nonatomic) NSMutableDictionary * activity2NameObject;
#property (retain, nonatomic) NSMutableDictionary * activity2StartTimeObject;
#property (retain, nonatomic) NSMutableDictionary * activity2LocationNameObject;
#property (retain, nonatomic) NSMutableDictionary * activity2CommentsFieldObject;
#property (retain, nonatomic) NSMutableDictionary * activity2LocationAddressObject;
I would like to compare the dictionaries with the same name in the two files by calling the method below (or something similar):
-(NSMutableDictionary *)cellColorForChanges:(NSMutableDictionary *)newdictionary :(NSMutableDictionary *)oldDictionary;
{
if(![newdictionary isEqualToDictionary:oldDictionary])
{
[newdictionary setValue:#"UIColor yellowColor" forKey:#"cellColor"];
}
return newdictionary;
}
I'm trying avoid writing code for each NSMutableDictionary manually. Is there a way to avoid the following:
if(![fileOne.lunchStartTimeObject isEqualToDictionary:fileTwo.lunchStartTimeObject])
{
fileOne.lunchStartTimeObject setValue:#"UIColor yellowColor" forKey:#"cellColor"];
}
I'm having trouble figuring out the most efficient way to accomplish the above. Is it somehow possible to send each dictionary to a method and get back the dictionary (updated with another key, if it's not equal)? Or what I'm trying to avoid is unavoidable?
You are running into this problem because you are not abstracting your objects sufficiently. It seems to me that your property list above is ridiculously redundant. Even the simple code code you provided is hardly readable.
Try to think of your problem in a more conceptional way. Try to think of objects that could encapsulate the functionality you are looking for.
Looking at your properties you probably want a class like this
#interface Activity : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSDate *startTime;
#property (nonatomic, strong) Location *location;
-(BOOL)isEqualToActivity:(Activity*)activity;
#end
Maybe you need a location class that stores more information about a location; perhaps you could use even more fields like firstName, lastName; maybe you need a type (enum or string) property that tells what kind of activity it is, etc. -- you get the idea.
As indicated, you could write your own comparison method where you could tweak for allowing more or less strict capital or small letters, number formats etc.

Static Instance releasing properties prematurely with ARC

I have a static instance variable that is being used throughout my application. It has properties. These properties are used through my application and seem to work pretty well. However, sometimes the properties are released prematurely. What is odd is that the object that is pulling these properties keeps some and releases others. What would be a good way to insure that the properties of my object are not released prematurely.
Edit: It turns out that the issue was not premature releasing at all. It was a conversion issue. Thanks all for help.
#interface Game : NSObject
#property (nonatomic, strong) PFObject *gameObject;
//#property (nonatomic, strong) Concept *concept; // Will need to add Concept Object to GameObject once it's wrapper is done
#property (nonatomic, strong) User *initialPlayer;
#property (nonatomic, strong) User *invitedPlayer;
#property (nonatomic, strong) User *lastPlayedPlayer;
#property (nonatomic, strong) NSDate *lastPlayedDate;
#property (nonatomic, strong) NSDate *timeOutDate;
#property (nonatomic, assign) int timerTicks;
#property (nonatomic, assign) int currentRoundNumber;
#property (nonatomic, strong) User *winnerPlayer;
#property (nonatomic, assign) int initialPlayerPoints;
#property (nonatomic, assign) int invitedPlayerPoints;
#property (nonatomic, assign) int currentPlayerPoints;
#property (nonatomic, assign) GameStatus status;
#property (nonatomic, assign) int initialPlayerTimeouts;
#property (nonatomic, assign) int invitedPlayerTimeouts;
#property (nonatomic, assign) BOOL isInitialPlayer;
#property (nonatomic, strong) NSMutableDictionary *rounds;
#property (nonatomic, strong, readonly) Round *currentRound;
+(void)getActiveUserGameObjects:(PFUser *)user target:(id)target selector:(SEL)selector;
+(void)getYourTurnGameObjects:(PFUser *)user target:(id)target selector:(SEL)selector;
+(void)getTheirTurnGameObjects:(PFUser *)user target:(id)target selector:(SEL)selector;
+(void)getGameObjects:(PFUser *)user yourTurn:(id)yourTurn target:(id)target selector:(SEL)selector;
+(Game*)currentGame;
+(void)setCurrentGame:(Game*)currentGame;
..
//.m #implementation
..
static Game *sharedInstance = nil;
..
+(Game*)currentGame
{
return sharedInstance;
}
+(void)setCurrentGame:(Game*)currentGame
{
sharedInstance = currentGame;
}
...
#pragma mark - Player Setters and Getters
-(void)setInvitedPlayer:(User *)invitedPlayer
{
if (nil != invitedPlayer.userObject)
{
[self.gameObject setObject:invitedPlayer.userObject forKey:GAME_INVITED_PLAYER];
}
}
-(User*)invitedPlayer
{
NSObject *value = [self.gameObject objectForKey:GAME_INVITED_PLAYER];
if ([value isKindOfClass:[PFUser class]])
{
return [User userFromPFUser:(PFUser*)value];
}
return nil;
}
What would be a good way to insure that the properties of my object are not released prematurely.
Holding onto them by maintaining a strong reference. It is extremely unlikely that ARC is randomly releasing your data. Much more likely is that you are letting go of it when you don't mean to.
The first place I'd look is at your use of setCurrentGame:, making sure that you're not accidentally working on different Game objects at the same time in different parts of the program. First, make sure t
Your +get... methods are awkwardly named (a get prefix means a very specific thing in ObjC, and it's not what you're doing here). Havings class methods that take targets and actions like this seems a likely place to have trouble. It makes me wonder what's going on inside there.
Your conversion between two kinds of User objects is a little suspicious, and I'd make sure you're not accidentally dropping User or PFUser objects when you don't mean to.
Generally speaking, though, this question is over-vague. Are you winding up with dangling strong pointers? Are your strong pointers seeming to become nil? Is your game object itself becoming nil? How do you know when things are being "released?" Or do you mean that they're deallocating? Have you put a breakpoint in dealloc to see who had the last reference to the object?
Make sure your properties are (retain) type (same as strong, I think), and keep an instance refereed to in the app delegate (so that ARC sees the reference as valid for the entire execution of your program).

Properties declared as instance variables too?

This code works:
#interface StringStuff : NSObject {
}
#property (nonatomic, retain) NSString *String1;
#property (nonatomic, retain) NSString *String2;
- (NSString *) doSomethingWithStrings;
#end
But I often see:
#interface StringStuff : NSObject {
NSString *String1;
NSSTring *String2;
}
#property (nonatomic, retain) NSString *String1;
#property (nonatomic, retain) NSString *String2;
- (NSString *) doSomethingWithStrings;
#end
Is there a reason that properties are often declared as an instance variable as well? Is it just considered good form?
Legacy; it used to be (and still is on 32 bit Mac OS X targeted code) that the ivar declarations were required. That is no longer true on iOS, the simulator and 64 bit OS X.
Note that it is common to #synthesize iVar = iVar_; to prevent accidental direct access where self.iVar is really required.

To Many Relationship in Core Data

This is my GeneratedCode for Core data, automatically generated by xCode Editor.
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Building, Category, City, District, Image, LatitudeLongitude, OpeningHour, Promotion, Rating, Review, URL;
#interface Business : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString * Website;
#property (nonatomic, retain) NSString * Email;
#property (nonatomic, retain) NSString * Street;
#property (nonatomic, retain) NSString * InBuildingAddress;
#property (nonatomic, retain) NSString * Phone;
#property (nonatomic, retain) NSString * Title;
#property (nonatomic, retain) NSString * Zip;
#property (nonatomic, retain) NSNumber * Price;
#property (nonatomic, retain) NSSet* Promotions;
#property (nonatomic, retain) Building * Building;
#property (nonatomic, retain) NSSet* Categories;
#property (nonatomic, retain) LatitudeLongitude * LatitudeLongitude;
#property (nonatomic, retain) NSSet* Images;
#property (nonatomic, retain) OpeningHour * OpeningHour;
#property (nonatomic, retain) NSSet* Reviews;
#property (nonatomic, retain) NSSet* URLs;
#property (nonatomic, retain) Rating * Rating;
#property (nonatomic, retain) NSSet* Districts;
#property (nonatomic, retain) City * City;
//I added these 3 lines, why not part of automatically generated Code?
- (void)addDistrictsObject:(District *)value;
- (void)addCategoriesObject:(Category *)value;
- (void)addReviewsObject:(Review *)value;
#end
Say I want to "clear" all Reviews and image.
Will doing self.Reviews=nil do the trick?
I know that doing self.LatitudeLongitude=nil will delete the relationship between self and it's LatitutudeLongitude.
EDIT - Not sure if you mean "clear" as in delete. My answer below is assuming that you want the objects gone from the context; not just severing the relationship between the NSManagedObjects
I don't believe
self.Reviews = nil;
will actually delete your Review objects for the Managed Object Context. That would send the release message to each one, but to delete them from the context you have to call
[aContext deleteObject:reviewObj];
on each one in the set. If you were to delete one of your Business objects (using "deleteObject" as shown above) and you had your relationship delete rules set to "Cascade", then I believe that would cause all of the Review, City, etc... objects owned by that Business object to be deleted automatically, but that is the only other way that I know of that will cause NSManagedObjects to be deleted.