understanding whether to use protocol or inheritance (or both?) - objective-c

I have a type of object in my game that simply moves horizontally.. It has a method like this:
-(void)moveLeftWithBlock:(void(^)())block {
self.targetX = self.position.x - MOVE_AMOUNT;
id action = [CCMoveTo actionWithDuration:0.125f position:ccp(self.targetX, self.targetY)];
id ease = [CCEaseInOut actionWithAction:action rate:4];
[self runAction: [CCSequence actions: ease,
[CCCallBlock actionWithBlock:block], nil]];
}
...
Now, I wanted to make a second type of object that's exactly the same, except that it can also move vertically... My initial thought was to just subclass that object's class, and overwrite the moveLeftWithBlock and update its targetY.. but not only do I not like that solution because I still end up with 99% duplicate code amongst the two classes, but also because my game needs the Y position set prior to that moveLeftWithBlock method being called.
So next I thought-- Ok, so I can make my game call a prepareToMove method, which could do any kind of setup that might be required... For the main object type, nothing.. For this 2nd object type, set the targetY.
However, I immediately started thinking-- wait---- I know protocols are about explicitly defining methods that are OPTIONAL or REQUIRED, and it made me think that perhaps I should be utilizing this here, but I just am not sure how.
So, can anyone explain to me how a protocol could be used in this case-- and if it is "the way to go" or not?

Any of these would work. You could add to this andAlsoMoveVertically: (bool) isVertical and then add the vertical movement in an if statement in the function.

Related

Required Methods for Text Changes in Custom NSTextView

I have a custom NSTextView, and I want to be sure to send all of the proper messages and notifications when making changes to the text programmatically. I mostly care about undo/redo registration, but I'd generally like to do things the "right" way. Anyway …
The messages I'm aware of are:
-shouldChangeTextInRange:replacementString:
-didChangeText
If I understand the documentation correctly, before any changes are made to the text view's textStorage object, one needs to send the -shouldChangeTextInRange:replacementString: message to make sure a new undo group is opened (and inform any delegates of the commencement of editing). If YES is returned, the changes can be made to the text. Once all of the changes have been applied, the -didChangeText message needs to be sent to close the undo group (and again, notify any observers). Is this right?
When modifying existing characters (or attributes) those instructions make sense to me. I'm acting on an existing range of text, so it's easy to know what to send for the affectedCharRange parameter. What about when I need to insert something?
Let's say I want to insert a random word at the current insertion point index. Do I need to send the -shouldChangeTextInRange:replacementString: message? I'm not modifying existing characters, but I am adding new characters to the existing characters.
If I do need to send this message, what range do I use for the affectedCharRange argument? Whenever I try to send the new computed range of the to-be-inserted text, I get "Range Out of Bounds" errors, which makes sense, considering the text view's length has yet to change. Do I just send the range for the insertion point with an empty length (e.g. self.selectedRange when nothing's selected)?
For example:
- (void)insertRandomWord:(id)sender
{
NSAttributedString *randomAttrStr = [self randomAttributedString];
BOOL shouldChangeText = [self shouldChangeTextInRange:shouldThisBeTheSelectedRange // <-- WTF, mate?
replacementString:randomAttrStr.string];
if ( shouldChangeText ) {
[self.textStorage insertAttributedString:randomAttrStr
atIndex:self.selectedRange.location];
// This should always get called, right?
[self didChangeText];
// Is this where I would set the typing attributes?
self.typingAttributes = [randomAttrStr attributesAtIndex:0 effectiveRange:NULL];
}
}
I've gone as far as to create a method that takes a range and a block as arguments, so I don't accidentally forget to call something. Is this a good idea or not?
- (void)changeTextInRange:(NSRange)range replacementString:(NSString *)replacementString usingBlock:(void (^)(void))block
{
BOOL change = [self shouldChangeTextInRange:range replacementString:replacementString];
if ( change ) {
block();
[self didChangeText];
}
}
Last, but not least, do I need to call the NSTextStorage "editing" methods, too? The methods I'm referring to are:
-beginEditing:
-endEditing:
The documentation discusses calling those when one subclasses NSTextStorage, but I'm a little confused as to whether those messages need to be sent, too. It doesn't really say whether or not to use -fixAttributesInRange:, but I know the -endEditing message calls that to do cleanup after an editing operation.
I apologize for the discombobulated mess of questions. I'm just super tired and confused, and Apple's documentation has been … lacking. Any tips, pointers, and/or suggestions would be greatly appreciated. Thanks!

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 setter in Objective-c. Why check is equal parameter

