Allocating a NSUInteger IndexBuffer - ios

I am trying to retrieve my NSIndexSet by calling -getIndexes:maxCount:indexRange
Here is my code
const NSUInteger arrayCount = picturesArray.count;
NSUInteger theIndexBuffer[arrayCount];
[picturesArray getIndexes:theIndexBuffer maxCount:arrayCount inIndexRange:nil];
However, in the debugger the IndexBuffer is always showing as -1. When I initialize it with a static number like NSUInteger theIndexBuffer[10], I get a proper instance.
This is probably because it doesnt know what arrayCount is at compile time.
What is the correct way of doing this?

You can dynamically allocate it using a pointer like this:
NSUInteger *theIndexBuffer = (NSUInteger *)calloc(picturesArray.count, sizeof(NSUInteger));
// Use your array however you were going to use it before
free(theIndexBuffer); // make sure you free the allocation
In C, even though this is a dynamically allocated buffer, you can use the array subscript operators and (for the most part) pretend that it's just an array. So, if you wanted to get the third element, you could write:
NSUInteger thirdElement = theIndexBuffer[2]; // arrays are 0-indexed
Just don't forget to free it when you're done.

I don't think you did anything wrong. It's valid in C99. You can double check by seeing if this evaluates as true:
sizeof(theIndexBuffer) == arrayCount * sizeof(NSUInteger)

Related

type casting in objective-c, (NSInteger) VS. integerValue

