【问题标题】:iOS - Problems with implementing a Delegate Reference using a singletoniOS - 使用单例实现委托引用的问题
【发布时间】:2016-12-19 16:05:07
【问题描述】:

我对 obj-c 很陌生,目前正在修改一些现有代码,其中使用了很多导致随机崩溃的单例。我设法用适当的协议替换了其中的大多数,但仍然难以在 ONE 代表上设置参考。我在这里读过一些关于单例和协议的帖子,也提到了apple docs,但我读的越多,我就越困惑。我假设有一个我不知道的副作用 - 有人可以帮助理解。

我需要设置委托引用的是 PlayerInterface 实例的 ID(指针地址)。

这是我到目前为止所做的:

// define delegate in DocumentsViewController.h
@property (weak, nonatomic) id <documentsProtocol> delegate;

// in DocumentsViewController.m
// set delegate reference using singleton
self.delegate = [PlayerInterface sharedInstance]; // here it crashes!

这是我当前面临的问题,当我通过单例设置委托引用时,它会在线程上崩溃。 ARC 功能已开启!

crash-log

对于我正在使用的单身人士:

// in PlayerInterface.m (NSObject)
+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

/// 1.编辑 ///

有人问我关于单例的初始化 - 在我的 MainViewController.m 中,第一次实例化 PlayerInterface 对象:

- (void)viewDidLoad {
    self.player = [PlayerInterface sharedInstance];
}

我也试图避免 dispatch_once:

- (void)viewDidLoad {
    PlayerInterface *play = [[PlayerInterface alloc] init];
    self.player = play;
}

但没什么区别......也会崩溃!谁能帮忙?

/// 2.编辑 ///

我尝试了一个奇怪的解决方法:当我第一次实例化 PlayerInterface 时,我将 ID 设为全局变量(我知道这与面向对象编程的想法背道而驰)。

extern id play;

当涉及到委托时,我现在可以使用以下方法轻松设置引用:

self.delegate = play;

它就像一个魅力,只是很好的旧 C 风格:)

我认为单例的问题是基于我有三个相互通信的对象这一事实。我会将通信重新路由到“星型”,看看这是否有帮助。

【问题讨论】:

  • 1) 崩溃的错误是什么? 2) 代表和单例之间没有任何关系。它们是两个完全独立且独立的概念。 3) 你为什么使用@synthesize?不要遵循任何使用 @synthesize 的过时教程(在大多数情况下)。
  • +1 表示不使用合成。您提供的代码没有崩溃。 PlayerInterface 对象的初始化可能有问题。
  • +1 用于崩溃日志。如果不了解更多关于崩溃本身的信息,我们可以提供的建议很少。正如@CharlesThierry 上面所说,您在上面发布的代码实际上并没有显示任何潜在的崩溃,所以它看起来在其他地方。但作为说明;单例的使用应该是有限的,很多时候它们引起的问题多于它们的价值,所以要小心。
  • 请同时设置异常断点,并分享崩溃源。
  • 问题出在dispatch_once 调用内部。使用单身人士的 init 方法更新您的问题。确保init 方法不会直接或间接导致对sharedInstance 方法的任何访问。

标签: ios objective-c reference delegates singleton


【解决方案1】:

委托只是一个对象,可以像任何其他对象一样查询 ID 和其他属性。将“tellMeYourID”方法添加到您的“documentsProtocol”中,您就可以开展业务了。

【讨论】:

  • 我认为这是一个“鸡/蛋”问题...如何在不知道实例 ID 的情况下设置委托引用!?
  • “实例 ID”是什么意思?你似乎对它赋予了不同的含义。
【解决方案2】:

我有三个通过协议相互通信的对象。即使我注意不要最终进入委托循环,这似乎也是导致问题的原因。将通信重新路由到“星型”后,所有问题都消失了。现在每个对象只是与另一个对象通信。 MainViewController 是中间的主人,如果我需要传递信息,我添加了一个简短的方法,例如:

// passing through MainVC to keep star type communication
- (void)updateList:(NSArray)list { 
    [self.player setList:list];
}

我不知道这是否是完美的解决方案,但比使用保存播放器实例 ID 的全局变量要好得多:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多