Regular class global variable being shared between object instances - help! - objective-c

I have just started learning objective c having a little Java experience and this site has been really helpful for answering loads of my questions, but I've hit an issue I can't quite fathom. Theres a fair amount to be read on the topic but I can't quite find where I've gone wrong.
I read this:
Objective C does not support class data members (i.e. data shared by all objects of the same class), however, they can be emulated through the use of the static modifier. For example, declaring a static int count variable in the implementation file of the Employee class would result in all Employee objects sharing a single integer variable called count.
But I seem to have ended up with this functionality without trying... and I don't want it!
The scenario is that I have a Category of UIImageView in which I'm declareing a global variable (just below my #implementation line) to count a particular event and have it used in my new methods.
#implementation UIImageView (Draggable)
int touchesCount = 0;
// methods ...
Everything works fine if I have a single UIImageView. However when I create and add a second instance of UIImageView this count variable is being shared between the two giving unexpected behaviour.
Figure it may be relevant to show how I'm creating the objects:
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:myImageRect];
UIImageView *myImageView2 = [[UIImageView alloc] initWithFrame:myImageRect];
// ... (create, manipulate and set 2 images to the 2 views)
[self.view addSubview:myImageView];
[self.view addSubview:myImageView2];
Other than that, any suggestions on where I might be going wrong?
Thanks!
Edit: To illustrate a bit more what I'm doing with the 2 views, self in this case is a ViewController.

What you are looking for are instance variables, but categories can't add those to an interfaceApple:
Note that a category can’t declare additional instance variables for the class; it includes only methods.
You should be using inheritance instead:
#interface MyView : UIImageView {
int touchesCount;
}
// ...
#end

Related

What is a proper paradigm for having a mutable global value in objective-C

So, let's say that I am displaying an integer myInt value in OneViewController. Then, while a different view is showing, AnotherViewController, I need to increment or decrement myInt.
So the scope needs to be global or at least be able to be accessed by other viewControllers and it needs to be mutable.
I know that properties one way to do this but I haven't been able to get them to work. I have been importing the header file of OneViewController into AnotherViewController but that wasn't what I was missing.
I've gone through several introductory books but multi-view controller variable work wasn't explicitly covered in any of them. Clearly I'm a beginner so please excuse any conceptual misunderstandings.
Doesn't have to be view controllers -- any sort of custom classes.
In FirstClass.h:
#property(whatever) int someIntInFirstClass;
-(void) someMethodInFirstClass;
SecondClass.h
#property(whatever) FirstClass* myParent;
FirstClass.m
SecondClass* second = [[SecondClass alloc] init];
second.myParent = self;
[second startSomething];
SecondClass.m:
[self.myParent someMethodInFirstClass];
int x = self.myParent.someIntInFirstClass;
self.myParent.someIntInFirstClass = x + 1;
Have a look at ReactiveCocoa library and check how the signal pattern works. The library has to offer a lot of things including the scenario you have just mentioned.
https://github.com/ReactiveCocoa/ReactiveCocoa
A bit of a learning curve. But worth!

Override a property to make it read-only from the subclass

I would like to subclass UILabel in such a way that the user of the class cannot set the text directly through label.text = #"foo". Instead I'd like to set the text from inside the subclass depending on some values.
What I tried:
BalanceLabel.h:
#interface BalanceLabel : UILabel
#property(nonatomic,copy, readonly) NSString *text;
#end
However, I get a warning telling me I'm restricting text access (like I wanted to) but I don't get any compile time errors if I try to set the text directly using an object of my subclass.
You can't do this. As a trivial example as to why not, just think of how the following code should behave:
UILabel *label = [[BalanceLabel alloc] init];
label.text = #"string";
That code creates a BalanceLabel, but stores it in a variable of type UILabel, which means that the subsequent setting of the .text property can't know that you tried to make the property readonly in BalanceLabel.
Unfortunately there's not much you can do about this. You could override the setter to throw an exception, which will let users know what they did wrong, but of course will also crash the app.
You should be putting the logic into controller that managed the view instead of view directly.
I assume you have some view that gets updated with new values and you want to update the BalanceLabel based on these new values.
Your controller is a delegate for your view so it receives new values, from either user or other modules of your app that populated new values (like loaded from file, downloaded from network and so on).
Your controller then figures out which bits of view needs update and sets new values - in your case calculate balance, I assume

Is there a way to see what variables are declared inside of a method?

