Closed texastoland closed 11 years ago
Can you explain what it's supposed to do? In particular, I don't understand the point of using dispatch_once
to set an associated object like that.
Yeah that pattern was popularized for instantiating singletons instead of checking nil
. My FIIcon
category snippet uses it for just that. It shouldn't cost any memory or computation until first access.
My UIView
category snippet is part of an API that proxies UIAppearance
selectors directly to arbitrary [sub]layers for better styling since CALayer
supports CSS-like method selectors. In this case it facilitates getting arbitrary additional sublayers for fancy filters or whatever. GCD ensures they're only added as desired even if by an UIAppearance
proxy.
In practice I typically only instantiate ivars once and modify their state thereafter. But I instantiate them in lifecycle methods that categories shouldn't replace. My Associated Object API provides both storage and lazy instantiation.
I'm familiar with the pattern, but this isn't a singleton. You're using a global dispatch_once
to control the adding of an associated object to a single arbitrary instance in your -[UIView sublayer]
. This doesn't make any sense to me, and providing an API that takes a dispatch_once_t *
in general does not seem like the right approach.
Ah quite right my sublayer one is messed up. I'll fix it. In essence it needs a unique key per instance.
That doesn't really address the overall concern, though. What is the point of using dispatch_once
to gate access to an associated object like this? dispatch_once
is generally used for globals, but associated objects are inherently per-instance, so it seems like a complete mismatch.
Although it's not a singleton it is truly a multiton. Because categories can't have ivars the only alternative is still a nil
guard or + load()
without lazy instantiation. GCD just "feels" better to me. It's funny I ran across your blog googling about it just now. What would you do besides a nil
guard? PS thx :)
The thing is that I don't see how the GCD solution works. There appear to only be two cases:
Case 1 is basically the standard singleton pattern and can be solved without associated objects, by just using a global variable. In case 2, dispatch_once
doesn't work, because you need to run the code more than once (i.e. once for each object). Case 1 can use dispatch_once
but doesn't need associated objects. Case 2 needs associated objects but can't use dispatch_once
. So I don't see where it's ever useful to have an API that combines them like this. Can you give an example of where it would be useful?
Wow what's ridiculous is I'm using a static variable for a singleton dictionary elsewhere in that same class. Guess I had tunnel vision. If I have a reasonable multiton solution I'll share. My use case is implementing category properties like my sublayers without nil
checks. Closing ticket; great feedback.
OK, cool, glad we figured out what the disconnect was. I think you'd want to use associated objects still, but I'm not sure if there's a good way to lazily initialize them. You can do a check-and-set, but it's not thread safe without external synchronization....
I tried concocting a strategy to use the pointer storage returned by objc_getassociatedobject(self, key)
to store a dispatch_once_t
and failed. I just wrapped it in @synchronized
for now.
Just wanted to note that anytime I've googled about Obj-C sticking points your blog has unanimously been the authoritative source of documentation. If you had a book I'd read it :neckbeard:
Would this fit in your library?