Objective-C: sortDescriptorsDidChange argument? - objective-c

I don't get why sortDescriptorsDidChange takes an argument oldDescriptors if it is never used in the method.
- (void)tableView:(CPTableView)aTableView sortDescriptorsDidChange:(CPArray)oldDescriptors {
[result sortUsingDescriptors:[aTableView sortDescriptors]];
[aTableView reloadData];
}
What am I missing ?

sortDescriptionDIdChange is a delegate, so you can implement your own behavior for it.
For example, you could use oldDescription along with the new description to manually calculate the changes and provide a nice animation for them. Or to implement specific behavior if the order didn't change etc. etc.

Related

How to pass parameters using #selector

I need to pass parameters with #selector and here is the method that i need to call using selector:
-(void)clickedInfo:(NSString *)itemIndex{
// some work with itemIndex
}
I know that what i can do is to use an intermediate method as described here.
This approach doesn't work in my case because im adding the target to the uibutton in the cellForItemAtIndexPath method for the collectionView.
The parameter that i need to pass to the clickedInfo method is indexPath.row
and i can not obtain this parameter in an intermediate method.
Thanx in advance
So you want to store some information that can be accessed by the action of a button. Some options are:
Use the tag property of the control. (can only store an integer)
Subclass UIButton and use that class for the button. The class can have a field that stores the information.
Use associated objects (associative references) to attach an object to the button. This is the most general solution.
You can use the performSelector:withObject: selector to pass an object.
Example:
[self performSelector:#selector(clickedInfo:) withObject:myIndex];
- (void) clickedInfo:(NSString *)itemIndex{
// some work with itemIndex
}
Edit: Should be just #selector(clickedInfo:) rather than what I had before.
Edit: Using #newacct 's suggestion, I'd recommend doing something similar to the following:
- (UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath)indexPath
{
button.tag = indexPath.row;
[button performSelector:#selector(clickedInfo:)];
// or
[button addTarget:self action:#selector(clickedInfo:) forControlEvents:UITouchUpInside];
}
- (void) clickedInfo:(id)sender
{
int row = sender.tag;
// Do stuff with the button and data
}
this is addressed lots of places, but it is easier to answer than to point you there:
[someObject performSelector:#selector(clickedInfo:) withObject:someOtherObject];
where someObject is the receiver and someOtherObject is the parameter passed to clickedInfo

How to add another parameter to an existing method

I have a category NSObject+Utilities which contains all kinds of tool methods I use in my projects. Unfortunately I have to add one more parameter to a method that returns NSColor.
Here an Example:
- (NSColor*) ccBlueLight {
return [self libMakeAColor :0.000f :0.535f :1.0f :1.000f];
}
The last parameter (1.000f) is responsible is for transparency. When I created this method I didn´t think of transparency and I fixed it to 1.000f. Since I´m using these cc Colors in different projects I cannot simply add another parameter without getting errors in the other projects when using them.
Is there a way to add the transparency parameter without problems?
Write a new method with transparency parameter:
- (NSColor*) ccBlueLight:(CGFloat)transparency {
return [self libMakeAColor :0.000f :0.535f :1.0f :transparency];
}
And change the implementation of existing method to use default value.
- (NSColor*) ccBlueLight {
return [self ccBlueLight:1.000f];
}
Note that these two are different methods. The old one's signature is not changed and there is no need to change the callers of old one.
Is there anything speaking against simply adding a second method? So that one project could use the original and the other one the new method.
- (NSColor *) ccBlueLightWithAlpha:(NSNumber *)alpha
{
return [self libMakeAColor :0.000f :0.535f :1.0f :[alpha floatValue];
}
Like this?
- (NSColor*) ccBlueLight {
return [self libMakeAColorRed:0.000f green:0.535f blue:1.0f];
}
- (NSColor*) ccBlueLightWithAlpha:(CGFloat)alpha {
return [self libMakeAColorRed:0.000f green:0.535f blue:1.0f alpha:alpha];
}

Changing objective-c method after wide implementation

I have a method which is used widely throughout my app, it looks like so:
-(void)commandWithParams:(NSMutableDictionary*)params command:(NSString *) command method: (NSString *) method onCompletion:(JSONResponseBlock)completionBlock { }
This is used to carry out REST calls to an API. After using it all over the place i realize that i need to add another parameter (which will be used only some of the time), and i'm wondering what the best way to do this is.
I thought about using a using a parameter which defaults to nil if not specified, but apparently this is a no-go in objective c (?)
How should i go about changing it? Do i have to change it everywhere it's called and pass nil? If so, any neat functions in xCode to do this without too much hassle?
Thanks.
There are no optional arguments in Objective-C. What you could do instead is use two separate methods.
Imagine you had this method:
- (void)methodWithArgument:(NSString *)str {
// block A
}
Now you need to add a new argument, but don't want to specify it everywhere in your code.
Create a new method with the additional argument and move your implementation to it. How you handle the additional argument, depends on what the method does. From your old method, call the new one with nil as the new argument:
- (void)methodWithArgument:(NSString *)str andArgument:(NSString *)str2 {
if (str2 != nil) {
// do something.
}
// block A
}
- (void)methodWithArgument:(NSString *)str {
[self methodWithArgument:str andArgument:nil];
}
This will work as if you had a method with an optional parameter, that defaults to nil (or whatever you chose). It's a common design pattern and you see it all over Apple's frameworks too.
As an alternative to the method above you may do refactoring in AppCode. It allows to do such of things.

Call a method every time a parameter is set on Objective-C (Cocoa)

I currently have a class with 15 properties (and growing), and I'm finding myself having to call an update method every time one of those properties change.
Currently, I'm overriding every setter with a code like this:
-(void)setParameterName:(NSUInteger)newValue {
if (_param == newValue)
return;
_param = newValue;
[self redraw];
}
The method [self redraw]; being the key here.
Is there a better way to do it? Should I be using keyValue observers (the method observeValue:forKeyPath:ofObject:change:context:)?
Notes:
All properties (so far) are assign (mostly enum, NSUInteger, CGFloat and BOOL);
All those properties are set using bindings (method bind:toObject:withKeyPath:options:). Except when loading from the filesystem (which is not important, as I already call the drawing methods on every object after the loading is done);
The value changes are only for the current object. I do not need to be told when changes occur on other objects;
I have other properties that I don't need to watch the changes on it (because it will have no effect on my output and drawing the output is kinda time-consuming).
Thanks!
Since these properties are updated using bindings, which invoke -setValue:forKey:, you can override that method instead of writing custom setters:
+ (NSArray *) keysAffectingDrawing {
static NSArray *singleton;
if (!singleton)
singleton = [NSArray arrayWithObjects:
#"property1",
#"property2",
#"property3",
nil];
return singleton;
}
- (void) setValue:(id) value forKey:(NSString *) key {
[super setValue:value forKey:key];
if ([[CustomClass keysAffectingDrawing] containsObject:key]) [self redraw];
}
(I was first inclined recommend key-value observing but agree it's not the best solution here. I think the reason is in part that there's only one object, and in part because the design doesn't follow MVC. Usually in MVC an object that draws itself isn't the one with all the properties.)
(Added: Ahh, I see. The model is responsible for rendering the properties to a bitmap, and that's what -redraw does. That's fine MVC. To make it clearer, I recommend changing the name of the method from -redraw to something like -updateImage or -renderImage, since it doesn't actually do any drawing.)
You could use the Key-Value Observing to avoid repeating in all properties setter the method call, however i think that calling the method directly in the setter is not the wrong way to do it, and could even be faster ...

Explanation of Cocoa #selector usage

I'm new to Cocoa/Cocoa Touch, and working through a development book. I've come across situations where the #selector() operator is used. I'm a bit lost on how and when the #selector() operator should be used. Can someone provide a short and sweet explanation and example of why it's used and what benefit it gives the developer?
By the way, here is sample code taken from Apple's iPhone development site that uses #selector()
if ([elementName isEqualToString:#"entry"])
{
parsedEarthquakesCounter++;
// An entry in the RSS feed represents an earthquake, so create an instance of it.
self.currentEarthquakeObject = [[Earthquake alloc] init];
// Add the new Earthquake object to the application's array of earthquakes.
[(id)[[UIApplication sharedApplication] delegate]
performSelectorOnMainThread:#selector(addToEarthquakeList:)
withObject:self.currentEarthquakeObject waitUntilDone:YES];
return;
}
The selector operator provides a way to refer to a method provided by an object, somewhat similar to a function pointer in C. It is useful because it allows you to decouple the process of calling methods on an object. For example one piece of code could provide a method, and another piece of code could apply that method to a given set of objects.
Examples:
Test to see if an object implements a certain method:
[object respondsToSelector:#selector(methodName)]
Store a method to later call on an object;
SEL method = #selector(methodName);
[object performSelector:method];
Call a method on a different thread (useful for GUI work).
[object performSelectorOnMainThread:#selector(methodName)]
In addition to what's been said, you can also wrap up the #selector in an NSInvocation for later use. You can set the arguments to the NSInvocation a long time after it's created, and activate it when you need the message to be fired. This gives you a lot of power.
For an introduction to the concept, Scott Stevenson has a great post entitled "Dynamic Objective-C with NSInvocation".
#selector() is used each time you need to pass the name of a method as an argument to another method, a function or as a variable value. Passing directly the name doesn't work in objective-C.
One practical example is validateMenuItem method where menu items are identified with their target actions.
Simplified example:
- (BOOL)validateMenuItem:(NSMenuItem *)item {
if ([item action] == #selector(selectFiles:) && otherCondition) {
return YES;
} else {
return NO;
}
}
One reference to look at:
http://en.wikipedia.org/wiki/Multiple_dispatch
You can use a selector to invoke a method on an object—this provides the basis for the implementation of the target-action design pattern in Cocoa.
[myObject performSelector:#selector(runMYmethod:) withObject:parameters];
is equivalent to:
[myObject runMYmethod:parameters];