Better way to handle arrays in Objective-C? - iphone

Please let me preface this question with an apology. I am very new to Objective C. Unfortunately, I have a very tight timeline on a project for work and need to get up to speed as fast as possible.
The code below works. I am just wondering if there is a better way to handle this... Maybe something more Cocoa-ish. The entire purpose of the function is to get an ordered list of positions in a string that have a certain value.
I fell back on a standard array for comfort reasons. The NSMutableString that I initially declare is only for testing purposes. Being a complete noob to this language and still wrapping my head around the way Objective C (and C++ I guess) handles variables and pointers, any and all hints, tips, pointers would be appreciated.
NSMutableString *mut = [[NSMutableString alloc] initWithString:#"This is a test of the emergency broadcast system. This is only a test."];
NSMutableArray *tList = [NSMutableArray arrayWithArray:[mut componentsSeparatedByString:#" "]];
int dump[(tList.count-1)];
int dpCount=0;
NSUInteger length = [mut length];
NSRange myRange = NSMakeRange(0, length);
while (myRange.location != NSNotFound) {
myRange = [mut rangeOfString:#" " options: 0 range:myRange];
if (myRange.location != NSNotFound) {
dump[dpCount]=myRange.location;
++dpCount;
myRange = NSMakeRange((myRange.location+myRange.length), (length - (myRange.location+myRange.length)));
}
}
for (int i=0; i < dpCount; ++i) {
//Going to do something with these values in the future... they MUST be in order.
NSLog(#"Dumping positions in order: %i",dump[i]);
}
text2.text = mut;
[mut release];
Thanks again for any replies.

There is not great way to do what you are trying to do. Here is one way:
// locations will be an NSArray of NSNumbers --
// each NSNumber containing one location of the substring):
NSMutableArray *locations = [NSMutableArray new];
NSRange searchRange = NSMakeRange(0,string.length);
NSRange foundRange;
while (searchRange.location < string.length) {
searchRange.length = string.length-searchRange.location;
foundRange = [string rangeOfString:substring options:nil range:searchRange];
if(foundRange.location == NSNotFound) break;
[locations addObject:[NSNumber numberWithInt:searchRange.location]];
searchRange.location = foundRange.location+foundRange.length;
}

This might be a little more streamlined (and faster in terms of execution time, if that matters):
const char *p = "This is a test of the emergency broadcast system. This is only a test.";
NSMutableArray *positions = [NSMutableArray array];
for (int i = 0; *p; p++, i++)
{
if (*p == ' ') {
[positions addObject:[NSNumber numberWithInt:i]];
}
}
for (int j = 0; j < [positions count]; j++) {
NSLog(#"position %d: %#", j + 1, [positions objectAtIndex:j]);
}

Related

hex a to binary

i am trying to convert my hex value to binary value , but i am facing little problem .
as i am new trying to learn my faults .
my code :
NSMutableString *str;
NSString *dd = #"192:168:1:2:0B:2:D:00";
NSCharacterSet *donotwant1 = [NSCharacterSet characterSetWithCharactersInString:#":""];
dd =[[dd componentsSeparatedByCharactersInSet:donotwant1] componentsJoinedByString:#" "];
NSMutableArray *array = [[dd componentsSeparatedByString:#" "] mutableCopy];
[array removeObjectAtIndex:0];
//NSLog(#"%#",array);
for (int j=0; j<[array count]; j++) {
NSScanner *scan = [NSScanner scannerWithString:[array objectAtIndex:j]];
unsigned int i=0;
if ([scan scanHexInt:&i]) {
// NSLog(#"numbner is %ustr", i);
}
NSInteger theNumber = i;
str = [NSMutableString string];
for(NSInteger numberCopy = theNumber; numberCopy > 0; numberCopy >>= 1) {
// Prepend "0" or "1", depending on the bit
[str insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
[array removeObjectAtIndex:j];
[array insertObject:str atIndex:j];
}
}
NSLog(#"Binary version: %#", array);
I'm getting
1,1100,11001111,1111,1111,11101111.....
in my code 0 values are eliminated . i want 8bits like(00000001,00001100.....) can any one tell me the reason
When the most significant bit is reached, your algorithm stops the conversion. Why not force the loop to always execute 8 times?
for (int numberCopy = theNumber, int i = 0; i < 8; numberCopy >>= 1, i++) {
// loop body here
}
By the way, here's a cleaner/shorter/simpler approach that doesn't involve highly superfluous copying and uses characters instead of string objects for hyper efficiency (just kidding, I'm all against micro-optimizations, but I feel like inserting an NSString before another one is unnecessary, especially if the number of bits is known and constant). This also assumes UTF-8 and exploits the fact that hexadecimal and binary representation have a very nice relationship, 16 being the 4th power of 2:
NSString *dd = #"01:0C:CF:0F:EF:AF:BD:00";
NSArray *bytes = [dd componentsSeparatedByString:#":"];
NSMutableArray *binaries = [NSMutableArray array];
NSString *lookup[256];
lookup['0'] = #"0000";
lookup['1'] = #"0001";
lookup['2'] = #"0010";
lookup['3'] = #"0011";
lookup['4'] = #"0100";
lookup['5'] = #"0101";
lookup['6'] = #"0110";
lookup['7'] = #"0111";
lookup['8'] = #"1000";
lookup['9'] = #"1001";
lookup['A'] = #"1010";
lookup['B'] = #"1011";
lookup['C'] = #"1100";
lookup['D'] = #"1101";
lookup['E'] = #"1110";
lookup['F'] = #"1111";
for (NSString *s in bytes) {
unichar n1 = [s characterAtIndex:0];
unichar n0 = [s characterAtIndex:1];
[binaries addObject:[lookup[n1] stringByAppendingString:lookup[n0]]];
}
NSLog(#"%#", binaries);

iOS Search Results Order

I have a UISearchBar that searches a table of data. When a search is typed in, the results are displayed in an order like so:
Starts typing 'ch...'
1. Ache
2. Cherries
3. Choice
It makes more sense to me (and for my app) that 'Cherries' and 'Choice' would be at the top of the results, because 'ch' and not 'ach' was typed in. Is this something that can be changed programatically, or is it just the way iOS searches work?
You have to give the search option as NSAnchoredSearch
NSRange searchRange = [sortedString rangeOfString:searchText options:NSAnchoredSearch];
Some of the search method listed below
NSCaseInsensitiveSearch
NSLiteralSearch
NSBackwardsSearch
NSAnchoredSearch
NSNumericSearch
NSDiacriticInsensitiveSearch
NSWidthInsensitiveSearch
NSForcedOrderingSearch
NSRegularExpressionSearch
Eg:
- (void)search {
NSString *searchText = [searchBar.text lowercaseString];
for (int index = 0; index < [availableCollectionArray count]; index++) {
NSArray *tempArray = [availableCollectionArray objectAtIndex:index];
for (int tempIndex = 0; tempIndex < [tempArray count] ; tempIndex++) {
NSString *sortedString = [tempArray objectAtIndex:tempIndex];
NSRange searchRange = [sortedString rangeOfString:searchText options:NSAnchoredSearch];
if (searchRange.length > 0)
{
[sortedArray addObject: sortedString]; //add the string which starts from searchBar.text
}
}
}
}

How to sort an array with alphanumeric values?

I have an array which contains strings like frame_10#3x.png , frame_5#3x.png,frame_19#3x.png etc.
So I want to sort this array according to the number after the underscore i.e. the correct sequence will be frame_5#3x.png,frame_10#3x.png,frame_19#3x.png.
I tried to use the following method but no result:
NSInteger firstNumSort(id str1, id str2, void *context) {
int num1 = [str1 integerValue];
int num2 = [str2 integerValue];
if (num1 < num2)
return NSOrderedAscending;
else if (num1 > num2)
return NSOrderedDescending;
return NSOrderedSame;
}
Please suggest how to do this sorting for array.
NSArray *sry_img = [[NSArray alloc] initWithObjects:#"frame_18#3x.png",#"frame_17#3x.png",#"frame_1222#3x.png",#"frame_10#3x.png",#"frame_3#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",#"frame_1#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",nil];
NSArray *sortedStrings = [sry_img sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
NSLog(#"%#",sortedStrings);
Enjy .......
But
localizedStandardCompare:, added in 10.6, should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method may be tweaked in future releases, and will be different under different localizations, so clients should not depend on the exact sorting order of the strings.
you want to do something like:
NSArray *components1 = [str1 componentsSeparatedByString:#"_"];
NSArray *components2 = [str2 componentsSeparatedByString:#"_"];
NSString *number1String = [components1 objectAtIndex:([components1 count] - 1])];
NSString *number2String = [components2 objectAtIndex:([components2 count] - 1])];
return [number1String compare:number2String];
I am not sure if my solution is the best possible approach but it can solve your problem for the time being :) .
1) First I have written a function to get the numbers before # character in your string and then I implemented simple SELECTION SORT algo to sort the array using this functions.
- (NSString*)getSubStringForString:(NSString*)value {
// First we will cut the frame_ string
NSMutableString *trimmedString = [NSMutableString stringWithString:[value substringWithRange:NSMakeRange(6, [value length]-6)]];
// New String to contain the numbers
NSMutableString *newString = [[NSMutableString alloc] init];
for (int i = 0; i < [trimmedString length] ; i++) {
NSString *singleChar = [trimmedString substringWithRange:NSMakeRange(i, 1)];
if (![singleChar isEqualToString:#"#"]) {
[newString appendString:singleChar];
} else {
break;
}
}
return newString;
}
This is the selection Implementation of the algo for sorting. The main logic is in the for loop. You can copy the code in viewDidLoad method to test.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"frame_10#3x.png",#"frame_5#3x.png",
#"frame_3#3x.png", #"frame_19#3x.png",
nil];
NSLog(#"Values before Sort: %#", array);
int iPos;
int iMin;
for (iPos = 0; iPos < [array count]; iPos++)
{
iMin = iPos;
for (int i = iPos+1; i < [array count]; i++)
{
if ([[self getSubStringForString:[array objectAtIndex:i]] intValue] >
[[self getSubStringForString:[array objectAtIndex:iMin]] intValue]) {
iMin = i;
}
}
if ( iMin != iPos )
{
NSString *tempValue = [array objectAtIndex:iPos];
[array replaceObjectAtIndex:iPos withObject:[array objectAtIndex:iMin]];
[array replaceObjectAtIndex:iMin withObject:tempValue];
}
}
NSLog(#"Sorted Values: %#", array);
I hope that it can atleast keep you going. :)
You can try this-
NSString *str1 = [[[[str1 componentsSeparatedByString:#"frame_"] objectAtIndex:1] componentsSeparatedByString:#"#3x.png"] objectAtIndex:0];
int num1 = [str1 integerValue];

split NSArray in groups of smaller NSArrays for paging

I have an NSArray of say 100 NSManagedObjects and I need to split that into an NSArray that contains 10 NSArray objects that each hold 10 of theses NSManagedObjects, how would I accomplish that?
I am going to do some paging and this will work well for me.
How are you getting these NSManagedObjects? If you're using an NSFetchRequest, you may want to keep that around and only get 10 results at a time from it.
Here is my code:
[object splitArrayWithArray:arrayWith100Objects rangeNumber:10];
- (NSArray*) splitArrayWithArray:(NSArray*)rawArray rangeNumber:(int)rangeNumber{
int totalCount = rawArray.count;
int currentIndex = 0;
NSMutableArray* splitArray = [NSMutableArray array];
while (currentIndex<totalCount) {
NSRange range = NSMakeRange(currentIndex, MIN(rangeNumber, totalCount-currentIndex));
NSArray* subArray = [rawArray subarrayWithRange:range];
[splitArray addObject:subArray];
currentIndex +=rangeNumber;
}
return splitArray;
}
Something along these lines should work instead of breaking it into separate arrays
//make a new range for each page
NSRange myRange = NSMakeRange(10, 10);
NSArray * myArray = [NSArray array];
//...pass both into a function
for (int i = myRange.location; i < myRange.location + myRange.length; i++) {
//stuff with the array elements
[[myArray objectAtIndex:i] doSomething];
}
It's no one-liner, but this will split an array into pages:
NSArray *arrayToSplit = ...
int pageSize = 50;
NSMutableArray *arrayOfPages = [NSMutableArray new];
NSRange range = NSMakeRange(0, pageSize);
while (range.location < arrayToSplit.count) {
if (range.location + range.length >= arrayToSplit.count)
range.length = arrayToSplit.count - range.location;
[arrayOfPages addObject:[arrayToSplit objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range]]];
range.location += range.length;
}

How to count '\n' in an UITextView

I got a headache trying to count returns (\n) in my UITextView. As you'll soon realise, I'm a bloody beginner and here is my theory of what I've come up with, but there are many gaps...
- (IBAction)countReturns:(id)sender {
int returns;
while ((textView = getchar()) != endOfString [if there is such a thing?])
{
if (textView = getchar()) == '\n') {
returns++;
}
}
NSString *newText = [[NSString alloc] initWithFormat:#"Number of returns: %d", returns];
numberReturns.text = newText;
[newText release];
}
I checked other questions on here, but people are usually (in my eyes) lost in some details which I don't understand. Any help would be very much appreciated! Thanks for your patience.
You can simply
UITextView *theview; //remove this line, and change future theview to your veiw
NSString *thestring; //for storing a string from your view
int returnint = 0;
thestring = [NSString stringWithFormat:#"%#",[theview text]];
for (int temp = 0; temp < [thestring length]; temp++){ //run through the string
if ([thestring characterAtIndex: temp] == '\n')
returnint++;
}
NSArray *newlines = [textView.text componentsSeparatedByString:#"\n"];
int returns = ([newlines count]-1)
Should work. Keep in mind this isn't such a great idea if you have a gia-normous string, but it's quick, dirty and easy to implement.
there are a lot of ways to do that. Here is one:
NSString *str = #"FooBar\n\nBaz...\n\nABC\n";
NSString *tmpStr = [str stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSInteger count = [str length] - [tmpStr length];
NSLog(#"Count: %d", count);