Im making a tweak in theos, and need to see the names of some variables.
Say a method looks like this:
- (UILabel*)makeALabel {
UILabel *name_that_i_want = [[UILabel alloc] init];
[name_that_i_want setText:#"abcdefg"];
return name_that_i_want;
}
When I look through the headers for this method, I would see:
-(id)makeALabel;
Is there a way for me to dump the variables that get declared inside of that method when I hook into it?
-(id)makeALabel {
%orig;
//somehow get name of the label declared
UILabel *label = MSHookIvar<UILabel *>(self, "name_that_i_want");
}
No!
Needing to know values of variables declared within a function or methods or object is indicative of bad design. It goes against encapsulation one of the 3 main principles of object-oriented programming.
The answer is NO.
What you are trying to do, may be accomplished by changing the design of your requirement, by creating a Class and ivars that you can use in the methods, just to replace the local variables.
Then you can use Objective-C Runtime to access ivars/properties/methods of a Class.

Understanding self in Objective-C

The code below is from an iTunes U course on iPhone dev in Objective-C. I've read the Apple documentation and it's all very very clear with the exception of self. I sort of understand self to be a pointer to myself, but what exactly does that mean? In the code below what exactly does self mean? What is the difference between self.topSpeed and self.nearestWormhole in the implementation file or does self refer to the same thing on both occasions? Does self.topSpeed refer to Planet * and self.nearestWormhole refer to Wormhole * ? Thanks to anyone who answers, I've learned C and now trying to learn OOP so any input is appreciated.
(Header file)
#import "Vehicle.h"
#import "Planet.h"
#interface Spaceship : Vehicle
#property (nonatomic) double topSpeed;
- (void)orbitPlanet:(Planet *)aPlanet
atAltitude:(double)km;
#end
(Implementation file)
#import "Spaceship.h"
#interface Spaceship()
#property (nonatomic, strong) Wormhole *nearestWormhole;
#end
#implementation Spaceship
#synthesize topSpeed = _topSpeed;
#synthesize nearestWormhole = _nearestWormhole;
- (void)setTopSpeed:(double)speed
{
if ((speed < 1) && (speed > 0)) _topSpeed = speed;
}
- (void)orbitPlanet:(Planet *)aPlanet atAltitude:(double)km
{
double speed = self.topSpeed;
if (speed > MAX_RELATIVE) speed = MAX_RELATIVE;
[self.nearestWormhole travelToPlanet:aPlanet
atSpeed:speed];
}
#end
self (or this in C++) refers to the object which is executing the method (or "on which the method is being invoked").
Suppose I have a room with three people, Arthur, Betty, and Ziggy, and a box of hats. We also define that
Arthur's teacher is Betty.
Betty's teacher is Ziggy.
Ziggy does not have a teacher.
I want to give the following set of instructions to all three people:
1. Put a hat on Ziggy's head.
This is pretty easy. "Ziggy" means the same person to Arthur, Betty, and even Ziggy. No matter who follows this instruction the same person receives the hat.
2. Put a hat on the head of your teacher, if you have one.
This instruction will have a different effect depending on who's following it, because teacher refers to someone different for each of the three. But each can ask him/herself "who is my teacher, if I have one?" and find that person.
But the next thing I want is for Arthur to put a hat on Arthur's head, Betty to put a hat on Betty's head, and Ziggy to put a hat on Ziggy's head. We can't refer to that person by name (like Ziggy) because it depends on who is doing it. Suppose we treat it like "teacher" and establish a variable "foo" such that Arthur's foo is Arthur, and Betty's foo is Betty… but it should be obvious that the idea we are really expressing is that Ziggy's foo is Ziggy, and Jack's foo would be Jack, and Skip's foo would be Skip… do we really need to establish a "foo"? No! Everyone has a foo: it's your self. So let's define an implicit variable "self" that is not declared anywhere but always refers to the person carrying out the action.
3. Put a hat on the head of your self.
This works for Arthur, Betty, Ziggy, and even Jack. It works for anyone.
In your code self refers to the Spaceship whose topSpeed needs to be accessed. You create many Spaceships and each needs to know the topSpeed of that one Spaceship which exists (we know it does because it's calling the method) but has no name (like myWingman.topSpeed) - one's self.
Cristian, I'll offer you a different tack on this. You say you know C, let's start there. If you needed to implement fractions you'd use a struct, and let's assume for some reason you decide to dynamically allocate your fractions. You have something like this:
typedef struct { int numerator; int denominator; } Fraction;
Fraction *newFraction(int numer, int denom)
{
Fraction *result = (Fraction *)malloc(sizeof(Fraction)); // allocate
result->numerator = numer;
result->denominator = denom;
return result;
}
Fraction *multiplyFraction(Fraction *left, Fraction *right)
{
Fraction *result = (Fraction *)malloc(sizeof(Fraction)); // allocate
result->numerator = left->numerator * right->numerator; // multiple (ignoring reduction)
result->denominator = left->denominator * right->denominator;
return result;
}
And you'd use it like:
Fraction *half = newFraction(1, 2);
Fraction *twothirds = newFraction(2, 3);
Fraction *onethird = multiplyFraction(half, twothirds); // results is 2/6 as we don't reduce in this example
This is the ADT - abstract data type - style of programming. You declare a data type whose content is private (the "abstract" part) to the functions you will provide, and a bunch of functions.
At the basic level what object-oriented programming does is just invert the way you look at this. Instead of "call function multiplyFraction passing two fractions" you say "pass the message multiplyFraction, along with a fraction, to a fraction". Using Objective-C syntax the last line above:
Fraction *onethird = multiplyFraction(half, twothirds);
becomes:
Fraction *onethird = [half multiplyFraction:twothirds];
Under the hood this "method send" just becomes a "function call" - Objective-C does a bit of work to locate multipleFraction and then calls it passing it both half and twoThirds.
Almost there! Now to match the changed syntax for the call Objective-C also changes the syntax of the definition of multiplyFraction:
- (Fraction *) multiplyFraction:(Fraction *)right
{
Fraction *result = [Fraction new]; // allocate
result->numerator = ????->numerator * right->numerator;
result->denominator = ????->denominator * right->denominator;
return result;
}
But what do you write for ????. As you'll see the syntax only names the second parameter (right), there is no name given for the first (which was left). Objective-C hides the passing of this parameter, every method takes at least one parameter - it is the "object" (rather than "ADT") that the method is sent to. It needs a name so you can refer to it, that name is self:
- (Fraction *) multiplyFraction:(Fraction *)right
{
Fraction *result = [Fraction new]; // allocate
result->numerator = self->numerator * right->numerator;
result->denominator = self->denominator * right->denominator;
return result;
}
And this is essentially it - self is the name of the first argument.
Object-oriented languages build upon this base, for example:
they had direct access to "instance" variables - the "fields" of the original struct;
they change some more syntax - e.g. #interface... replaces struct...; and rather than list the methods (functions) after the type (struct) in the header they are listed inside of it (the `#interface);
they usually add inheritance (though some ADT languages have that as well);
etc.
But under the hood an Objective-C class is implemented as a C struct...
HTH
Objective C emphasizes using getters and setters. To make things simpler, it even generates getters and setters when you #synthesize something.
So
self.topSpeed
accesses the getter for topSpeed. If you omit the "self" part, then it is equivalent to accessing the instance variable(ivars) directly (bad practice).
The reason for having a underscore before the variable name is also to make a clear differentiation between instance variable and the getter for the instance variable. This way, we cannot accidentally refer to topSpeed without "self".
You need to use self to access variable in all places except:
init
dealloc
Hope that helps.
self is indeed a pointer reference to the instance of the class that is running the code. In this case, self would be a reference to an instance of the Spaceship class.
When you reference self in a class method (which is very possible and an acceptable behavior), you are actually referencing a singleton instance representing the class. You can also get this singleton instance by calling [Spaceship class]. In practice, you'd use self like this mostly in factory methods when you need to allocate a new instance.
What you seem more confused about is syntax regarding other classes. You asked:
Does self.topSpeed refer to Planet * and self.nearestWormhole refer to
Wormhole * ?
Wormhole *nearestWormhole represents an instance of the Wormhole class, named nearestWormhole. So, when you use self.nearestWormhole, that is a pointer to a instance of the Workhole class. Inside the Spaceship class you could actually use _nearestWormhole or self.nearestWormhole to access that pointer. Other classes might call something like spaceship.nearestWormhole, which is using the accessor.
'self' refers to the instance of the current class, i.e. in your example it would refer to an instance of the Spaceship class. Because 'self' always refers to an instance of the class, it's not possible to call upon self in class methods.

What is the difference between these two syntax types? (Objective-C)

I'm just trying to get my head around this type of syntax
I know that the
[instanceOfClass Method];
eg. [myImage setImage:[NSImage imageNamed:#"picture.jpg"]];
performs a method on the instance of the class.
but how does this work..
Variable = [Class methodName];
eg. int Value = [sender intValue];
can someone explain this to me. I get that the first example performs a method on instance of class, class or variable..
but how does the latter part work?
Thank you very much.
There are instance methods (defined with a -) and class methods (with a +). Instance methods are called in instances and class methods in classes.
- (void)instanceMethod;
+ (void)classMethod;
Apart from this, you example:
int Value = [sender intValue];
Seems to be an instance method. If it's inside an action, keep in mind sender is just an argument:
- (IBAction)startWork:(id)sender
{
...
}
The second example also performs a method on an instance of a class, but that method returns a value which is assigned to the value on the left side of the equation.
I'd recommend spending a little time reading the introduction provided by Apple. This specific question is discussed in this part of the document:
Like standard C functions, methods can return values. The following
example sets the variable isFilled to YES if myRectangle is drawn as a
solid rectangle, or NO if it’s drawn in outline form only.
BOOL isFilled;
isFilled = [myRectangle isFilled];