【问题标题】:Return an unique identifier in a idempotent way以幂等方式返回唯一标识符
【发布时间】:2015-02-11 11:36:02
【问题描述】:

我正在创建第三方库,我需要找到一种以幂等方式创建唯一标识符的方法。我会尽力解释。

假设您是UIViewController,例如MyViewController。该库公开了两个不同的 API 来注册/注销组件。

当我对视图控制器执行register 时,我需要为控制器创建一个唯一标识符,该标识符在被释放之前应该是有效的。如果我创建这个控制器的另一个实例,标识符应该不同。

换句话说,假设我有

MyViewController* a = // alloc-init

现在在a 内,我这样注册自己

// I'm within viewDidLoad for example
[[LibraryManager sharedManager] registerEntry:self];

此时,我的需求如下:根据我传入的实例创建一个唯一标识符(在我的库中)

如果a想注销,可以这么简单

// I'm within dealloc for example
[[LibraryManager sharedManager] deregisterEntry:self];

根据传入的实例 (self),我需要(以某种方式)检索先前创建的标识符,以便清除使用 register 方法创建的内容。

如果我创建另一个控制器,比如b,则标识符应该与使用a 创建的不同。

我不会依赖委托模式来要求控制器(在这种情况下)通过 [[NSUUID UUID] UUIDString]; 或类似的方式提供唯一标识符。

有没有办法根据传入的实例创建唯一标识符?我正在考虑存储内存地址或类似的字符串表示形式,但这是一种 hack,恕我直言。

【问题讨论】:

  • 你能写一个随机字符串生成器函数吗?如果字符串有 40 个字符,那么它至少有 40 分之 1 是唯一的

标签: objective-c uniqueidentifier idempotent


【解决方案1】:

您想要做什么并不完全清楚,但您可以使用关联的引用。例如,当你想要一个对象的唯一标识符时,你会尝试使用:

NSUUID* uuid = objc_getAssociatedObject(theObject, myKey);

如果对象尚未分配唯一 ID,则将返回 nil。在这种情况下,您可以生成唯一 ID 并为对象设置它:

if (!uuid)
{
    uuid = [NSUUID UUID];
    objc_setAssociatedObject(theObject, myKey, uuid, OBJC_ASSOCIATION_RETAIN);
}

密钥myKey 对您的图书馆来说是独一无二的。一种常见的策略(例如,用于 KVO 的上下文)是创建一个静态变量并使用其地址:

static const int foo;
static const void* const myKey = &foo;

您可以将这些组合起来,使密钥拥有自己的地址:

static void* const myKey = (void*)&myKey;

无论如何,关联对象将在与其关联的对象被释放时被释放(或者如果在其上设置了不同的关联对象,尽管在您的情况下不会这样做)。

不幸的是,这种方法不是线程安全的,因为两个线程都可以尝试查找唯一 ID,发现尚未分配任何 ID,然后生成一个新 ID,然后分配它。最后一个分配将获胜,但与此同时,另一个可能返回的 ID 最终被替换。实际上,该对象将有两个不同的 ID。

因此,如果两个线程有​​可能同时尝试查询 ID,则需要在方法中提供同步。例如,创建一个串行 GCD 队列和dispatch_sync() 一个包含该队列的上述代码的块。

【讨论】:

  • 感谢您的回复。我会尝试重新审视这个问题以使其更清楚。
  • 我刚刚编辑了这个问题。让我知道它是否比以前更清楚。
  • 是的!我同意这种方法。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-05
  • 2012-06-02
  • 2012-11-21
  • 1970-01-01
相关资源
最近更新 更多