I am following a tutorial from Ray Wenderlich site and i am trying to understand this code where it has nsarray readonly and nsmutableble array with the same name but writable. Also what is the reason to use _(underscore)property vs setting a property and using self.x Here is the code:
this is from the site
MatchmakingServer.h
@interface MatchmakingServer : NSObject <GKSessionDelegate>
@property (nonatomic, assign) int maxClients;
@property (nonatomic, strong, readonly) NSArray *connectedClients;
@property (nonatomic, strong, readonly) GKSession *session;
- (void)startAcceptingConnectionsForSessionID:(NSString *)sessionID;
@end
MatchmakingServer.m
#import "MatchmakingServer.h"
@implementation MatchmakingServer
{
NSMutableArray *_connectedClients;
}
@synthesize maxClients = _maxClients;
@synthesize session = _session;
- (void)startAcceptingConnectionsForSessionID:(NSString *)sessionID
{
_connectedClients = [NSMutableArray arrayWithCapacity:self.maxClients];
_session = [[GKSession alloc] initWithSessionID:sessionID displayName:nil sessionMode:GKSessionModeServer];
_session.delegate = self;
_session.available = YES;
}
I am doing something like this instead
matchmakingserver.h
@interface zvMatchMakingServer : NSObject <GKSessionDelegate>
@property (nonatomic, assign) int maxClients;
@property (nonatomic, strong, readonly) NSArray *connectedClients;
@property (nonatomic, strong, readonly) GKSession *session;
- (void)startAcceptingConnectionsForSessionID:(NSString *)sessionID;
@end
matchmakingserver.m
@interface zvMatchMakingServer()
@property (nonatomic,strong) NSMutableArray *connectedClients;
@property (nonatomic, strong) GKSession *session;
@end
@implementation zvMatchMakingServer
-(NSArray *)connectedClients
{
return self.connectedClients;
}
-(void)startAcceptingConnectionsForSessionID:(NSString *)sessionID
{
self.connectedClients = [[NSMutableArray alloc]initWithCapacity:self.maxClients];
self.session = [[GKSession alloc]initWithSessionID:sessionID displayName:nil sessionMode:GKSessionModeServer];
}
Is what i am doing basically the same thing or it won’t work. Thank you!
I’ll try to explain what happens in Ray’s code:
He declares a property:
(I assume this was pre iOS 6, because in iOS 6 Apple changed the way properties generate iVars.)
This property causes the compiler to automatically generate an iVar
NSArray *connectedClients. This iVar is not used in the code. Instead he’s declaring a new (private) iVar named_connectedClientsof typeNSMutableArray. Note that he doesn’t synthesize the accessors for the property. He writes the accessor himself and instead of returning the iVar generated by the property (connectedClients), he’s returning his ‘own’ iVar (_connectedClients):Since
NSMutableArrayis a subclass ofNSArraythere’s no problem doing that.What you’re doing is trying to redeclare the property
@property (nonatomic,strong) NSMutableArray *connectedClients;as private property and that’s not allowed. Carefully compare your code to Ray’s, then you’ll see the difference.As for the underscore:
That’s only a convention many people use to name their iVars. It has no semantical meaning.
In fact Apple changed the names of ‘auto-generated’ iVars to also use the underscore.
Pre iOS 6 a property
generated an iVar named
name. In iOS 6 that same property generates an iVar named_name. Also in iOS 6 you don’t need to add the@synthesizeline anymore.Prefixing names of iVars with an underscore was convenient because if you wanted to override an automatically generated accessor the autocompletion suggested this:
if your iVar was also named
namethe parameternamewould hide the iVar in the accessor implementation, so you had to change the name of the parameter. If you renamed your iVar by using@synthesize name = _namethe parameternamedid no longer hide it and you could use the autocompletion generated code for the accessor.