dispatch_async doesn't go into loop - objective-c

I need to fill in array. I have two methods. First of this create object that need to be added to array. I do it like this:
__block NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:inputArray.count];
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{
dispatch_apply(inputArray.count,queue , ^(size_t index) {
[array insertObject:[self getObject:[inputArray objectAtIndex:index]] atIndex:index];
});
});
Finally I receive array with 2 objects instead of 100. I need to get array with objects that processed in getObject function.
If i code this:
dispatch_apply(inputArray.count, queue, ^(size_t index){
[array insertObject:[self getObject:[inputArray objectAtIndex:index]] atIndex:index];
});
I receive different numbers of array count. Can anybody tell me how to do it correctly?

The method initWithCapacity does not create an array with that many elements, it is just a hint to NSMutableArray on what the number of elements is likely to be. When you then try to insert an object at a specific instances things go wrong. From the docs for insertObject:atIndex::
Note that NSArray objects are not like C arrays. That is, even though you specify a size when you create an array, the specified size is regarded as a “hint”; the actual size of the array is still 0. This means that you cannot insert an object at an index greater than the current count of an array. For example, if an array contains two objects, its size is 2, so you can add objects at indices 0, 1, or 2. Index 3 is illegal and out of bounds; if you try to add an object at index 3 (when the size of the array is 2), NSMutableArray raises an exception.
You'll get different behaviour depending on the order the blocks queued by dispatch_apply are executed.
I'm assuming you are doing this as your getObject: is a time consuming process but multiple of them may be performed in parallel. If that is the case then:
a) After allocating the array pre-fill it up with cheap objects, e.g. [NSNull null] will do.
b) Use replaceObjectAtIndex:withObject: to add your objects to the array, this will replace your pre-filled object with your real ones.
Note: You are also misusing __block. This attribute is for when you wish to change the value of a local variable in the enclosing method from within a block. You never change the value of array either in the method or the block after you assign a reference to an NSMutableArray instance to it when it is declared. Your code then modifies the contents of the referenced object, not the value of the reference. Remove the __block.
HTH

Related

NSMutableArray will not return/keep a sequence of NSNumbers

