Ios 从超类方法内部获取类的特定实例

Ios 从超类方法内部获取类的特定实例,ios,objective-c,oop,singleton,Ios,Objective C,Oop,Singleton,我需要一个子类的单例,以便能够有一个抽象的会话管理器来完成大部分提升,但仍然可以子类化,以便多个会话可以共存,并且仍然可以在整个应用程序中使用。我正在构建一个我所有应用程序的演示,这就是为什么这个功能很重要的原因 一切都进行得很顺利,直到我意识到超级会话类中承载的api方法引用了singleton本身来设置会话,这是一个问题bc sharedInstance是这样引用的: + (NSURLSessionDataTask *)login:(NSString*)email andPassword:(

我需要一个子类的单例,以便能够有一个抽象的会话管理器来完成大部分提升,但仍然可以子类化,以便多个会话可以共存,并且仍然可以在整个应用程序中使用。我正在构建一个我所有应用程序的演示,这就是为什么这个功能很重要的原因

一切都进行得很顺利,直到我意识到超级会话类中承载的api方法引用了singleton本身来设置会话,这是一个问题bc sharedInstance是这样引用的:

+ (NSURLSessionDataTask *)login:(NSString*)email andPassword:(NSString*)password andCallback:(void (^)(NSArray *responseArray, NSError *error))block {


    if(![self hasInternet]){return nil;}
    NSLog(@"Session.login");
    [APIClient sharedClient].requestSerializer = [AFJSONRequestSerializer serializer];
    [[APIClient sharedClient].requestSerializer setValue:email forHTTPHeaderField:@"email"];
    [[APIClient sharedClient].requestSerializer setValue:password forHTTPHeaderField:@"password"];
    [[APIClient sharedClient].requestSerializer setValue:@"poop" forHTTPHeaderField:@"apikey"];


    return [[APIClient sharedClient] POST:@"/login" parameters:nil progress:nil success:^(NSURLSessionDataTask * __unused task, id JSON) {
        NSLog(@"session.loginWithEmail.response:%@",JSON);


        if([JSON objectForKey:@"user"]){
            NSMutableDictionary *user=[[NSMutableDictionary alloc] initWithDictionary:[[JSON objectForKey:@"user"] copy]];
            [user setObject:password forKey:@"password"];
            [[Session sharedInstance] startSession:user];
            if([[Session sharedInstance] isSessionActive]){

                if([JSON objectForKey:@"req_onboarding"]){
                    NSLog(@"session.onboard!=nil");
                    [Session sharedInstance].requiredOnboarding=[JSON objectForKey:@"req_onboarding"];
                }

                if (block) {
                    NSLog(@"session.login.block.success");
                    block(nil, nil);
                }
            }else{
                NSLog(@"Failed to set session");
            }


        }

    } failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
        if (block) {

            NSLog(@"Session.login.Fail");
            block([NSArray array], error);
        }
    }];
}
当它只是一个会话单例时,我可以在类方法中这样做:
[Session sharedInstance]isSessionActive]

但现在,重要的是[共享立场]是积极的];
是对调用类方法的特定子类的引用。是否可以从该类方法中检索特定实例的引用,而不将其作为参数发送?

其目的似乎是为超级(可能是抽象)类的每个子类分发一个单例。
sharedInstance
代码不能做到这一点,因为这一行:

+ (instancetype)sharedInstance
{
    NSLog(@"[Master sharedInstance]");
    id sharedInstance = nil;

    @synchronized(self) {
        NSLog(@"MS | synchronized(self)");

        NSString *instanceClass = NSStringFromClass(self);

        // Looking for existing instance
        sharedInstance = [_sharedInstances objectForKey:instanceClass];

        // If there's no instance – create one and add it to the dictionary
        if (sharedInstance == nil) {
            NSLog(@"MS | sharedInstance == nil");
            sharedInstance = [[super allocWithZone:nil] init];
            [_sharedInstances setObject:sharedInstance forKey:instanceClass];
            NSLog(@"MS | SharedInstances:%@",_sharedInstances);
        }
    }

    return sharedInstance;
}
将仅创建超类的实例。我认为您需要子类的实例,以便能够访问重写的数据和行为

如果我正确理解您的目标,那么解决方法很简单:

sharedInstance = [[super allocWithZone:nil] init];

这样,当您向ClassA发送
sharedInstance
时,您将得到一个(单个)ClassA实例。当您将其发送到ClassB时,您将得到一个(单个)ClassB实例。根据我的建议,这些将实际上是子类A和B的实例,而不是它们都继承自的类的实例。如果每个调用方都重写了
isSessionActive
或任何其他超类方法,则调用方将根据其请求的单例类获得不同的、重写的实现。

这个
+登录:和密码:以及回调:
方法是您自己的代码吗?还是你不能搞乱的代码?如果它是您自己的,我建议将其从类方法更改为实例方法,此时您应该能够使用
[self isSessionActive]
,如果
+登录:和密码:以及回调:
是在
会话上定义的。问题似乎在于我是如何看待这个问题的,相反,我决定将会话管理器设置为单例,并使会话不是单例,而是会话管理器直接持有和管理的对象。:-)在最初撰写本文时,我试图决定是否批评您的决定,即使用多个“单例”,这有点自相矛盾。在我的应用程序中,我的模型类继承自一个类,该类知道如何进行远程读写网络操作。这将使用和丢弃计数不受控制的会话。如果会话是单例会话,但它具有可通过init(具有更多属性的authUser的子类)传入的authUser属性,则调用[Session sharedInstance].user时如何访问子类属性。[我知道的自定义SSAuthUser属性存在并已设置]在我的应用程序周围?如果在标题中公开声明了该用户属性,则该属性应该有效。我无法具体评论,因为我不确定您的代码状态,以及您是否采纳了我的建议(这仍然是针对您的问题的正确建议)。
sharedInstance = [[self allocWithZone:nil] init];  // notice "self"