iOS function leaking memory - ios

I am creating a client socket using POSIX socket. Since this process needs an NSArray to use the data, I wrote the following two loops to convert an unsigned char array to an NSArray and vise versa. I checked the memory situation and noticed that memory usage increases slowly when running through these functions multiple times. Can anyone spot any potential memory leaks?
//read code run in background
NSMutableArray * arr = [[NSMutableArray alloc] init];
NSUInteger i = 0;
NSNumber *aUChar = 0;
for(;;)
{
n = read(sockfd,buffer,SOCKET_SIZE);
if (n > 0)
{
[arr removeAllObjects];
for (i = 0; i < n; i++)
{
aUChar = [NSNumber numberWithUnsignedChar:buffer[i]];
[arr addObject:aUChar];
}
//do sth with arr
}
}
//write code run in main thread when function called
int n=0;
unsigned char buffer[SOCKET_SIZE];
NSUInteger i = 0;
NSNumber *tmpnum;
NSArray *data_arr = [command.arguments objectAtIndex : 0];
for (i = 0; i < SOCKET_SIZE; i++)
{
tmpnum = [data_arr objectAtIndex:i];
buffer[i] = [tmpnum charValue];
}
n = write(sockfd,buffer,TCP_SOCKET_SIZE);

Related

How to reduce the set of colors in Objective-C