I would like, every time this function is called, that the NSMutableArray "sequence" to return the numbers already in the sequence, plus another random one from 0 to 3 at the end. This is the function I have so far:
Edit
I tried calling initialising this function from inside didMoveToView and it now returns a sequence.
This code works now:
-(NSMutableArray *)extendSequence {
int newItem = arc4random_uniform(4);
NSNumber* newItemAsNumber = [NSNumber numberWithInteger:newItem];
[sequence addObject:newItemAsNumber];
NSLog(#"%#", sequence);
return sequence;
}
(I am not sure where/if I could insert the NSMutableArray *sequence = [NSMutableArray alloc] init]]; statement yet, because when I tried earlier, it wiped the sequence each time it was called.)
How could I achieve this?
A random sequence could return to be something like e.g. "1", then "1,3" then "1,3,0" etc.
Thank you in advance.
Sounds like you are a little unclear on where you are keeping track of the "state" of what the sequence is so far. It sounds like you have an instance variable called "sequence" on this object somewhere (otherwise what you are writing now wouldn't compile). This is a reasonable place to keep track of this set of numbers, which will exist throughout the object's lifecycle, but adding to it each time the -sequence method is called.
You should add the initialization line for the array to your object's -init method. That way it is initialized just once with the object.
(The reason the current code returns nil is that you're never initializing the array, so the "additions" to it have no effect. The reason your other version, where you initialize within that method, kept wiping out the contents, is simply that you were creating and returning a fresh array every single time, which would replace the one you'd created the last time.)

Changing NSMutableArray size in objective-c

I was looking around and couldn't find anything, and I'm starting to think it's not possible with objective-c.
I have a NSMutableArray *myMutableArray and the size varies depending on what csv file is loaded. Since I do not set a size of myMutableArray I can't do:
if (c == 5){
myMutableArray[q] = [[NSNumber numberWithFloat:myOtherArray] stringValue];
q = q + 1;
c = 0;
}
Else {
c = c + 1;
}
Since myMutableArray is technically of size nil I guess I can't add objects to it.
In cases, q can be between 1500 and 2500.
My question is, how do I make `myMutableArray' change size on every loop.
If this isn't possible, I guess I will have to make myMutableArray very large - but I need the values in myMutableArray for a graph. If I do myMutableArray = [[NSMutableArray alloc] initWithCapacity:5000]; and don't use the 5000 memory locations, will these locations be nil, or 0? (sorry if the technical words are wrong, by memory locations I mean the memory given to myMutableArray)
Thank you, if there is anything else I can add to this please feel free to let me know.
EDIT: What I'm trying to achieve is adding data to the array, and with that data create a graph
You can't have a sporadically populated array. Creating an array with capacity 5000 is just a hint as to how much data you might be going to store into the array. Consider using an array of dictionaries where the dictionary contains the q value (presumably one coordinate) and the associated value. You can then sort the array based on the q values if you need to (for plotting). Then you can just add the dictionaries to the array as usual (addObject:).
The NSMutableArray class declares the programmatic interface to objects that manage a modifiable array of objects. This class adds insertion and deletion operations to the basic array-handling behavior inherited from NSArray.
If you
arrayWithCapacity:
Creates and returns an NSMutableArray object with enough allocated memory to initially hold a given number of objects.
Mutable arrays expand as needed. When declaring them, we can init them like this:
+ (instancetype)arrayWithCapacity:(NSUInteger)numItems
Here numItems simply establishes the object’s initial capacity.
Later to add more data, i.e. to expand mutable array, use this
addObject:
What it does is, it inserts a given object at the end of the mutable array.
- (void)addObject:(id)anObject
It's important to note that:
The object to add to the end of the array's content. This value must not be nil. It raises an NSInvalidArgumentException if anObject is nil.

Sorting objective-C array: where does 'element' come from?

I'm reading a book on Objective-C. A part dealing with sorting arrays in an Addressbook. The sort method is like this:
- (void) sort
{
[book sortUsingSelector: #selector(compareNames:);
}
The 'compareNames' method is like this:
//Compare the two names from the specified address cards
-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]];
}
I kinda can see how it works. By comparing each element of the array to the next until all the 'names' are swapped in alphabetical order.
What I don't get (as it hasn't been mentioned earlier) is where the '(id) element' argument comes from? The 'name' I get cause that's been initialized earlier. But where does 'element' come from? Is that a fixed object that comes with NSArray? Earlier is described how to print an element by e.g. NSLogging nummer[1]. In case of this address book one element or card in that book could be printed by NSLogging book[32]. But how does 'element' fit in that?
The 'name' I get cause that's been initialized earlier.
I'm not sure you understand how this works. The method corresponding to the sorting selector must compare two objects that are members of the array. No "static" objects, no ahead-of-time-initialized stuff, nothing.
This method will be called on an object in the array, and its argument will be another object in the array, to which it should compare the first object (its self argument). The implementation of sortUsingSelector: uses the return value of this method to decide if two objects are in the right order. Internally, it is called like this:
id oneObject = array[firstIndex];
id otherObject = array[secondIndex];
NSComparisonResult cmpRes =
[oneObject performSelector:#selector(comparisonSelector)
withObject:otherObject];
if (cmpRes == NSOrderedDescending) {
// swap the objects if they're in the wrong order
}
Maybe the asymmetry is confusing; in principle, NSArray could as well use a freestanding function that takes two objects and returns the comparison result. Actually, there indeed is a method (sortUsingComparator:) that takes a block which isn't called "on an object" (since it's not a method), but it's simply called with two arguments: the two objects to compare.
It's pretty simple. The sorting algorithm is based on object-comparison. Let's say we have 3 objects in the array: [A, B, C].
Then the method compareNames: is called on the following objects:
[A compareNames:B]
[B compareNames:C]
[A compareNames:C]
The element is just some other object in the array.

Filling NSMutableArray for later use in obj-c

How do you fill a NSMutableArray with a set capacity for later use?
Basically I want to set up a NSMutableArray to act as a map for my game objects, so I have this line...
gameObjects = [[NSMutableArray alloc] initWithCapacity:mapWidth*mapHeight];
Which I had hoped would create and fill my MutableArray so I can get then access it with this kind of index...
int ii = (cellY*mapWidth)+cellX;
NSDictionary *currentObject = [gameObjects objectAtIndex:ii];
But I just learned initWithCapacity doesn't fill the array, so should I create blank objects to fill it with, or is there a Null that I can fill it with? Also would I do that with 2 for loops or is there an instruction something like "initWith:myObject" ?
I want to be able to check at a certain index within the array to see if there's an object there or not, so I need to be able to acces that index point, and I can only do that if there's something there or I get an out of bounds error.
I'll be using this NSMutableArray pretty much as a grid of objects, it's a 1 dimensional array organised as a 2 dimensional array, so I need to be able to fill it with mapWidth*mapHeight of something, and then calculate the index and do a check on that index within the array.
I've looked on here and googled but couldn't find anything like what I'm asking.
Thanks for any advice.
I think what you are looking for is [NSNull null]. It is exactly what you want- a placeholder value.
You can find more information on the topic in this question.
initWithCapacity is just a performance optimization -- it has no effect on the array behavior, it just keeps the code "under the covers" from having to repeatedly enlarge the internal array as you add more entries.
So if you want a "pre-allocated" array, you'd need to fill it with NSNull objects or some such. You can then use isKindOfClass to tell if the object is the right type, or simply == compare the entry to [NSNull null]. (Since there's only ever one NSNull object it always has the same address).
(Or you could use a C-style array of pointers with nil values for empty slots.)
But you might be better off using an NSMutableDictionary instead -- no need to pre-fill, and if the element isn't there you get a nil pointer back. For keys use a NSNumber object that corresponds to what would have been your array index.
initWithCapacity only hints to NSMutableArray that it should support this many objects. It won't actually have any objects in it until you add them. Besides, every entry in the array is a pointer to an object, not a struct like you'd normally have in a standard c array.
You need to change how you're thinking about the problem. If you don't add an object to the array, it's not in there. So either you pre-fill the array with "empty" objects as you've said, which is weird. Or you can add the objects as you need them.

NSNumbers being added as values to NSMutableDictionary become nulls

I have a piece of code that constructs a dictionary of objects as keys and operation codes (like add/update/remove) as values.
Recently, either with iOS 6, or with the arrival of "zee Germans", it broke. Values are constructed, and occasionally added, but most of the time I get a dictionary full of (null) values.
for (int i = 0; i < newArray.count; i++)
{
if (![oldArray containsObject:[newArray objectAtIndex:i]])
{
NSNumber *opNumber = [NSNumber numberWithInt:(int)kInsertOperation];
[_operationsForRows setObject:opNumber forKey:[newArray objectAtIndex:i]];
}
else ...
}
I've already decorated the code with intermediate variables and explicit casting of enum value to int, and grew even more confused. Printing out the resulting dictionary gives:
{
"<Order: 0x8aad980>" = (null);
"<Order: 0x8aad7a0>" = (null);
}
Can anyone explain, what am I missing here? The dictionary shouldn't even be able to hold nulls, should it?
This code is under ARC.
NSMutableDictionary was initialized on the main thread, but used exclusively on a single secondary thread.
Sometimes, an object or two would be added correctly. Say, 10%. What I've tried since:
I've moved dictionary initialization to the same thread as usage. Wow, 90-95% of objects are added correctly, but still a null here and there.
I've saved all possible NSNumbers in class fields. With both dictionary and numbers created on main thread, 0% success rate, lower than I started with.
Using current-thread-initialized dictionary and main-thread numbers in class fields, I get to 90-95% again...
Cry, cry... Looks like a rewrite of the whole place.
Try using NSMutableDictionary instead of NSDictionary.
The difference between the two being that you can modify NSMutableDictionary after initialisation whereas NSDictionary is set.