Often find custom setter sintaxis like this:
- (void)setParentCatalog:(Catalog *)parentCatalog {
if (_parentCatalog != parentCatalog) { //???
_parentCatalog = parentCatalog;
[self refresh];
}
}
Why i should check?
if (_parentCatalog != parentCatalog)
This checks if both _parentCatalog and parentCatalog are pointing to the same memory location.
If both are same object then no need to set the objectValue.
The reason for checking if the two are equal is to avoid executing code when it's not necessary. If the method is called very often, this could have a performance benefit. Under non-ARC, your code might look more like this:
- (void)setParentCatalog:(Catalog *)parentCatalog {
if (_parentCatalog != parentCatalog) {
[_parentCatalog release];
[parentCatalog retain];
_parentCatalog = parentCatalog;
[self refresh];
}
}
So, by checking that what you received is actually a new value, you avoid those retain and release calls happening (which are still there with ARC). You've also got [self refresh] in there, which probably doesn't need to happen unless the value has actually changed.
The idea here is that if the parameter passed in to the setter is the same object already stored in the property, then there is no need to call [self refresh] again.
A refresh method often reads in data, works on it and then re-displays it in the app's views. No need to do all this work again if the data in the property haven't really changed.
It's a decision that is use case dependant. The idea behind this guard is to prevent doing unnecessary work.
If you imagine that your [self refresh] kicked off a very expensive operation then you would be reluctant to do it every time. So if you only do it when the object actually changes you save yourself some work.
Of course this may well be the behaviour you are looking for in which case you would need to stick the [self refresh] call outside of the guard.
Like all code examples you find it's worth weighing up the trade offs of the implementation and then you can better decide what you need in your case.

In Objective-C, why is casting needed when assigning to a variable whose type is specified?

This use of type casting comes up a lot, e.g. in a button tap action:
UIButton *button = (UIButton *)sender;
My question is why the explicit cast "(UIButton *)" is necessary. Doesn't assigning the value of "sender" to variable "button" already effectively cast it as a pointer to UIButton?
It tells the compiler that you know what you're doing: "I know sender technically isn't a UIButon* but I promise that it always will be at run-time."
As Stephen said, it is not really required.
But it is a quesiton of style and good business practice.
BTW, when you omit it, you get a warning, not an error.
Just for getting rid of the warning you could simply do:
someObject = (id) anotherObject;
That will work with references to any Object of any class. You see that there is hardly any casting acutally done.
You can allways assign to superclasses without cast:
objectOfAClass = objectOfSubclassOfA;
Bottom line is, it helps you avoiding mistakes by forcing you to think a very brief moment about what you are actually doing there.
In objective-c it is common to write action methods like
- (void)didAction:(id)sender
This method can be called by any object(eg. UIButton, UIControl etc.), and expected set the sender self.
Ever object is an id. So in that method you have a variable in type of id. If you are sure it is a button then you can cast to UIButton.
Another way is, if you are sure that the method will be called only by a UIButton instance then you can change your action method to
- (void)didAction:(UIButton *)senderButton
If you do it so, you do not need to cast.
Please note that, for that kind castings you are responsible, that nothing goes wrong. If you unsure you can always check the class of object with
- (BOOL)isKindOfClass:(Class)aClass
method.

methods sequence by NSMutableArray/NSMutableDictionary contents (Image multi-effecting)

What I want to do:
I want to implement ability for user to use CIFilters on image. So I need somehow to fix it's sequence. For example if user opens image, then applies CIGaussianBlur, and then CIColorControls and then CISepia, I need to get result like that:
On user opened image apply CIGaussianBlur -> on CIGaussianBlur output image apply CIColorControls - > on CIColorControls output image apply CISepia.
Thats OK. But what if then user turns off CIGaussianBlur? I need then to repeat this effect's sequence just without blur. It would look like this:
On user opened image apply CIColorControls -> on CIColorControls output image apply CISepia.
The question
Is it possible to do something like this:
After applying any effect, add some string in NSMutableArray or NSMutableDictionary. Then when applying another effect, check NSMutableArray or NSMutableDictionary contents like that:
if object at index 0 is equal to "blur", apply blur on source image, then take blur's output image like current effect's input image
And so on? So that effects would be re-applied every time in their sequence made by user.
If it is possible maybe someone could suggest me any solution?
I think that this is a great instance for the factory idea to be used.
You should store your array of filters to process the image as an array - that maintains sort order, and is fairly straightforward to deal with (other than something like a NSCountedSet).
The next logical question to ask, then, is how do we apply the factory pattern here? The most important thing to consider is what type should the context object be? Here are a few thoughts:
Using NSString as a constant identifier.
Probably the simplest to start, its , and easy to understand - the downside is that it's slower than other options, and can get to be quite the complex if-else block, as you cannot use a switch statement on a NSString.
NSNumber, wrapping an enum value.
This is probably one of the better options. You can convert right down to an int variable, which compares quite fast on almost any processor I can imagine, and, if you use ObjC 2.5's fancy literals, you could do something like this:
[filters addObject:#(filterType_gaussianBlur)];
Where filterType_gaussianBlur is an enum constant or something.
Another advantage to using an enum is the support for switch statements out of the box. It cleans up your code if done properly, it's faster than a large if-else block, the only thing to look out for is ensuring that you break properly!
Storing Class objects
This one may require some explaining. In objective-c, you can actually store a reference to the type of an object, CIGaussianBlur, NSString, NSData, etc.
This class "object" allows you to dynamically create an object based just on it's type, for example:
Class cls = nil;
if (stringMutable)
cls = [NSMutableString class];
else
cls = [NSString class];
NSString *mutableOrNot = [[cls alloc] initWithString:#"Hello World!"];
However, the disadvantage to this approach would be the inability to configure the objects after they are initialized, and you must use the same selector (method) to initialize each one. If that is not an issue (I do not use CoreImage), then using the Class approach should be fine.
All in all, use whatever makes sense in the situation. If these filters need no additional configuration after they have been initialized, then approach 3 makes a lot of sense. I personally wouldn't recommend approach 1, unless it really is necessary to use a string. Whenever you can, always try to control the values that an object can have. It makes your life much easier, trust me.