Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 静态变量在多个目标之间的行为如何?_Ios_Objective C_Iphone_Xcode_Xctest - Fatal编程技术网

Ios 静态变量在多个目标之间的行为如何?

Ios 静态变量在多个目标之间的行为如何?,ios,objective-c,iphone,xcode,xctest,Ios,Objective C,Iphone,Xcode,Xctest,我对Objective-C.m文件中全局范围中定义的静态变量的行为有问题。具体地说,我看到同一个变量在同一代码中引用的对象的不同实例取决于从XCTest目标执行时的作用域 在.m文件中定义的全局静态变量在主目标和XCTest目标之间的行为如何?下面是我看到的问题的一个例子: 设置代码 Manager.m #import "Manager.h" // This is the variable of interest! static Manager *sharedManager = nil; @

我对Objective-C.m文件中全局范围中定义的
静态
变量的行为有问题。具体地说,我看到同一个变量在同一代码中引用的对象的不同实例取决于从XCTest目标执行时的作用域

在.m文件中定义的全局静态变量在主目标和XCTest目标之间的行为如何?下面是我看到的问题的一个例子:

设置代码 Manager.m

#import "Manager.h"

// This is the variable of interest!
static Manager *sharedManager = nil;

@implementation Manager

+ (instancetype)sharedManager
{
    return sharedManager;
}

+ (void)setManager:(Manager *)manager
{
    sharedManager = manager;
}

@end
下面是一个极其简单的
ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Manager *tempManager = [[Manager alloc] init];
    [Manager setManager:tempManager];
}
混乱的实质 我正在尝试编写利用
Manager
的xtest单元测试。问题是,根据代码的上下文,我在同一个代码执行流中看到了不同的
Manager
实例。这对我来说是全新而怪异的。例如,考虑本单元测试:

- (void)testManager {
    // 1
    ViewController *vc = [[ViewController alloc] init];

    // 2
    NSLog(@"manager %@", [Manager sharedManager]);

    Manager *tempManager = [[Manager alloc] init];
    [Manager setManager:tempManager];

    // 3
    NSLog(@"manager %@", [Manager sharedManager]);
    [vc viewDidLoad];

    // 4
    NSLog(@"manager %@", [Manager sharedManager]);
}
以下是一些观察到的行为:

  • 断点在第1行暂停。如果我
    po[Manager sharedManager]
    我将看到一个具有内存地址的n对象实例。我假设这是因为
    ViewController
    是项目情节提要的初始视图控制器,
    viewDidLoad()
    创建并设置第一个
    Manager
    共享实例
  • 这行将null打印到控制台,这很奇怪,因为1上的断点和po显示了控制台中的实际对象
  • 此行打印实际对象实例,但与第1行不同。有趣的是,如果我在这一行中断,
    [po Manager sharedManager]
    将打印一个不同于这一行的NSLog的对象实例,但与在断点1处打印的实例相同
  • viewDidLoad()
    运行一个新的
    管理器
    。用
    po
    在这一行中断会显示一个新实例,但
    NSLog
    会打印与3相同的实例
  • 要点通常
    NSLog
    'd对象的内存地址与调试器
    po
    'd对象不同。我不知道为什么。我猜这与XCTest如何在不同的“应用”实例中执行有关

    我观察到的行为是,在相同的代码流中,.m文件中的
    静态
    全局变量的访问取决于访问它的文件。为什么?


    我在GitHub上发布了一个功能齐全的项目,演示了这一点:

    当我尝试在一个新项目中手动重新创建问题时,我得到了:

  • 通过加载初始视图控制器创建的管理器。(顺便说一句,这是一种测试气味,因为测试应该完全控制其环境。对于单元测试,我使用了一种方法来防止这种情况发生。)
  • 相同的管理器被记录
  • tempmanager
  • viewDidLoad
    设置的管理器
  • 这是意料之中的。不同的结果表明,项目设置中存在一些奇怪的东西。然后我下载了你的项目并复制了你描述的内容。日志中会出现一条重要警告:

    objc[5304]:类管理器在/Users/jorei/Library/Developer/CoreSimulator/Devices/BEEDA9FD-5FDA-4347-8691-FD80B8C7A18D/data/Containers/Bundle/Application/020A6698-99B6-472A-8E77-330CBCB5AA1A/TestStatic.app/TestStatic和/Users/jorei/Library/Developer/Xcode/DerivedData/TestStatic clulxcackwiypobvsqvfatqiznvi/Build/Products/Debug iphonesimulator/TestStatic.app/PlugIns/TestStaticTests.xctest/TestStaticTests。将使用其中一个。哪一个是未定义的

    问题是:


    有两次出现Manager.m。每个都有自己的
    sharedManager
    静态变量副本。

    我对1感到惊讶。然而,为什么不实现通常的、线程安全的、经过良好测试的共享实例模式呢?好的一点,这是一个我必须在其中工作的约束的简化示例,这意味着我无法重构到适当的SingletonThreak@jon reid-这是一个关于目标成员身份的好发现,而且是有意的。基于此项目的第三方依赖关系是如何设置的,这是一个预先存在的条件,我需要弄清楚如何解决。我想这里的主要收获是,一个给定的实现文件不应该有多个目标的成员资格。我刚刚遇到了这个问题,更难找到的是没有日志,因为我的类是一个框架的成员和依赖于该框架的应用程序扩展。对于应用程序,Xcode控制台中有日志,但对于应用程序扩展没有日志。