开发者社区> 问答> 正文

objective-c 单例继承问题

今天在修改数据库,发现每个类都有自己的单例实现函数,然后很多冗余的逻辑,于是就想父类写一个单例函数,然后子类继承就可以生成各自的单例了.
结果发现俺错了...

+ (id)sharedInstance{
    static BaseDAO *kInstance = nil;
    NSLog(@"kInstance=%@", kInstance);
    @synchronized(self){
        if(kInstance == nil){
            kInstance = [[self alloc] init];
        }else{
        }
    }
    return kInstance;
}

结果是所有的子类得到的都是同一个单例,然后就unrecognized selector sent to instance
我看了下java是有这种功能的,因为可以把属性设置为static, oc刚试了不行.
不知道有木有方法实现各子类不同单例.

展开
收起
a123456678 2016-07-19 17:02:38 2167 0
2 条回答
写回答
取消 提交回答
  • 宇宙虽有其起源,却没有终结。无限。 星球虽也有起源,却因其自身之力走向毁灭。有限。

    因为这个static对象都是同一个对象。
    然后如果你一定要实现的你的想法的话,可以将这个static类型改成NSMutableDictionary,在sync里面,以[self class]为key,去取存对应的value就行。

    2019-07-17 19:58:34
    赞同 展开评论 打赏
  • 先说你错在哪:
    虽然方法中self是不同的类,但是kInstance只有一个。
    你只用[BaseDAO sharedInstance];一直都不会出问题
    一旦[XXX sharedInstance]; kInstance已存在,不会再重新生成,返回的就是BaseDAO的单例。你对着BaseDAO的对象发XXX的消息当然会unrec sel。
    总之,kInstace存的一直都是第一次调用sharedInstance时,接收消息的类的单例

    你耳朵里有没有偶尔回旋起这样一句话:
    
    多用组合,少用继承
    你如果觉得用组合有绕路的感觉,我来炫下技:
    
    NSObject+OTSharedInstance.h:
    
    @interface NSObject (OTSharedInstance)
    
    + (id)sharedInstance;
    
    @end
    NSObject+OTSharedInstance.m:
    
    #import <objc/runtime.h>
    
    @implementation NSObject (OTSharedInstance)
    
    + (id)sharedInstance
    {
        Class selfClass = [self class];
        id instance = objc_getAssociatedObject(selfClass, @"kOTSharedInstance");
        if (!instance)
        {
            instance = [[selfClass alloc] init];
            objc_setAssociatedObject(selfClass, @"kOTSharedInstance", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return instance;
    }
    
    @end
    内存不够用的话可能需要释放单例,补个释放的方法:
    
    + (void)freeSharedInstance
    {
        Class selfClass = [self class];
        objc_setAssociatedObject(selfClass, SHARED_INSTANCE_KEY, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    测试代码:
    
    #import "NSObject+OTSharedInstance.h"
    id a;
    id b;
    for (int i = 0; i<10; i++)
    {
        a = [UIWindow sharedInstance];
        NSLog(@"instance a : %@",a);
        b = [UIView sharedInstance];
        NSLog(@"instance b : %@",b);
    }
    如果你觉得用了上述方法,所有类都能产生单例太脏,可以新建个Protocol,单在Protocol中声明sharedInstace。需要单例的类自己多重继承一下

    好用的话把答案勾给我

    2019-07-17 19:58:34
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
相关产品:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载