views:

61

answers:

2

I have a UIImageView object in one of my classes, but I need to set that view from within another class.

How is access granted to that method?

Regards

+1  A: 

All interface methods are public by default, so as long as you have access to the object itself, you can call the method.

However, instance variables are private by default, and not automatically exposed as methods. If you want to write them from outside, you need to declare them as readwrite properties, and either @synthesize or manually implement the corresponding setXXX accessor method. (In the case of an object property like a UIImageView, you should set it as retain as well.)

See the properties documentation for more details.

(Note that, while you can pass around a view like any object, if you want it onscreen and participating in event-driven behaviour, there's usually some other management to do. This will not be supplied by a default @synthesize setter, so writing an explicit accessor is probably the way to go.)

Longwinded and probably patronising update

(Feel free to skip to the end for the executive summary!)

OK, from your comment it seems your problem is more structural than syntactic. Ultimately, you need to think about what objects exist where and who owns which of them. These are design decisions, and there isn't necessarily one "right" answer; the only thing that is for sure is that if you want object X to be able to do stuff to object Y, then sooner or later it has to be able to get -- or be given -- a reference to it somehow.

Now, one way to do this is just to make all the relevant objects into global variables. This is very unfashionable and brings with it a lot of potential problems, but isn't always wrong. It seems you already know how to do this, since you say that your image index is global.

Most alternative approaches are ways of wrapping up something that is still tucked into a global somewhere, but making it a bit less exposed. For example, you could make the object a static variable in some file and implement a function or class method in the same file that returns a reference to it. This should be marginally safer, but it amounts to something pretty similar in the end.

What you will normally do -- and probably are even if you haven't thought about explicitly -- is to hang your objects of interest off some main application object. This is what pretty much everyone does pretty much all of the time in a modern GUI app. So there's still at least one global object somewhere, but the way everything else fits together is much more structured. This is where you have to start thinking about design and ownership and responsibility.

Your main application object owns everything in it, and everything will ultimately be created as a result of what the app does. The responsibilities will generally be subdivided and shared between a number of auxiliary objects that the top level will create, and these in turn will create others, and so on. In the case of a Cocoa app, some of them might well be created at build time in IB and carbon-frozen into NIB files for subsequent runtime reanimation, but that reanimation will itself be done by one of the app's levels of control.

Every object that gets created, of every class you design, is created by something, at some defined point in the program, and has to be owned by something. Something has to be in control -- and you should know what it is. For the kind of objects you're talking about, the things in control will often be controllers (or delegates, or something acting as both). When they create their objects, they are responsible for them. One of those responsibilities is often to set up any links that need to exist between them.

Of course, I don't know what the actual structure of your program is. But here are a couple of obvious possibilities:

If your objects exist in NIB files, then you can link them up in Interface Builder by making sure that there are appropriate IBOutlet fields in their interfaces and then setting those fields in IB. In this case, the runtime chores of linking will be handled during reanimation, and you can just use the IBOutlet ivar in one object to send messages to the other.

If, on the other hand, the objects are being explicitly created in code, then the code that creates them can pass a reference from one to the other. The receiving object needs to do something with the reference -- for example, stash it in an instance variable exposed as a property -- but can thereafter use it to invoke methods to do things like set images.

One likely complication in the latter case is that the relevant objects are being created in different bits of code and different owners have responsibility for them. In which case, you need to adjust your design to accommodate the fact that one needs to know about the other. The crude thing to do would be to bolt on methods up and down the hierarchy until something can see both at once and do the magic joining. Alternatively, you could rethink your design so that it doesn't require such arbitrary coupling of non-cohesive objects.

In Short

If you have object A that needs to do something with object B, either:

Provide some way of getting a reference to B when you need it, such as a class method +(ClassOfB*)getTheGlobalInstanceB

Or:

  • Give A an instance variable ClassOfB* theB
  • Declare it as @property (readwrite, retain) ClassOfB* theB in the interface for A
  • In the implementation for A add @synthesize theB
  • At some point in the code where you have created and have access to both A and B, and before A starts actually needing to use B, include a line like A.theB = B

Recasting this advice in terms of UIImageView etc is left as an exercise for the reader.

walkytalky
My problem is I have a UIImageView object which is need to set but it is declared in one class, and I need to set that same object from another class. I tried readwrite , but it still cant find the object.
alJaree
@aljaree Do you mean that you don't have a reference to the object that *contains* the UIImageView?
walkytalky
I have an object UIImageView *myView which I set to an image in an array using a global index. I need to set that image to the index from the other class. I do reset the index, now I just need to get that picture from the array(which is being working) and assign it to the myView object. Yes I mean I dont have reference to that object myView from the outside class. regards
alJaree
I tried this Daily_QuoteViewController.myView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.png", tempInt]]; and got an error saying image is not a structure or union.
alJaree
Thanks,I appreciate the time. I know java and design etc. I have only been doing objective c for about 8 days, I solved it. All I needed to do was reference it using UIImageView *myView. :P Thanks a lot. Your advice was very good.
alJaree
+1  A: 

Declare it as a property in the class header file, synthesize and manage it in the implementation file.

Depending on how you define the property (but usually) any instance of the class will have that property's accessors available to other classes.

Alex Reynolds
I have tried this and get a myView undeclared error. I define the property like follows @property(nonatomic, retain, readwrite) UIImageView *myView;
alJaree
I think you only need `nonatomic` and `retain`. But you also need to 1. `@synthesize` the property in the implementation file; 2. initialize the property somewhere in the class; 3. `release` the property in your class' `dealloc` method. The documentation I linked goes into these details, which you may want to read.
Alex Reynolds
I do all of the above. I use myView object, set it in the viewController class, but I have another class which holds a UITableView which when the user selects a row in the table I need to load the saved "favorite" which is an image. This image needs to be loaded by setting myView to the current index of the array which holds the image. I tried to put the code in the viewDidLoad method of the viewController but the view loads only on startup, the other 2 views(add favorite and show favorite) only load and then are dismissed when user selects a row in the table or clicks add to save favorite.
alJaree
Why not instantiate the other two view references in `-viewDidLoad` and use them in the table delegates? Then your class will always have references to them for the life of the view controller (or until those two views are released by you somewhere else).
Alex Reynolds