Encoding an Objective-c Block? - objective-c

Is it possible to encode an Objective-C block with an NSKeyedArchiver?
I don't think a Block object is NSCoding-compliant, therefore [coder encodeObject:block forKey:#"block"] does not work?
Any ideas?

No, it isn't possible for a variety of reasons. The data contained within a block isn't represented in any way similar to, say, instance variables. There is no inventory of state and, thus, no way to enumerate the state for archival purposes.
Instead, I would suggest you create a simple class to hold your data, instances of which carry the state used by the blocks during processing and which can be easily archived.
You might find the answer to this question interesting. It is related.
To expand, say you had a class like:
#interface MyData:NSObject
{
... ivars representing work to be done in block
}
- (void) doYourMagicMan;
#end
Then you could:
MyData *myWorkUnit = [MyData new];
... set up myWorkUnit here ...
[something doSomethingWithBlockCallback: ^{ [myWorkUnit doYourMagicMan]; }];
[myWorkUnit release]; // the block will retain it (callback *must* Block_copy() the block)
From there, you could implement archiving on MyData, save it away, etc... The key is treat the Block as the trigger for doing the computation and encapsulate said computation and the computation's necessary state into the instance of the MyData class.

Related

Are These Two Instance of the Same Class? (ReactiveCocoa Documentation Examples)

