What is the best way to update elements into an observable array? - mobx

I see two options:
#1 observable_array.replace() ?
or
#2 observable_array=[ ] ?
Any suggestion will be appreciated?

You should favor the first according to the documentation
The problem with overriding the array is that you will lose the observable property if you don't override the observable array with a new observable array.
In the end, when setting an observable array, mobx observes changes for each entry of the array, not changes on the array object itself.

Related

How to reorder MKMapView annotations array

I'd like to reorder the array of annotations shown on a map in order to create a next/prev button for quickly cycling through all annotations (sorted by date) using a simple iterator.
As far as I see the annotations array used as a store [worldmap annotations] is not mutable and therefore I cannot reorder it. I tried the following to create a temporary copy of the annotations array, sort it by date and re-attach it.
(worldmap is my MKMapView object)
//COPY
NSMutableArray *annotationSort = [[NSMutableArray alloc]initWithArray:[worldmap annotations]];
//SORT
[annotationSort sortedArrayUsingComparator:^NSComparisonResult(EventPin* obj1, EventPin* obj2) {
return [obj1.eventItemObject.eventDateBegin compare: obj2.eventItemObject.eventDateBegin];
}];
//ADDED SORTED ARRAY
[worldmap removeAnnotations:[worldmap annotations]];
[worldmap addAnnotations:annotationSort];
This doesn't seem to work. Any idea how can I reorder the MKMapKit annotations array?
As the answer in the linked question mentions, there is no guarantee that the map view's annotations property will preserve any order.
In addition, since the annotations property includes the userLocation if you have showsUserLocation turned on (but which you don't yourself explicitly call addAnnotation for), the annotation order will not be what you may expect.
Don't rely on the order of the annotations in the map view's annotations array.
Instead, keep your own array of references to the annotations and sort them any way you want (like your annotationSort array).
But there's no point in removing them from the map and adding them back.
Keep in mind that the map view's annotations array may contain the MKUserLocation annotation so when constructing your array, check the type of each annotation before including it or accessing custom properties.
However, note that the code to sort the array:
[annotationSort sortedArrayUsingComparator:...
is flawed itself because sortedArrayUsingComparator returns an NSArray.
It does not sort the array in-place.
Instead, to sort an NSMutableArray, call its sortUsingComparator method.
Using this sorted array, your app can access or select the annotations in the order desired.

Parent class of my array

I have an object which contains an array.
Without coredate or a database, how do I model the relationship back to the parent from any of the children. Do I have to explicitly store the parent id in the child? Or is there a way to get the "parent" class of this array?
Objective-C (unlike Qt and a few other object models) has no "parent-child" or "ownership" relationship. Yes, sometimes we say that the object that retains an object "owns" it, but that's more of a shared ownership, since multiple objects can retain a given object, but none of the "owners" is more "distinguished" than the others and hence (in the plain Objective-C model) the "parent".
The first thing to consider is whether your "parent/child" concept really makes sense in this multiple-owner environment. If so, then you need to maintain the child-to-parent pointers yourself, somehow.
Without subclassing NSArray and adding an extra property, which I think is a bad idea, I guess you have two choices:
Make the object at index 0 a pointer to your containing object
Don't store your array directly in your "parent" object, store it in a NSDictionary which also has a #parent key, holding a reference to the parent.
To be honest I'm not sure what you are trying to achieve here - when would you need to find out this information that wouldn't be better done by simply working with the parent object itself?
UPDATE
I've just seen this answer to a separate question: Create Custom UIButton class
Associative references sound like they could be what you need? You can associate a reference to your containing object to the NSArray. I don't know anything else about them, though, I just saw that answer and thought of this question.
NSArray * array = [[NSArray alloc]init];
id parrent = [array super];

addEntriesFromDictionary: a true copy method?

I am trying to understand exactly what is going on with this method, as noted in the Apple docs:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/Reference/Reference.html
If I create an NSMutableDicationary and use addEntriesFromDictionary: to fill it, can I do anything I want to this mutable dictionary without affecting the original immutable dictionary from where these items came?
The original dictionary will not be modified. However, if the keys or values of the original dictionary are themselves mutable in some way (e.g. they're instances of UIView or NSMutableArray) and you modify them, the changes will be reflected in the original dictionary.
To avoid that, make a deep copy of the original dictionary before adding it to the new dictionary:
NSDictionary *deepCopy = [[NSDictionary alloc] initWithDictionary: original copyItems: YES];
if (deepCopy) {
[destination addEntriesFromDictionary: deepCopy];
[deepCopy release];
}
Yes, modifications you make to the new dictionary will not affect the old one. Any changes you make to the objects inside the dictionary will affect those inside the original dictionary, though. They are the same same objects, after all. As the documentation says:
Each value object from otherDictionary is sent a retain message before being added to the receiving dictionary. In contrast, each key object is copied ... and the copy is added to the receiving dictionary.
You can check for yourself by logging the addresses of the keys and values. My guess is that it copies the keys, as is the standard NSDictionary behavior, and simply retains the values. You can mutate the dictionary (which comprises just the key->value mappings) all you want, but if you mutate the objects that are its values, you'll be mutating those objects everywhere.
EDIT: Logging a test case as suggested indeed shows that is the behavior. The copied key will in fact be the same as the original key for the common case of an immutable string key.

How to implement the NSFastEnumeration protocol?

I have a class and I want my class to confirm to the NSFastEnumeration Protocol. I've read the documentation but it's not really clear. Can someone please tell me what the protocol method should return and how it works?
Apple's FastEnumerationSample shows you what to do, but here's a breakdown.
The sole NSFastEnumeration method, countByEnumeratingWithState:objects:count:, returns chunks of the collection. It's executed whenever more items are needed, until it indicates that there are no more items by returning 0. A chunk is passed as a C array of ids.
Within the method, the state parameter holds most (if not all) of the data you'll be using. You'll need to set state->itemsPtr and update state->state with each separate invocation of countByEnumeratingWithState:objects:count:. Here's a brief description of each field of NSFastEnumerationState:
state: represents the position in the sequence being iterated over. For indexed collections, this would be the index. For linked lists, this could be a node pointer. For other types, this could be a more complex type (e.g. for a tree, state->state could be an NSMutableArray used as a stack to store nodes). When countByEnumeratingWithState:objects:count: is first called, state->state is 0; check for this condition to initialize the state struct.
itemsPtr: the items in the chunk; points to a C array of ids. Cocoa will loop over this array, binding each item in turn to the variable named in the for-in loop.
mutationsPtr: for mutable collections, used to indicate that the collection has changed since the last call to countByEnumeratingWithState:objects:count:. Typically, you'd set this once when initializing the state. Collection mutators increment the value that this points to. Cocoa will compare the value returned by countByEnumeratingWithState:objects:count: to the value from the previous invocation; if they're different, Cocoa will throw an exception.
extra: you can use this to store extra data.
You can set state->state and any element of state->extra to whatever you wish; they're provided solely for your convenience, and do not affect Cocoa. state->itemsPtr, *state->mutationsPtr and the value returned by the method, however, do affect Cocoa.
As for the two other method parameters, stackbuf is an array that Cocoa provides to hold items. Its use is optional, but if you don't use it, you'll have to allocate storage space for state->itemPtr. If you use it, set state->itemsPtr to stackbuf with each invocation. len is the length of stackbuf, the maximum number of items that you'll be able to store in it.
Further reading:
Friday Q&A 2010-04-16: Implementing Fast Enumeration (mikeash.com)
Implementing countByEnumeratingWithState:objects:count: (Cocoa with Love)
NSFastEnumeration Protocol Reference
Implementing NSFastEnumerator on Custom Class (SO)
Just reviving this thread after finding an excellent explanation. The Apple link seems to be broken. You can try here: https://developer.apple.com/library/ios/#samplecode/FastEnumerationSample/Introduction/Intro.html
The best example for implementing fast enumeration that I've found is at: http://mikeash.com/pyblog/friday-qa-2010-04-16-implementing-fast-enumeration.html. It looks much worse than it is.

Change a value within a NSMutableArray

I have a NSMutableArray that is loaded with values.
Later in the application, I need to change the values of one of the elements in the array.
How do I accomplish this?
thanks
tony
Take a look at the class reference instance methods:
http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSMutableArray_Class/Reference/Reference.html
You can use:
replaceObjectAtIndex:withObject: given you know the index of the object.
replaceObjectsAtIndexes:withObjects: to replace multiple objects at once.
Call -[NSMutableArray replaceObjectAtIndex:withObject:]. Or, if the object in the array is mutable, just grab it with -objectAtIndex: and modify its properties directly.
You would probably want to use 'replaceObjectAtIndex:withObject:' for replacing the object itself.
refer following link. It may help you
http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/instm/NSMutableArray/replaceObjectAtIndex:withObject:
From that you can use replaceObjectAtIndex:withObject: or
replaceObjectsAtIndexes:withObjects: for replacing objects.
just you have to know the index of objects.