【问题标题】:Objective-C setting/accessing iVars in singleton class' superclassObjective-C 在单例类的超类中设置/访问 iVar
【发布时间】:2014-09-02 17:09:37
【问题描述】:

我有两个类:一个超类 User 和它的子类 UserSession。用户极其简单,只是一些instanceVariables的容器:

//User.h    
@interface User : NSObject

- (id)initWithJSON:(NSDictionary *)JSONDictionary;

-(NSNumber *)getUserID;
-(NSString *)getUserName;
-(NSString *)getUserUsername;
-(NSString *)getUserEmail;
-(NSString *)getUserBio;
-(void)setUserID:(NSNumber *)userID;
-(void)setUserName:(NSString *)userName;
-(void)setUserUsername:(NSString *)userUsername;
-(void)setUserEmail:(NSString *)userEmail;
-(void)setUserBio:(NSString *)userBio;
@end

//User.m
@interface User()

@end

@implementation User

NSNumber *_userID;
NSString *_userName;
NSString *_userUsername;
NSString *_userEmail;
NSString *_userBio;

- (id)initWithJSON:(NSDictionary *)JSONDictionary
{
    self = [super init];
    if (!self)
        return nil;

    _userID = JSONDictionary[@"userID"];
    _userName = JSONDictionary[@"userName"];
    _userUsername = JSONDictionary[@"userUsername"];
    _userEmail = JSONDictionary[@"userEmail"];
    _userBio = JSONDictionary[@"userBio"];

    return self;
}

为 iVar 加上相关的 setter 和 getter。

UserSession 是一个单例类,它是 User 的子类:

//UserSession.m
@interface UserSession ()

@end

@implementation UserSession

static UserSession *_session = nil;


-(void)updateUserForUserSessionWithParams:(NSDictionary *)params
{
    [self setUserID:params[@"userId"]];
    [self setUserName:params[@"userName"]];
    [self setUserUsername:params[@"userUsername"]];
    [self setUserEmail:params[@"userEmail"]];
    [self setUserBio:params[@"userBio"]];
}

+ (instancetype)sharedSession
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // Create a session
        _session = [[UserSession alloc] init];
    });
    return _session;
}

问题出在:当我拨打类似

的电话时
[[UserSession sharedSession]
 updateUserForUserSessionWithParams:@{@"userId":@1],
                      @"userName":@"Steve Smith",
                      @"userUsername":responseObject[@"ssmith"],
                      @"userEmail":responseObject[@"ssmith@test.com"],
                      @"userBio":responseObject[@"I'm steve smith"]}];

然后在其他地方:

NSString* stringName = [[UserSession sharedSession] getUserName];
NSString* stringUsername = [[UserSession sharedSession] getUserUsername];
NSString* stringBio = [[UserSession sharedSession] getUserBio];

这些吸气剂返回零!

抱歉所有代码,但我认为我做错了什么。任何帮助都会很棒。

提前致谢!

【问题讨论】:

  • 我想我们需要看一个 setter 和 getter 的例子,但是你必须想知道为什么你要自己编写这些,而你可以简单地使用 Objective-C 属性? @property NSNumber *userID; 可以解决问题并为您节省大量代码。此外,我们还需要查看-[UserSession init] 方法。
  • 对 ObjectiveC 来说还是新手,所以我只是为了自己的理智而自己编写它们。我认为这并不重要。我没有 -[UserSession init] 虽然。我会在里面放什么?

标签: objective-c singleton subclass superclass


【解决方案1】:

虽然我没有 -[UserSession init]。我会在里面放什么?

好吧,对于初学者来说,子类应该始终将其称为超类的初始化程序,因此您应该调用-initWithJSON: 或其他一些User 初始化程序。在这种情况下,这并不能完全解决您的问题,但是 Objective-C 严重依赖约定来使事情正常进行,除非您真正了解自己在做什么,否则最好遵守这些约定。

我认为您的代码的主要问题在这里:

@implementation User

NSNumber *_userID;
NSString *_userName;
NSString *_userUsername;
NSString *_userEmail;
NSString *_userBio;

这些不是您要声明的实例变量——它们是文件范围的全局变量。您可以将实例变量声明为 @implementation 块的一部分,但您仍然需要像 @interface 块一样使用大括号:

@implementation User
{
    NSNumber *_userID;
    NSString *_userName;
    NSString *_userUsername;
    NSString *_userEmail;
    NSString *_userBio;
}
//...

无论如何,我建议使用这些属性。访问器方法很容易出错,如果您刚刚开始,发现这些类型的问题(如本例所示)通常并不容易。即使您有很多经验,也可能不容易,但这很难知道;经验丰富的人通常会使用属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 2011-01-10
    • 2016-06-17
    相关资源
    最近更新 更多