Forward Declaration Stalls App

时间:2014-07-09 19:37:13

标签: ios objective-c xcode

所以我遇到了循环依赖的问题,所以我试图实现前向声明。我有三个类(logger,api,helpers),所有这些都是单例对象。我有一个控制器类(globalclass),它具有链接到三个类的属性。

这是我的代码:

INCLUDES.H:

#import "globalclass.h"
#import "logger.h"
#import "api.h"
#import "helpers.h"

globalclass.h:

@class logger
@class api
@class helpers

@interface globalclass : NSObject

+ (id) sharedGlobal;

- (id) init;

...

@property (nonatomic, strong) logger *log;
@property (nonatomic, strong) api *remote;
@property (nonatmoic, strong) helpers *utils;

...

logger / api / helpers.h templates:

@class globalclass

@interface logger : NSObject

+ (id) sharedLogger;

- (id) init;

...

@property (nonatomic, strong) globalclass *gc;

...

globalclass.m:

#import "includes.h"

@implementation globalclass

/*
 * Singleton Class
 */
+ (id) sharedGlobal
{
    static globalclass *sharedGlobalClass = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedGlobalClass = [[self alloc] init];
    });
    return sharedGlobalClass;
}

/*
 * Init
 */
- (id) init
{
    self = [super init];
    if (!self) return nil;

    // Logging
    self.logger = [logger sharedLogger];

    ...

    return self;
}

logger / api / helpers.m模板:

#import "includes.h"

@implementation logger

/*
 * Singleton Class
 */
+ (id) sharedLogger
{
    static logger *sharedLog = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedLog = [[self alloc] init];
    });
    return sharedLog;
}

/*
 * Init
 */
- (id) init
{
    self = [super init];
    if (!self) return nil;

    // Global Class
    self.gc = [GlobalClass sharedGlobal];

    ...

    return self;
}

然后,在我的AppDelegate中,我有一个属性到全局类,我正在这样做:

  
    

self.gc = [GlobalClass sharedGlobal];

  

但是,似乎每次启动我的应用程序时,它都会停止并自动终止,因为启动时间太长。

我是否错误地考虑了前导全局?

该应用程序构建良好。

任何帮助都将不胜感激。

感谢。

1 个答案:

答案 0 :(得分:3)

你有一个死锁,因为sharedGlobal中的dispatch_once块是(通过全局类init)调用sharedLogger,它本身正在调用sharedGlobal(通过记录器类init)。

由于一切都是单身,因此您可以采取一些方法来避免此问题。这是两个:

一个。使用self.log替换全局类中的所有[logger sharedLogger]用法,并使用self.gc替换记录器类中的所有[globalclass sharedGlobal]用法。你可以完全摆脱这些属性。 dispatch_once在第一次调用后非常快,因此性能不是将单例作为属性存储的原因(尽管您可以想象有其他原因)

B中。保留loggc属性,但使用自定义getter将它们设为只读属性:

@property (nonatomic, readonly) globalclass *gc;
// implementation:
- (globalclass *)gc
{
    return [globalclass sharedGlobal];
}

@property (nonatomic, readonly) logger *log;
// implementation:
- (logger *)log
{
    return [logger sharedLogger];
}

我个人会选择A.

这两种替代方法都消除了对init方法中单例访问器的任何引用,从而消除了死锁。