I don't understand where the RACSignal object comes from in the following example in the ReactiveCocoa github documentation.
Under Parallelizing independent work, it first shows the classic objective-c version:
__block NSArray *databaseObjects;
__block NSArray *fileContents;
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *databaseOperation = [NSBlockOperation blockOperationWithBlock:^{
databaseObjects = [databaseClient fetchObjectsMatchingPredicate:predicate];
}];
Clearly, [databaseClient fetchObjectsMatchingPredicate:predicate] returns an array. But, in the reactive version:
RACSignal *databaseSignal = [[databaseClient
fetchObjectsMatchingPredicate:predicate] // <== this should also be an array
subscribeOn:[RACScheduler scheduler]]; // ,<== subscribeOn: is a RACSignal Method only
... it looks like the same method is supposed to return not an array (which would have a rac_sequeance attribute) but a RACSignal.
In this example, is it meant to be read that `databaseClient' class in the RAC example is actually a subclass of RACSignal? Or, is a signal being created in some way not shown?
Currently running MacOS 10.9.3 with Reactive Cocoa 2.3. Documentation is from the ReactiveCocoa 3.0 branch.
It's fairly idiomatic in ReactiveCocoa code to name a method that returns a signal in a similar fashion to a method that would return the value directly. In other words, even though the method that returns the signal doesn't actually perform the action directly (when the method is executed), it's given a method name that suggests that it does.
For example, a method that queries a database and returns the result of that query directly might be named like this:
- (DBResult *)queryDatabase:(DBQuery *)query;
Whereas a RAC-ified version of this method would probably be named like this:
- (RACSignal *)queryDatabase:(DBQuery *)query;
It might seem a bit unintuitive at first, because technically that method doesn't query the database – instead, it returns a signal that results in an action to query the database when the signal is subscribed to – but that's the convention. You don't have to observe the convention in your own code, but a perusal of the OctoKit source code will show you that it's not uncommon.
In this example, is it meant to be read that databaseClient class in the RAC example is actually a subclass of RACSignal? Or, is a signal being created in some way not shown?
In this example, databaseClient is not a subclass of RACSignal. It is just an object that responds to the -fetchObjectsMatchingPredicate: message, and returns a RACSignal from the corresponding method. Hypothetically, the object's class might look something like:
#interface MyDatabaseClient : NSObject
- (RACSignal *)fetchObjectsMatchingPredicate:(NSPredicate *)predicate;
#end

What is the best programming practice for creating an Objective-C Object?

I am learning Objective-C, and as one of the lessons, we create a class Employee, and its superclass Person, along with an Asset class, whose instances are owned by Employee. To test the classes, and their instance functions, I wrote the following code
int main(int argc, const char *argv[]){
#autoreleasepool{
NSMutableArray *employees = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++){
Employee *person = [[Employee alloc]init];
[person setWeightInKilos:90 + i];
[person setHeightInMeters:1.8 - i/10.00];
[person setEmployeeID:i];
[employees addObject:person];
}
.../*code continues from here, to assign [person]
's at random indexes in *employees, instances of the Asset class */
}
}
I was wondering what are the benefits or disadvantages to setting the [person] with one method, which in turn calls the other methods, like so:
main.m:
....
for (int i = 0; i < 10; i++){
Employee *person = [[Employee alloc]init];
[person setWeightInKilos:90 + i withAHeightOf:1.8 - i/10.00 andId:i];
[employees addObject:person];
}
....
Thanks.
Basically there isn't any right and wrong here, objective-c syntax and coding conventions allow you to have long messages with multiple parameters.
There are a couple of options here:
Setting these parameters on init (e.g. initWithId: height: weight:)
Creating a property for each of them
Creating an individual function for each of them
Creating a setProperties function
To decide this you should first ask yourself:
Does these triplets (Height, Weight, Id) belong together logically?
Does it make sense to set just one of them?
Does it makes sense that this object is missing these values?
Is there a need to make setting these parameters an atomic action?
Does Immutability of the object matters?
Most of the time I choose to make my object immutable, which means I create a readonly property for them, and set them via init function.
Your Person class has several properties including weightInKilos, heightInMeters, and employeeID.
You can, of course, set each property individually. As a convenience, you can provide special "helper" methods that make it easier to set several properties in one call. This is completely optional. Whether you choose to add these extra methods is strictly a matter of personal taste and style.
One consideration for such "helper" methods is where to draw the line. Which properties should be parameters to such methods? What happens if you later add another property? Do you update the "helper" methods to take another parameter and then update all code calling those methods?
In many cases it's better to just set each one individually. One guideline I use for deciding on whether to create such a "helper" method is if the object requires a certain set of properties to be set to be valid. If there is such a case then I usually create a special init method that takes the required properties as parameters. Then all of the optional ones can be set individually.
You neglected to show how you've defined the Employee object. Are weight, height and identification held as properties? If so, they generally will have accessor methods automatically generated for them so you will not need to write those routines. Properties have nice conveniences associated with them.
As to why you would use one method over another, the most compelling reason is a matter of personal style. Something to consider -- what happens if you choose to change the stored weight of a person; do you have a method to set only that parameter, or do you need to set everything about them?
It's common to have an initializer that receives the information to be initialized about an object, but something like - (id)initWithWeight:andHeight:andId:andSomethingElse:andMoreStuff: gets ugly far sooner than I've stretched it out. To solve this, the NSDictionary class can be helpful, where the dictionary contains all the fields you choose to include and the method becomes - (id)initUsingDictionary:(NSDictionary *)dictionary;. A nice benefit to this is you can easily make fields optional and a single method signature handles it.

An Array of Blocks?

This seems like a very strange interaction to me but at the same time it not only works but throws no warnings or errors in the process. Just looking to get some better understanding of blocks in general and why something like this could be right or wrong.
Is there any reason why something like this shouldn't be done?
NSArray *array = [NSArray arrayWithObjects:^{NSLog(#"Block 1");}, ^{NSLog(#"Block 2");}, ^{NSLog(#"Block 3");}, nil];
for (id block in array) {
[block invoke];
}
Putting Blocks into NSArrays is fine; they're objects. In fact, they inherit from NSObject.
You do need to copy, them, however. Those Blocks are created on the stack and need to be moved to the heap in order to live past the end of the current method. If you're using ARC, this is easy:
NSArray *array = [NSArray arrayWithObjects:[^{NSLog(#"Block 1");} copy], ...
Under MRR, you need to balance that copy, so you have two unpleasant options: use temps, or enumerate the array right after creating it and send release to all its members.
Sending invoke, on the other hand, isn't completely kosher, because that's a private method. The only fully-API-compliant way to invoke a Block is with function-call syntax:
typedef GenericBlock dispatch_block_t;
for( GenericBlock block in array ){
block();
}
Sure, that's fine. Why wouldn't it be fine?
In languages like JavaScript this technique is commonplace when registering event handlers.
object.clickHandlers.push(function() { doStuff() });
object.clickHandlers.push(function() { doMoreStuff() });
I see no reason that similar techniques couldn't be used with ObjC blocks, as they are real objects.
The more interesting question to me though, is if this pattern is the best choice for whatever your goal is. Which you haven't really told us.
Blocks in Objective-C are "first-class citizen" objects. Whatever you can do to a regular object, be it passing as a parameter, storing in an array or a dictionary, and so on, you can do it to block objects as well.
For example, an array of block objects may be useful to encode a sequence of actions that is not known at compile time; a dictionary of block objects keyed by strings could be useful in implementing a scripting language, and so on.
The best way to call a block retrieved from a collection is casting it to its proper type, and using the regular block invocation syntax on it.

Why create custom init when ivars/properties can be set from outside the instance?

I'm reading an Objective-C book and I have a question that the book doesn't seem to really answer.
Let's say I have two custom-made classes.
The first class is called ClassA. It has both the .h and .m files of course. The second class is called ClassB. It also has both .h and .m files.
Somewhere in the code, 'ClassA' has this method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
NSString *numberString = [myNumber storedNumberAsString];
// storedNumberAsString is just a method that returns a string object that holds
// myVariable.
[textView insertText:numberString];
//textView is a object I created that just displays some text on screen.
[myNumber release];
}
The book tells me that ClassB should have a method:
-(id)init {
[super init]; //I know why this is done, the book explains it well.
myVariable = 42; // I created this variable already in the ClassB .h file
return self;
}
Now, when in the Interface Builder I click the buttons I connected, etc. It works, the number displayed is 42.
My question is, why do I have to create an -(id)init method for ClassB, if I can do the following in ClassA's method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
myNumber.myVariable = 42; //I just do this to skip the -(id)init method.
NSString *numberString = [myNumber storedNumberAsString];
[textView insertText:numberString];
[myNumber release];
}
Doing this, it still displays the same value: 42. I can change it to whatever I like. So why not just use the init inherited from NSObject and just do the simple way myNumber.myVariable = 42?
Suppose that the value of the instance variable were something more complicated than an integer. Suppose it involved reading a string from a file, or getting some information over the network, or just doing some arithmetic. In that case, it wouldn't make sense to have ClassA be responsible for setting that value correctly. That would break the encapsulation that makes it useful to have separate classes in the first place.
In this extremely simple case, you're quite right, there may be no reason to have a custom initializer for ClassB, but in general, a class should itself be responsible for its state being set up correctly. Foisting that responsibility off on other classes means that those others need to know about the internals of the first, meaning the two may be too tightly coupled.
In some cases, the value of the ivar might be a piece of information that is known only to ClassA, or needs to be calculated based on such a piece of information. Then you should create a custom initializer for ClassB which receives that value, e.g., - (id) initWithInteger: This would become the "designated initializer", and you would then override -[ClassB init] to call it with some reasonable default value.
If instances of ClassB do not have to have anything initialized (other than to nil/zero), you do not need to create an explicit init method for ClassB. In this case the question is whether setting myVariable to 42 is ClassB's answer to life, the universe, and everything, or whether myVariable is just a field in ClassB that could be set to any value.
That is, the issue is conceptual, not of physical significance. If conceptually the value 42 "belongs" to ClassB, then there should be an init method for ClassB that sets it. If that specific value has more meaning to ClassA than to ClassB then some method of ClassA should set it. If you do it "wrong" the code still works fine, but your design is slightly less elegant, slightly less extendable, slightly less robust.
This is kind of a tricky issue. I was "brought up" to think that after a constructor (initializer) runs, the object should be ready to go. You should be able to safely call any method on it. Therefore, you need to set up any instance variables in the constructor for which 0 is not a valid value. I like to set them up if they have 0 values anyway, just for sanity, because I never want to bother to know the minute details of every language I work with, like whether they initialize instance variables to 0 automatically.
However, there are some arguments for not initializing some variables.
The initialization is complex, like loading a file or getting data from the network. You want to keep open the possibility of creating an instance and waiting until you're ready to do heavy weight operations.
There are quite a lot of instance variables that are configurable. Your options are to make a constructor with umpteen arguments, or make a constructor with no or a few arguments, and let the caller decide which values should be set to non-default values by property setters.
You need to set up a whole object graph before you can meaningfully initialize a value. That is, initializing the value might have side effects that depend on other related objects. The best solution is to construct each object, then use property setters to set the relationships between objects, then use property setters to initialize attribute values.

Memory cleanup on returned array from static method (objective-c)

In objective-c, I have a utility class with a bunch of static methods that I call for various tasks. As an example, I have one method that returns an NSArray that I allocate in the static method. If I set the NSArray to autorelease, then some time later, the NSArray in my calling method (that is assigned to the returned pointer) losses it's reference because the original form the static method is cleaned up. I can't release the NSArray object in the static method because it needs to be around for the return and assignment.
What is the right way to return an object (like the NSArray) from a static class, and have it hang around for the calling class, but then get cleaned up later when it is no longer needed?
Do I have to create the object first in the caller and pass in a pointer to the object and then return that same object form the static method?
I know this is a basic O-O problem, I just never had this issue in Java and I do not do much C/C++.
Thanks for your help.
Your autorelease is correct in the return just retain it when you call the static method.
NSArray *data = [[StaticClass getArray] retain];
If you have a property for the place your assigning the return value to, you can just do self.data = .. and the retain is automatic.
Please take the time to read over the rules. These apply to all of the frameworks you'll be using, and should apply to your code as well. Burn these into your head, and they'll become second nature. Thankfully, it's not complex, rather simple.
It's quite simple. If you do not own an object, it will go away at some indeterminate point in the future. In your case, the "indeterminate" point is when the autorelease pool gets drained, which in the normal case, is at the end of processing the current event.
If you want an object to hang around, you need to own it. The memory management rules referred to by jer will tell you exactly how you get ownership of an object. In this case, you need to retain the object. You must then, of course, release it later when you have done with it.
Regards your comment to Matt's answer. Your code is this:
for (NSString * date in dateList)
{
[historyList addObject:[[BIUtility historyForDate:date] retain]];
}
and
+ (NSArray *) historyForDate:(NSString *)date
{
NSMutableArray * ret = [[[NSMutableArray alloc] init] autorelease];
}
The first thing you need to know is that collections retain their members, so, in fact, your retain of the historyForDate is unnecessary. You don't want to own that object, historyList does. If it's disappearing, it's probably because historyList itself is being deallocated (because you don't own it) or is nil.
By the way, historyForDate: does nothing with the date. Is that correct?