3

It it possible to create a locally scoped variable in a method for the lifetime of it's class instance?

I can't use static because it would be shared across all class instances, which is no good. In essence, I want to protect an instance variable by making it so that can only be accessed by one particular method in the class.

I'm thinking this can't really be done, but I thought I'd ask cause it would help a lot.

UPDATE
So, I'm marking @dasblinkenlight's answer as correct (and it is). Although @joshcaswell provided a reference to a better answer in the comments, which is an actual implementation of associative references by Richard J. Ross III. This provides a much easier way of associating a reference without having to dive into the runtime (because he does it for you). If I had found this answer during my original search I wouldn't have asked this question in the first place. But I didn't, so I did.

Why Do this?
I came across an article by Brent Simmons today called Why is Using Associated Objects a Hack?, which directly relates to the question of why I would need to do this in the first place (@bbum & @GabrielePetronella asks this). In my commented discussion with @dasblinkenlight, I explain I want to protect a lazily instantiated iVar from being accessed directly except by it's constructor method. The best way to do this is to hide the iVar from all other class methods so it can only be accessed through it's constructor method. You can, of course, rely on naming conventions (i.e.: _lazyiVar) to remind you not to access it directly, but this is (IMO) a rather fragile form of protection (and I have done this exact thing in the past). Using associated references is a hack and you should question techniques that access the runtime directly, but in this case I prefer the hack as it makes my code that much less likely to crash by protecting my lazily instantiated variables.

8
  • 1
    An instance variable? Commented Oct 18, 2013 at 18:11
  • @bbum local method scope Commented Oct 18, 2013 at 18:12
  • @GabrielePetronella Not sure what that buys vs. an instance variable. Commented Oct 18, 2013 at 19:54
  • 1
    @bbum Oh me neither. :D Commented Oct 18, 2013 at 21:29
  • I think this is the same as ObjC ivar scoped method variables, for which a thoroughly clever though rather wild and wooly solution was written by Richard J. Ross III. Commented Oct 18, 2013 at 23:44

1 Answer 1

4

You are correct, this is not possible: locals cannot outlast the scope in which they are defined. You can add "private"-ish instance variables through class extensions, but these would be accessible to implementations of all methods, not just a single one.

You can also fake addition of instance variables with associative references, but that would require direct interaction with runtime. These references would be accessible to all methods as well, but you can "hide" them by making their static ObjectTagKey local to your method.

Sign up to request clarification or add additional context in comments.

4 Comments

Yeah, using associative references would work, but it's too much for what I'm trying to accomplish. I'm lazily instantiating the variable and thought it would be great if I could force other method calls to use the method rather than directly access the variable.
@AaronHayman If the ivar is in a class extension (i.e. not in the header), the only code that has direct access to it is your own.
I think you misunderstand. I mean "force other methods in the same class" to use the constructor method rather than access the iVar directly. This would ensure I don't accidentally access the iVar directly when it hasn't been instantiated (for example, if I come back to the code after a while). All my iVars are listed privately in the @implementation unless I absolutely need to make them public... which is very rare.
@AaronHayman I see. In this case you could give your variable a special name related to the actual name, but also indicating that the variable is initialized lazily. For example, if your variable stores maxSize, call the variable _lazyInitMaxSize, and use it exclusively in the maxSize method. People who maintain your code (including yourself) should be able to guess that they must not access this variable directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.