I don't very understand about the diference between (NSInteger)aNumberValue and [aNumberValue integerValue], then do some test. For example, here is a response data from server:
You can see it's an int but the value is hold by NSNumber. I retrieve the data by writting NSInteger count = (NSInteger) dic[#"count"];, and in Xcode debug area, saw this:
it's really a strange value but when I run po count and saw this:
anyway, the value is correct, but another strange thing is:
the number 2 is not less than 100!
Then I try NSInteger a = [dic[#"count"] integerValue] and saw the normal value in Xcode debug area:
and:
So, I am a little bit confused, what's the deference between (NSInteger)aNumberValue and [aNumberValue integerValue]?
NSNumber is a class; NSInteger is just a typedef of long, which is a primitive type.
dic[#"count"] is a pointer, which means that dic[#"count"] holds an address that points to the NSNumber instance. NSNumber has a method called integerValue which returns an NSInteger as the underlying value that the NSNumber instance represents. So you can conclude that [dic[#"count"] integerValue] gets you a long, and that's how you retrieve the value out of NSNumber.
You don't retrieve the value of NSNumber by casting it to NSInteger. That's because dic[#"count"], as I said, is a pointer. So by writing
NSInteger count = (NSInteger) dic[#"count"];
you are actually casting the pointer itself to an NSInteger, which has nothing to do with the actual represented value. The value 402008592 you see is just a decimal representation of the value of the pointer, which is an address.
The command po is used for printing objects, so lldb will actually try to print out the object at the address of count. That's why you get 2 back using po. You can try p count and you'll get 402008592.
About po count < 100: The expression (count < 100) is evaluated first; since count is really just an NSInteger of 402008592, it will evaluate to false.
The root issue is that Objective-C collection classes can only store Objective-C objects, not primitive types like float, int or NSInteger.
Therefore NSNumber provides a mechanism to store numbers and booleans in object form.
The value 402008592 looks like an address, so it's probably an NSNumber object containing an NSInteger value.
Don't get confused by the NS prefix of NSInteger and NSUInteger; they are still primitive types and not objects like NSNumber.

Write float values to Pointer Array of float in C# (unsafe or safe) using AVAudioPCMBuffer

While I'm not very comfortable using the unsafe context in C#, I do understand that I may have to sometimes use it.
To get right to it, in order to write byte values to an IntPtr, I could write the below from a safe context:
for (int i = 0; i < counter; i++)
{
System.Runtime.InteropServices.Marshal.WriteByte (data, i, 0);
}
How can i do the same from an unsafe context?
To be more specific I am actually trying to write float values to a an Intptr variable that is actually a float array pointer. I dont see any overloads capable of handling writing float data using System.Runtime.InteropServices from a safe context.
I tried the below but get the error:
malloc: *** error for object 0x17e9eca4: incorrect checksum for freed object - object was probably modified after being freed.
var data = (float*)buffer.FloatChannelData;
for (int i = 0; i < buffer.FrameLength; i++)
{
data [i] = 0.0f;
*data++ = 0.0f; // also tried this but got the same error
}
Your help is much appreciated.
Additional details:
I am trying to write data to AudioPCMBuffers in Xamarin.IOS. I thought the buffer contained a an array of float but as pointed by #Passant in the comments it actually contains an array of pointers to array of framelength floats. he same premise applies, whether from a safe or unsafe context I would like to be able to write data to the buffers. An example will be very helpful. Thanks and apologies for the confusion
Rolf's answer for the question is here:
Try this: https://gist.github.com/rolfbjarne/dc947383a6c9172bc664
It will mix mic input with a sine wave.

Nested NSArray filtering

I have the need to obtain the maximum value of a property of a collection of custom objects of the same class. The objects are stored in a NSArray, and the property happens to be another NSArray of numbers.
Let me explain in detail:
NSArray *samples; // of CMData, 4000 elements
CMData is a class that models a sample, for a specific moment in time, of a set of different channels that can have different values.
#interface CMData : NSObject
#property (nonatomic) NSUInteger timeStamp;
#property (nonatomic, strong) NSArray *analogChannelData; // of NSNumber, 128 elements
#end
(I have stripped other properties of the class not relevant to the question)
So for example, sample[1970] could be:
sample.timeStamp = 970800
sample.analogChannelData = <NSArray>
[
[0] = #(153.27)
[1] = #(345.35)
[2] = #(701.02)
...
[127] = #(-234.45)
]
Where each element [i] in the analogChannelData represents the value of that specific channel i for the timeStamp 970800
Now I want to obtain the maximum value for all the 4000 samples for channel 31. I use the following code:
NSUInteger channelIndex = 31;
NSMutableArray *values = [[NSMutableArray alloc] init]; // of NSNumber
// iterate the array of samples and for each one obtain the value for a
// specific channel and store the value in a new array
for (CMData *sample in samples) {
[values addObject:sample.analogChannelData[channelIndex]];
}
// the maximum
NSNumber *maxValue = [values valueForKeyPath:#"#max.self"];
I want to replace this programming structure by a filter through an NSPredcicate or use valueForKeyPath: to obtain the maximum of the data I need.
Anyone knows how to do this without a for loop? Just using NSPredicates and/or valueForKeyPath?
Thank you very much in advance for your help.
Update 1
Finally I benckmarked the for-loop version against the keyPath version (see accepted answer) and it runs much faster so it is better to go with a for loop.
Recalling some lessons from my algorithms classes, I implemented an even faster version that doesn't need an array to store the values. I just iterate over the selected channel and just choose the maximum in each iteration. This is by far the fastest version.
So:
version 1: for loop (see code above)
version 2: version with custom property (see selected answer from Marcus, update 2)
version 3: new code
Code for version 3:
NSUInteger channelIndex = 31;
NSNumber *maxValue = #(-INFINITY);
for (CMTData *sample in samples) {
NSNumber *value = sample.analogChannelData[channelIndex];
if (value) { // I allow the possibility of NSNull values in the NSArray
if ([value compare:maxValue] == NSOrderedDescending)
maxValue = value;
}
}
// the maximum is in maxValue at the end of the loop
Performance:
After 20.000 iterations in iOS simulator:
Version 1: 12.2722 sec.
Version 2: 21.0149 sec.
Version 3: 5.6501 sec.
The decision is clear. I'll use the third version.
Update 2
After some more research, it is clear to me now that KVC does not work for infividual elements in the inner array. See the following links: KVC with NSArrays of NSArrays and Collection Accessor Patterns for To-Many Properties
Anyway because I wanted to compute the maximum of the elements it is better to iterate the array than use some tricks to make KVC work.
You can solve this with using Key Value Coding and the collection operators.
NSNumber *result = [sample valueForKeyPath:#"#max.analogDataChannel"];
Update 1
As Arcanfel mentioned, you can join the arrays together:
NSNumber *result = [samples valueForKeyPath:#"#max.#unionOfArrays.#analogChannelData"];
I would suggest reading the documentation that we both linked to. There are some very powerful features in there.
Update 2
Further to HRD's answer, he has your solution, you need to combine his changes with KVC.
Add a propert to your CMData object for currentChannel. Then you can call
[samples setValue:#(channelIndex) forKey:#"currentChannel"];
Which will set it in every instance in the array. Then call:
[samples valueForKeyPath:#"#max.analogDataForCurrentChannel"];
Then you are done.
I have not tested out the code yet, but I think this is exactly what you are looking for:
[samples valueForKeyPath:#"#max.(#unionOfArrays.analogChannelData)"];
I guess you can also use #distinctUnionOfArray to remove duplicate values.
Here is the link to Apple Documentation that covers collection operators.
Hope this is helpful!
Cheers!
A suggestion for further exploration only
Offhand it is not clear you can do this as-is with a single KVC operator. What you might consider is adding two properties to your class: currentChannel, which sets/gets the current channel; and analogChannelDataForCurrentChannel, which is equivalent to analogChannelData[currentChannel]. Then you can:
samples.currentChannel = channelIndex;
... [samples valueForKeyPath:"#max.analogChannelDataForCurrentChannel"];
with any appropriate locking between the two calls if thread-safety is required (so one thread does not set currentChannel, then a second, and then the first do the KVC operator with the second's channel...).
HTH

Set NSDecimal to zero

What are the different ways of setting a NSDecimal to zero? I'm not keen on any of the 3 I found so far.
NSDecimal zero = {0}; // Not obvious what's going on here.
NSDecimal zero = #(0).decimalValue; // #(0) appears to always return the same instance.
NSDecimal zero = [NSDecimalNumber zero].decimalValue; // [NSDecimalNumber zero] appears to always return the same instance.
Is there one that is most accepted than others? Am I missing some kind of NSDecimalZero constant/function?
I have never noticed that NSDecimal doesn't have a nice Create function.
I can't imagine another method than the 3 you list.
NSDecimal zero = {0};
You are right, this is not obvious, this is actually very far from obvious. Usual programmers won't look up the documentation to see what value the struct will represent with all attributes set to zero.
NSDecimal zero = #(0).decimalValue
I don't like it because it uses NSNumber and needlessly creates an autoreleased object.
NSDecimal zero = [NSDecimalNumber zero].decimalValue
This is my preferred solution. Using NSDecimal structs directly is done mostly for performance boosts (without creating objects on the heap). This method matches the intent because it uses a singleton constant.
However, if you have a lot of code involving NSDecimal and performance is really important for you, create your own function/macro to initialize the struct and use this function everywhere. Then this problem won't matter to you because the function name will make the code obvious.
NSDecimal is a C struct which you are not supposed to look inside (you can but you shouldn't) so that rules out the first which is technically looking inside the struct.
Either of the second two are absolutely fine. Note that, in C, assigning to a struct copies all the fields, so although [NSDecimalNumber zero] always returns the same object, your NSDecimal will be a unique struct and changing its contents won't affect any other NSDecimal that has been "created" in the same way.
I guess you need to use NSDecimalNumber,
Typically we do as:
NSDecimalNumber *zeroDecimal = [[NSDecimalNumber alloc] initWithFloat:0.f];
NSDecimal zero = #(0).decimalValue; // #(0) appears to always return
the same instance.
NSDecimal zero = [NSDecimalNumber zero].decimalValue; //
[NSDecimalNumber zero] appears to always return the same instance.
Above two returns equivalent value of 0.0, first one is just the shorthand notation for the second one. You boxed 0 to NSDecimalNumber, using new syntax.
However, NSDecimal is typedefStruct that looks like this
typedef struct {
signed int _exponent:8;
unsigned int _length:4; // length == 0 && isNegative -> NaN
unsigned int _isNegative:1;
unsigned int _isCompact:1;
unsigned int _reserved:18;
unsigned short _mantissa[NSDecimalMaxSize];
} NSDecimal;

ios NSUinteger to type 'id'

My brain is failing me today. I know this has got to be a simple one, but I just don't see it.
CGFloat *minutes = [self.displayData objectForKey:index];
Incompatible integer to pointer conversion sending 'NSUInteger' (aka 'unsigned int') to parameter of type 'id'
index is a NSUInteger in a loop, (0 1 2 3 etc)
How do I get past this one? Thanks.
The dictionary waits for an object as the key (id) rather than a plain integer (NSUInteger).
Try wrapping the integer in a NSNumber object.
CGFloat *minutes = [self.displayData objectForKey:[NSNumber numberWithUnsignedInteger:index]];
The -objectForKey: method returns a value of type id, but you're trying to assign that to a CGFloat*, which isn't compatible with id because CGFloat isn't a class. If you know that the object you're retrieving from the dictionary is a certain type, say an NSNumber, you can take steps to convert it to a CGFloat when you get it.
Also, you're trying to use an int as a key into a dictionary, but dictionaries require their keys to be objects too. If you want to access your objects by index, store them in an array instead of a dictionary.
Putting it all together, you'd have something like this:
// after changing the displayData to an array
NSNumber *number = [self.displayData objectAtIndex:index];
CGFloat minutes = [number floatValue];
You should not be using a pointer like this:
CGFloat minutes = [self.displayData objectForKey:index];
Easy question. Just don't use NSUIntegrer. Instead of it, do the following:
id index;//then set the index

Resources