I'm very, very new to Objective-C (this is for a React Native app), and I am trying to pare down a list of colors and remove duplicates.
I've got this so far:
... code related to pulling pixels from an image
float flexibility = 2;
float range = 60;
NSMutableArray * colors = [NSMutableArray new];
float x = 0;
float y = 0;
for (int n = 0; n<(width*height); n++){
int index = (bytesPerRow * y) + x * bytesPerPixel;
int red = rawData[index];
int green = rawData[index + 1];
int blue = rawData[index + 2];
int alpha = rawData[index + 3];
NSArray * a = [NSArray arrayWithObjects:[NSString stringWithFormat:#"%i",red],[NSString stringWithFormat:#"%i",green],[NSString stringWithFormat:#"%i",blue],[NSString stringWithFormat:#"%i",alpha], nil];
[colors addObject:a];
y++;
if (y==height){
y=0;
x++;
}
}
free(rawData);
Now the script I am basing this off of has some code to pare down the list:
NSMutableDictionary * colourCounter = [NSMutableDictionary new];
//count the occurences in the array
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:colors];
for (NSString *item in countedSet) {
NSUInteger count = [countedSet countForObject:item];
[colourCounter setValue:[NSNumber numberWithInteger:count] forKey:item];
}
//sort keys highest occurrence to lowest
NSArray *orderedKeys = [colourCounter keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){
return [obj2 compare:obj1];
}];
//checks if the colour is similar to another one already included
NSMutableArray * ranges = [NSMutableArray new];
for (NSString * key in orderedKeys){
NSArray * rgb = [key componentsSeparatedByString:#","];
int r = [rgb[0] intValue];
int g = [rgb[1] intValue];
int b = [rgb[2] intValue];
bool exclude = false;
for (NSString * ranged_key in ranges){
NSArray * ranged_rgb = [ranged_key componentsSeparatedByString:#","];
int ranged_r = [ranged_rgb[0] intValue];
int ranged_g = [ranged_rgb[1] intValue];
int ranged_b = [ranged_rgb[2] intValue];
if (r>= ranged_r-range && r<= ranged_r+range){
if (g>= ranged_g-range && g<= ranged_g+range){
if (b>= ranged_b-range && b<= ranged_b+range){
exclude = true;
}
}
}
}
if (!exclude){ [ranges addObject:key]; }
}
//return ranges array here if you just want the ordered colours high to low
NSMutableArray * colourArray = [NSMutableArray new];
for (NSString * key in ranges){
NSArray * rgb = [key componentsSeparatedByString:#","];
float r = [rgb[0] floatValue];
float g = [rgb[1] floatValue];
float b = [rgb[2] floatValue];
UIColor * colour = [UIColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0f];
[colourArray addObject:colour];
}
//if you just want an array of images of most common to least, return here
//return [NSDictionary dictionaryWithObject:colourArray forKey:#"colours"];
I ultimately want to return this colourArray (the original library uses colour, I use color, so you'll sometimes see one or the other spelling - I'll probably standardize it to color when finished).
However, whenever I use this code, RN generates an error:
As far as I can tell, this is due to calling a function that doesn't exist? Is there something I am missing here, or calling incorrectly?

SIGABRT on sprintf

My code keep crashing (it's an old iOS app, without ARC). This is the code in question:
- (NSString *) dataToHex:(NSData *)data {
NSUInteger len2 = [data length] * 2;
unsigned char* chars = (unsigned char*) [data bytes];
char finalChar[len2 + 1];
for(int i = 0; i < len2; i++) {
sprintf(finalChar + (i * 2), "%02x", chars[i]);
}
finalChar[len2] = '\0';
NSString *hexString = [NSString stringWithFormat:#"%s", finalChar];
return hexString;
}
The crash is in the line of sprintf(). Any ideas? I've tried using bigger buffer sizes, but doesn't work.
It looks like this loop:
for(int i = 0; i < len2; i++) {
should be:
for(int i = 0; i < len; i++) {
(otherwise you're reading beyond the end of your input data and writing beyond the end of your output data).
In your case, the size of the finalChar array is len2 + 1. later, in the for loop, by saying
for(int i = 0; i < len2; i++) {
sprintf(finalChar + (i * 2), "%02x", chars[i]);
}
finalChar + (i * 2) will point to out of bound memory at some point (when i will be greater than len2/2) because, i is not limited to data length. Out of bound memory access cause undefined behavior.
I believe, it should be something like
for(int i = 0; i < len2/2 ; i++) {
sprintf(finalChar + (i * 2), "%02x", chars[i]);
}

Filling NSMutableArray from Json Response

I am trying to fill an array of points for graphing. Here is an example of the data returned:
(
{
precipIntensity = 0;
precipProbability = 0;
time = 1398123660;
},
{
precipIntensity = 0;
precipProbability = 0;
time = 1398123720;
},
{
precipIntensity = 0;
precipProbability = 0;
time = 1398123780;
})
I can access the individual values by using:
responseArray[i][#"precipProbability"]
where i is equal to the index.
I am trying to fill an array with these points but I can't seem to get it to work. Can someone help?
I have tried:
if (!responseArray || !responseArray.count){
} else {
for (int i=0; i > [responseArray count]; i++) {
ArrayOfValues[i] = responseArray[i][#"precipProbability"];
}
and
if (!responseArray || !responseArray.count){
} else {
for (int i=0; i > [responseArray count]; i++) {
[ArrayOfValues insertObject:responseArray[i][#"precipProbability"] atIndex:i];
}
and the ArrayOfValues is always empty (null).
Your for loop condition is backwards. You want:
if (!responseArray || !responseArray.count){
} else {
for (NSUInteger i = 0; i < [responseArray count]; i++) {
[ArrayOfValues addObject:responseArray[i][#"precipProbability"]];
}
Also note the proper data type for i.
it looks like your data is already in an array. if you'd like to copy them to a mutable array you can call
NSMutableArray *mut = [responseArray mutableCopy];
if your real goal is to parse the JSON objects into an Obj-C model object, you probably want to read up on <NSFastEnumeration>
How about this:
NSArray *array = [responseArray valueForKey:#"precipProbability"];

How to transform byte array in short array with Objective-C?

I'm developing a mobile application for iOS related to voice recording.
Due to that fact, I'm developing some different sound effects to modify recorded voice but I have a problem to implement some of them.
I'm trying to create echo/delay effect and I need to transform a byte array into a short array but I have no idea how to do it in Objective-C.
Thanks.
This is my current source code to implement it, but like byte is a very short type, when I apply attenuation (what must return a float value) produce an awful noise in my audio.
- (NSURL *)echo:(NSURL *)input output:(NSURL *)output{
int delay = 50000;
float attenuation = 0.5f;
NSMutableData *audioData = [NSMutableData dataWithContentsOfURL:input];
NSUInteger dataSize = [audioData length] - 44;
NSUInteger audioLength = [audioData length];
NSUInteger newAudioLength = audioLength + delay;
// Copy bytes
Byte *byteData = (Byte*)malloc(audioLength);
memcpy(byteData, [audioData bytes], audioLength);
short *shortData = (short*)malloc(audioLength/2);
// create a new array to store new modify data
Byte *newByteData = (Byte*)malloc(newAudioLength);
newByteData = byteData;
for (int i = 44; i < audioLength - delay; i++)
{
newByteData[i + delay] += byteData[i] * attenuation;
}
// Copy bytes in a new NSMutableData
NSMutableData *newAudioData = [NSMutableData dataWithBytes:newByteData length:newAudioLength];
// Store in a file
[newAudioData writeToFile:[output path] atomically:YES];
// Set WAV size
[[AudioUtils alloc] setAudioFileSize:output];
return output;
}
Finally, I could finish my echo effect implementing these four methods. I hope they will be useful for you.
Byte to short array
- (short *) byte2short:(Byte *)bytes size:(int)size resultSize:(int)resultSize{
short *shorts = (short *)malloc(sizeof(short)*resultSize);
for (int i=0; i < size/2; i++){
shorts[i] = (bytes[i*2+1] << 8) | bytes[i*2];
}
return shorts;
}
Short to byte array
- (Byte *) short2byte:(short *)shorts size:(int)size resultSize:(int)resultSize{
Byte *bytes = (Byte *)malloc(sizeof(Byte)*resultSize);
for (int i = 0; i < size; i++)
{
bytes[i * 2] = (Byte) (shorts[i] & 0x00FF);
bytes[(i * 2) + 1] = (Byte) (shorts[i] >> 8);
shorts[i] = 0;
}
return bytes;
}
Effect
- (NSMutableData *) effect:(NSMutableData *)data delay:(int)delay attenuation:(float)attenuation{
NSUInteger audioLength = [data length];
// Copy original data in a byte array
Byte *byteData = (Byte*)malloc(sizeof(Byte)*audioLength);
memcpy(byteData, [data bytes], audioLength);
short *shortData = (short*)malloc(sizeof(short)*(audioLength/2 + delay));
shortData = [self byte2short:byteData size:(int)audioLength resultSize:(int)audioLength/2 + delay];
// Array to store shorts
short *newShortData = shortData;
for (int i = 44; i < audioLength/2; i++)
{
newShortData[i + delay] += (short)((float)shortData[i] * attenuation);
}
Byte *newByteData = [self short2byte:newShortData size:(int)(audioLength/2 + delay) resultSize:(int)(audioLength + delay*2)];
// Copy bytes to a NSMutableData in order to create new file
NSMutableData *newAudioData = [NSMutableData dataWithBytes:newByteData length:(int)(audioLength + delay*2)];
return newAudioData;
}
Echo effect
- (NSURL *)echo:(NSURL *)input output:(NSURL *)output{
NSMutableData *audioData = [NSMutableData dataWithContentsOfURL:input];
// we call effect method that returns a NSMutableData and create a new file
[[self effect:audioData delay:6000 attenuation:0.5f] writeToFile:[output path] atomically:YES];
// We set file's size (is a method I have implemented)
[[AudioUtils alloc] setAudioFileSize:output];
return output;
}
There's no predefined function that will create a short array from a byte array, but it should be fairly simple to do it with a for loop
// create a short array
short *shortData = malloc(sizeof(short)*audioLength);
for (i=0; i<bytearray.length, i++)
{
shortData[i] = byteData[i];
}
The code is not rigorously correct (meaning I didn't compile it, just wrote it here on the fly), but it should give you an idea on how to do it.
Also be aware that saving audio data with two bytes instead of one can give very different results when playing back, but I'll assume you know how to handle with audio data for your specific purposes.

Non repeating random numbers in iOS? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Non repeating random numbers in Objective-C
How to generate non repeating random numbers?
I saw this on many sites but they give in main.c file code.
When I use the main.c file the code working is fine, but when I try to convert in to my.m file it is not working.
example:
I need to get all the numbers between 0-10 randomly.and the numbers should not repeat again.
srand(time(NULL));
int s[10];
BOOL fl = 1;
for (int i = 0; i<10; i++) {
while (fl) {
s[i] = rand()%10;
fl = 0;
for (int j = 0; j < i; j++) {
if (s[j] == s[i]) {fl = 1; j = i+1;}
}
}
}
int n = 10;
NSMutableArray *numbers = [NSMutableArray array];
for (int i = 0; i <= n; i++) {
[numbers addObject:[NSNumber numberWithInt:i]];
}
NSMutableArray *result = [NSMutableArray array];
while ([numbers count] > 0) {
int r = arc4random() % [numbers count];
NSNumber *randomElement = [numbers objectAtIndex:r];
[result addObject:randomElement];
[numbers removeObjectAtIndex:r];
}
NSLog(#"%#", result);
Hope the below lines of code will help you
srand(time(NULL));
int randomIndex = rand() % limit;
[reportIDTextField setText:[NSString stringWithFormat:#"%i", randomIndex]];
Benefit of this code is it won't allow repetitive random numbers. Here limit for random numbers.
Hope this is what you are looking for.
Enjoy Coding :)
NSMutableArray *storeArray = [[NSMutableArray alloc] init];
BOOL record = NO;
int x;
for (int i=0; [storeArray count] < 10; i++) //Loop for generate different random values
{
x = arc4random() % 10;//generating random number
if(i==0)//for first time
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
else
{
for (int j=0; j<= [storeArray count]-1; j++)
{
if (x ==[[storeArray objectAtIndex:j] intValue])
record = YES;
}
if (record == YES)
{
record = NO;
}
else
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
}
}
NSLog(#" Non Repeated Random Numbers : %#",storeArray);
can u try this code may be it's use full to you
Try this:-
This will produce numbers between 0 to 10 randomly.
srand(time(NULL));
int n = 11;
int card[n];
for (int y=0; y<n; y++) {
card[y] = y;
}
for(int q= 0 ;q<3;q++) {
for (int y=0; y<(n-1); y++) {
int r = y + (arc4random() % (n-y));
int temp = card[y]; card[y] = card[r]; card[r] = temp;
}
}
for (int g=0;g<n ; g++) {
int w = card[g];
NSLog(#"%i",w);
}
You can do something like this
number = (arc4random()%10)+1; //Generates Number from 1 to 10.
save it to an Array
Then you can put a condition,That will check the number whether it is present or not in the array.
if not then add it to the array ,if it is already present then simply discard it.
A NOTE: "Never, ever add or multiply random numbers in an attempt to get 'better' randomness
:)

Resources