【问题标题】:iOS - singleton is not working as supposed in delegateiOS - 单例在委托中没有按预期工作
【发布时间】:2016-12-17 00:43:43
【问题描述】:

目前我正在开发一个应用程序,它使用四种协议在类之间进行通信。三个工作正常,但一个仍然不工作。我已将其设置为与其他人相同,但代表总是丢失其 ID。我对 Objective-C 很陌生,所以我无法深入了解它。这是我所做的:

我有一个带有委托的 MainViewController.h

@property (weak, nonatomic) id <PlayerProtocol> player;

还有一个 MainViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    [[Interface sharedInstance] Init];
    NSLog(@"Player ID: %@", _player);
    NSLog(@"viewDidLoad: %@", self);
}

- (void)sedPlayer:(id) pointer{ //sed is no typo!
    _player = pointer;
    NSLog(@"sedPlayer ID: %@", _player);
    NSLog(@"sedPlayer: %@", self);
}

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

在 Interface.m (NSObject) 中

- (void)Init {
    [[MainViewController sharedInstance] sedPlayer:self];
}

当然还有一个protocol.h,但这并不重要,因为委托会麻烦!当我运行代码时,我在控制台上得到以下输出:

sedPlayer ID: <Interface: 0x1700ab2e0>
sedPlayer: <MainViewController: 0x100406e30>
Player ID: (null)
viewDidLoad: <MainViewController: 0x100409550>

所以很明显单例不工作,因为 MainViewcontroller 的实例是不同的。对于单例,我使用 dispatch_once 标准方法,就像使用其他可以正常工作的协议一样。 ARC 已打开。有谁知道这里出了什么问题以及为什么单例不起作用?

【问题讨论】:

  • 首先你应该使用assign替换strong,当你使用delegate:@property (strong, nonatomic) id &lt;PlayerProtocol&gt; player,其次,请在你的问题中发布你的整个代码,我们可以找到在哪里问题。
  • ^ 不,使用weak 代替assignassign 将要求您在该对象被解除分配时 nil 对该对象的引用,否则当您向(现在已解除分配的)对象发送消息时会崩溃。
  • @Hecot 你确定[MainViewController sharedInstance]viewDidLoad 的调用来源相同吗?
  • @aircraft:我之前用过weak,但是assign也没什么区别。
  • 使用单例表明您的应用程序架构存在缺陷,使用视图控制器单例对我来说是完全错误的。

标签: ios objective-c delegates singleton


【解决方案1】:

这就是我认为您最终得到MainViewController 的两个实例的方式。我假设第一个是在导航到与MainViewController 关联的屏幕时创建的。第二个是在您在Interface.m 中调用[MainViewController sharedInstance] 时创建的。

由于 ViewController 视图是延迟加载的(“视图控制器延迟加载其视图。第一次访问视图属性会加载或创建视图控制器的视图。”来自 ViewManagement 下的 Apple docs),您会看到 @987654327 @ 仅记录一次,当第一个 MainViewController 被导航到并加载视图时。

这是我的建议:

既然你在- (void)viewDidLoad中做了Interface初始化,那么你不妨设置self.player = [Interface sharedInstance]

代码看起来像这样:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.player = [Interface sharedInstance];
    NSLog(@"Player ID: %@", _player);
    NSLog(@"viewDidLoad: %@", self);
}

您还应该删除 MainViewController 中的 - (void)sedPlayer:(id) pointer+ (instancetype)sharedInstance。拥有一个 ViewController 单例绝不是一个好主意,因为您最终可能会弄乱导航或拥有多个状态。

有关避免单例的更深入的文章,您可以查看objc.io Avoiding Singleton Abuse

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-04-21
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多