Objective-c recursion, advanced recursive method construction - objective-c

I want to mimic NSDirectoryEnumerator with a simple recursive function, but my attempts so far have had my loops stopping prematurely.
The method needs to stop when there is no longer a directory or file present at an nth level.
How can I rearrange the method below to be a simple recursive function that will terminate accordingly?
Any help would be much appreciated. Thanks.
#import "MenuFromPathData.h"
#interface MenuFromPathData ()
#property (nonatomic,strong) NSFileManager *myFileManager;
#end
#implementation MenuFromPathData
#synthesize myFileManager=_myFileManager;
#define ROOT_DIRECTORY #"TextData"
//
////
//
- (void) simpleMenuArrayBuilder
{
NSArray *fileNamesLevel1 = [self fullArrayReturn:ROOT_DIRECTORY];
for(int i = 0; i < [fileNamesLevel1 count]; i++)
{
NSString *pathNameLevel2 = [NSString stringWithFormat:#"%#/%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i]];
NSArray *fileNamesLevel2 = [self fullArrayReturn:pathNameLevel2];
for(int j = 0; j < [fileNamesLevel2 count]; j++)
{
NSString *pathNameLevel3 = [NSString stringWithFormat:#"%#/%#/%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i],[fileNamesLevel2 objectAtIndex:j] ];
NSArray *fileNamesLevel3 = [self fullArrayReturn:pathNameLevel3];
for(int k = 0; k < [fileNamesLevel3 count]; k++)
{
NSString *pathNameLevel4 = [NSString stringWithFormat:#"%#/%#/%#/%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i],[fileNamesLevel2 objectAtIndex:j],[fileNamesLevel3 objectAtIndex:k] ];
NSArray *fileNamesLevel4 = [self fullArrayReturn:pathNameLevel4];
for(int l = 0; l < [fileNamesLevel4 count]; l++)
{
NSString *pathNameLevel5 = [NSString stringWithFormat:#"%#/%#/%#/%#/%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i],[fileNamesLevel2 objectAtIndex:j],[fileNamesLevel3 objectAtIndex:k],[fileNamesLevel4 objectAtIndex:l] ];
NSArray *fileNamesLevel5 = [self fullArrayReturn:pathNameLevel5];
for(int m = 0; m < [fileNamesLevel5 count]; m++)
{
NSString *pathNameLevel6 = [NSString stringWithFormat:#"%#/%#/%#/%#/%#/%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i],[fileNamesLevel2 objectAtIndex:j],[fileNamesLevel3 objectAtIndex:k],[fileNamesLevel4 objectAtIndex:l], [fileNamesLevel5 objectAtIndex:m] ];
NSArray *fileNamesLevel6 = [self fullArrayReturn:pathNameLevel6];
NSLog(#"-- LVL 6.0 %# -- ",pathNameLevel6);
for(int n = 0; n < [fileNamesLevel6 count]; n++)
{
NSString *pathNameLevel7 = [NSString stringWithFormat:#"%#/%#/%#/%#/%#/%#%#",ROOT_DIRECTORY,[fileNamesLevel1 objectAtIndex:i],[fileNamesLevel2 objectAtIndex:j],[fileNamesLevel3 objectAtIndex:k],[fileNamesLevel4 objectAtIndex:l], [fileNamesLevel5 objectAtIndex:m],[fileNamesLevel6 objectAtIndex:n] ];
NSArray *fileNamesLevel7 = [self fullArrayReturn:pathNameLevel7];
NSLog(#"-- LVL 7.0 %# -- ",pathNameLevel7);
}
}
}
}
}
}
}
//
////
//
- (NSString*) resourcePath : (NSString*) pathName {
return [[NSBundle mainBundle] pathForResource:pathName ofType:nil];
}
- (NSArray*) bundleArrayReturn : (NSString*)pathForResource {
NSError* error;
return [self.myFileManager contentsOfDirectoryAtPath:pathForResource error:&error];
}
- (NSArray*) fullArrayReturn : (NSString*) pathName {
return [self bundleArrayReturn:[self resourcePath: pathName]];
}
//
////
//
- (NSFileManager*) myFileManager {
if(!_myFileManager) {
_myFileManager = [NSFileManager defaultManager];
}
return _myFileManager;
}
#end

Something like this should work. Only trick is to add another parameter to your method to track current depth during the recursion.
- (void) simpleMenuArrayBuilderForPath:(NSString*)pathToDecend allowedDepth:(int)depth
{
// if we've defended far enough, then stop
if(depth == 0) return;
// otherwise, get the next directory listing at this level
NSArray *fileNamesNextLevel = [self fullArrayReturn:pathToDecend];
for(int i = 0; i < [fileNamesNextLevel count]; i++)
{
// find each path inside the directory we're looking at
NSString *nextLevelPathName = [pathToDecend stringByAppendingPathComponent:[fileNamesNextLevel objectAtIndex:i]];
// process it however you want...
NSLog(#"Looking at %#", nextLevelPathName);
// and recur into it
[self simpleMenuArrayBuilderForPath:nextLevelPathName allowedDepth:depth-1];
}
}
then, call it by:
[self simpleMenuArrayBuilderForPath:ROOT_DIRECTORY allowedDepth:5];

Related

EXC_BAD_ACCESS Error for type NSString

I'm new to this mac application development.
The app is working fine for some data and the app crashes for few entries.
-(void)presentClientsss
{
[productVendorTextField setStringValue:[NSString stringWithFormat:#"%#", [[popUpVendor selectedItem] title]]];
NSMenuItem *tempMenuItem = [popUpVendor selectedItem];
NSString *selectedItemTitle = [tempMenuItem title];
for (int k = 0; k < [appDelegate.vendorInfoArr count]; k++)
{
VendorInfo *tempCustomerInfoModel = [appDelegate.vendorInfoArr objectAtIndex:k];
if ([tempCustomerInfoModel.vendorName isEqualToString:selectedItemTitle])
{
oldVendorIde = [NSString stringWithFormat:#"%ld", tempCustomerInfoModel.rowId];
NSLog(#"Selected RowID = %#",oldVendorIde);
break;
}
}
}
I'm sending the oldVendorIdestring to next method.
- (ItemModel *)itemNodelWithAttributes {
isProductIdExist = NO;
if ([senderInfo isEqualToString:#"nP"]) {
for (int i = 0; i < [appDelegate.itemsArr count]; i++) {
ItemModel *tempIM = [appDelegate.itemsArr objectAtIndex:i];
if ([tempIM.productId isEqualToString:[[productIdTextField stringValue] uppercaseString]]) {
isProductIdExist = YES;
break;
}
}
}
if ([senderInfo isEqualToString:#"eP"]) {
for (int i = 0; i < [appDelegate.itemsArr count]; i++) {
ItemModel *tempIM = [appDelegate.itemsArr objectAtIndex:i];
if (tempIM.itemId == itemIdentity) {
if ([tempIM.productId isEqualToString:[[productIdTextField stringValue] uppercaseString]]) {
isProductIdExist = NO;
}
}
else if ([tempIM.productId isEqualToString:[[productIdTextField stringValue] uppercaseString]]) {
isProductIdExist = YES;
}
}
}
int tempItemExists = [self saveProductImage:[[productIdTextField stringValue] uppercaseString]];
NSLog(#"oldVendorIde =%#",oldVendorIde);
ItemModel *iM = [[ItemModel alloc] initWithItemId:itemIdentity defaultItemMinimumValue:[productMinValueTextField floatValue] staticItemPrice:[productPriceTextField doubleValue] dynamicItemQuantity:[productCurrentStockTextField doubleValue] staticItemDescription:[productDescriptionTextField stringValue] prodId:[[productIdTextField stringValue] uppercaseString] itemVendor:oldVendorIde itemImgExists:tempItemExists stockAvailable:0 itemNotes:[notesTextField string] BarcodeDesc:[BarcodeDescTextView stringValue]];
return iM;
}
In this method the same oldVendorIde is working fine for some data and some time it gets crashed at this point.
The oldVendorIde sometime doesnot get any value in itemNodelWithAttributes method and the app crashes at that point.
Can Sone help me to solve the issue.. Thanks in advance..
The text from a UITextField is accessed through the text property ([productIdTextField text]), not through stringValue.

getting NCFString error while searching the tableview using searchbar

i ve got a table view parsed from json string.everthing works good .if i m to type a character in my search bar i m getting this error '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x1d52ac50'below is the code.were the below variable name data is NSMutableArray.could u guys help me out.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controllershouldReloadTableForSearchString:(NSString *)searchString
{
[searchData removeAllObjects];
NSArray *group;
for(group in nameData)
{
NSLog(#"wat am i doing here:%#",group);
NSMutableArray *newGroup = [[NSMutableArray alloc] init];
NSString *element;
for(element in group)
{
NSRange range = [element rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (range.length > 0) {
[newGroup addObject:element];
}
}
if ([newGroup count] > 0) {
[searchData addObject:newGroup];
}
}
return YES;
}
Please check out this code
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
NSMutableArray *array=[[NSMutableArray alloc]init];
NSDictionary *naming= [self.friendsDictionary objectForKey:#"data"];
NSLog(#"ggg %#",[self.friendsDictionary objectForKey:#"data"]);
for(int i =0 ; i< [[self.friendsDictionary objectForKey:#"data"] count]; i++){
[array addObject:[[[self.friendsDictionary objectForKey:#"data"] objectAtIndex:i] objectForKey:#"name"]];
}
NSLog(#"Array %#", array);
if(self.searchDisplayController.searchBar.text.length>0)
{
NSString *strSearchText = self.searchDisplayController.searchBar.text;
NSMutableArray *group = [[NSMutableArray alloc]init];
for (int i=0; i<array.count; i++) {
NSString *strData = [array objectAtIndex:i];
NSLog(#"string Data:%#",strData);
NSRange rng = [strData rangeOfString:strSearchText options:NSCaseInsensitiveSearch];
if(rng.location != NSNotFound)
{
if(rng.location== 0)//that is we are checking only the start of the names.
{
[group addObject:strData];
}
}
}
if ([group count] > 0)
{
searchData = [[NSMutableArray alloc] init];
[searchData addObjectsFromArray:group];
NSLog(#"Sear %#", searchData);
}
}
return YES;
}

Print a line 10 times in Objective-C?

I know that print line is NSLog. How do I print a line 10 times in Objective-C?
I haven't had a chance to refactor yet, but something like this should work!
for(int i = 0; i < 10; i++)
{
if(i == 0)
NSLog(#"A line");
else if (i == 1)
NSLog(#"A line");
else if (i == 2)
NSLog(#"A line");
else if (i == 3)
NSLog(#"A line");
else if (i == 4)
NSLog(#"A line");
else if (i == 5)
NSLog(#"A line");
else if (i == 6)
NSLog(#"A line");
else if (i == 7)
NSLog(#"A line");
else if (i == 8)
NSLog(#"A line");
else if (i == 9)
NSLog(#"A line");
}
Another while loop option.
//
// main.m
// Pritner
//
// Created by Joshua Caswell on 7/19/12.
//
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
// A Pritner instance holds and displays a passed-in string. The string is publicly
// unchangeable.
#interface Pritner : NSObject
+ (id)pritnerWithLine: (NSString *)newLine;
- (void)printLine;
#property (readonly, copy, nonatomic) NSString * line;
#end
// Extension to manage "class variable" for counting number of created instances
#interface Pritner ()
+ (NSUInteger)numPritnersCreated;
+ (void)setNumPritnersCreated:(NSUInteger)n;
+ (NSUInteger)maxNumPritners;
#property (readwrite, copy, nonatomic) NSString * line;
- (id)initWithLine: (NSString *)line;
#end
#implementation Pritner
#synthesize line;
+ (id)pritnerWithLine: (NSString *)newLine {
id newInstance = [[self alloc] initWithLine:newLine];
if( newInstance ){
NSUInteger createdSoFar = [self numPritnersCreated];
// Only allow maxNumPritners to ever be created; keeping track of them
// is the client's problem.
if( createdSoFar >= [self maxNumPritners] ){
abort();
}
[self setNumPritnersCreated:createdSoFar + 1];
}
return newInstance;
}
// Fake class variable using associated objects; keep count of created instances
char numPritnerKey;
+ (NSUInteger)numPritnersCreated {
NSNumber * n = objc_getAssociatedObject(self, &numPritnerKey);
if( !n ){
n = [NSNumber numberWithUnsignedInteger:0];
[self setNumPritnersCreated:0];
}
return [n unsignedIntegerValue];
}
+ (void)setNumPritnersCreated:(NSUInteger)n {
objc_setAssociatedObject(self,
&numPritnerKey,
[NSNumber numberWithUnsignedInteger:n],
OBJC_ASSOCIATION_RETAIN);
}
// Maximum number of instances ever allowed to be created
+ (NSUInteger)maxNumPritners {
return 10;
}
- (id)initWithLine: (NSString *)newLine {
self = [super init];
if( !self ) return nil;
line = [newLine copy];
return self;
}
- (void)printLine {
NSLog(#"%#", [self line]);
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
while( YES ){
Pritner * p = [Pritner pritnerWithLine:#"I figure, if you're going to build a time machine out of a car, why not do it with some style?"];
[p printLine];
}
}
return 0;
}
Please don't use this in real life.
Don't forget the "object" in "Objective-C".
NSArray *lines = [#"123456789" componentsSeparatedByCharactersInSet:[NSCharacterSet alphanumericCharacterSet]];
[lines enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL* stop) {
NSLog(#"a line");
}];
If you think Objective-C isn't true enough to its Smalltalk roots, you can do something like the following.
typedef void (^LoopBlock)(NSNumber*);
#interface NSNumber (loop)
-(void)to:(NSNumber*)upTo do:(LoopBlock)block;
-(void)timesRepeat:(LoopBlock)block;
#end
#implementation NSNumber (loop)
static NSString *loopSeparator = #"_";
-(void)to:(NSNumber*)upTo do:(LoopBlock)block {
[ [ [#"" stringByPaddingToLength:[upTo unsignedIntegerValue]-[self unsignedIntegerValue]
withString:loopSeparator
startingAtIndex:0
] componentsSeparatedByString:loopSeparator
] enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL* stop) {
block([NSNumber numberWithUnsignedInteger:i+[self unsignedIntegerValue]]);
}
];
}
-(void)timesRepeat:(LoopBlock)block {
[[NSNumber numberWithUnsignedInteger: 1] to:self do:block];
}
#end
int main() {
#autoreleasepool {
[[NSNumber numberWithInt:10]
timesRepeat:^(NSNumber* i){
NSLog(#"a line");
}];
}
}
Use recursion:
print(10);
void print(int i){
if(i == 0)
return;
NSLog(#"print this line");
print(i - 1);
}
Use Grand Central Dispatch another way:
dispatch_apply(10, dispatch_get_main_queue(), ^(size_t curr_iteration){
NSLog(#"a line");
});
Use a goto statement:
int i = 0;
print:
NSLog(#"print this line");
if (i++ < 10) goto print;
Use a for loop:
for (int i = 0; i < 10; i++) {
NSLog(#"print this line");
}
Use Grand Central Dispatch:
__block int i = 0;
__block dispatch_block_t print_block = ^() {
NSLog(#"print this line");
i += 1;
if (i < 10) dispatch_sync(dispatch_get_main_queue(), print_block);
}
dispatch_sync(dispatch_get_main_queue(), print_block);
Use a while loop:
int i = 0;
while (i < 10) {
NSLog(#"print this line");
i += 1;
}

Problem with the duplicate values picking from Address book in Iphone sdk

Here I had a problem that I am adding contact from the address book and checking it whether it is already in the favourites list or not.If not I am adding the contact to favourite list.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
ContactDTO* dtoObject = [[ContactDTO alloc] init];
ABRecordID personId = ABRecordGetRecordID(person);
NSString* personIdStr = [NSString stringWithFormat:#"%d", personId];
dtoObject.contactId = personIdStr;
NSString *lastNameString, *firstNameString;
firstNameString = [self getValueForProperty:kABPersonFirstNameProperty forContact:personIdStr];
lastNameString = [self getValueForProperty:kABPersonLastNameProperty forContact:personIdStr];
dtoObject.firstName = firstNameString;
dtoObject.lastName = lastNameString;
printf("\n *****************firstNameString %s",[firstNameString UTF8String]);
//ABMultiValueRef emailMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonEmailProperty) autorelease];
ABMultiValueRef phoneMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonPhoneProperty) autorelease];
if (ABMultiValueGetCount(phoneMultiValue) > 0)
{
ABMultiValueRef phoneMultiValue =[(NSString *)ABRecordCopyValue(person, kABPersonPhoneProperty) autorelease];
NSString* curentTypeLabel =[(NSString *)ABMultiValueCopyLabelAtIndex(phoneMultiValue,identifier) autorelease];
curentTypeLabel = [curentTypeLabel stringByReplacingOccurrencesOfString:#"_$!<" withString:#""];
curentTypeLabel = [curentTypeLabel stringByReplacingOccurrencesOfString:#">!$_" withString:#""];
dtoObject.numberType = curentTypeLabel;
NSString* currentPhone = [(NSString *)ABMultiValueCopyValueAtIndex(phoneMultiValue,identifier) autorelease];
dtoObject.mobNumber = currentPhone;
FavoritesAppDelegate* appDelegate = (FavoritesAppDelegate*) [[UIApplication sharedApplication] delegate];
if ([favoritesArray count] > 0)
{
for (int i=0; i< [favoritesArray count]; i++)
{
ContactDTO* dtoObject1 = [favoritesArray objectAtIndex:i];
printf("\n dtoObject1.contactId value = %s, Main value = %s",[dtoObject.firstName UTF8String],[dtoObject1.firstName UTF8String]);
printf("\n dtoObject1.mobNumber value = %s, Main mobNumber value = %s",[dtoObject1.mobNumber UTF8String],[dtoObject.mobNumber UTF8String]);
if ([dtoObject.firstName isEqualToString:dtoObject1.firstName])
{
printf("\n inside if....");
}
else
{
[appDelegate addContactToFavorites:dtoObject];
break;
printf("\n inside else....");
}
}
}
else
{
[appDelegate addContactToFavorites:dtoObject];
}
[self dismissModalViewControllerAnimated:YES];
}
/*else if(ABMultiValueGetCount(emailMultiValue) > 0)
{
NSString* currentEmail =(NSString *)ABMultiValueCopyValueAtIndex(emailMultiValue,identifier);
printf("\n *************currentEmail** %s",[currentEmail UTF8String]);
[self emailBtnAction:currentEmail];
}*/
[dtoObject release];
return NO;
}
For that the code I written was shown as above.
Eventhough I am getting the duplicate values the condition is failed and duplicate values are added.
Can anyone give suggestions to get rid of this?
Anyone's help will be much appreciated.
Thanks to all,
Monish.
You are adding to favorites array if the new contact doesn't match ONE of the existing items in the favorites array. But the new contact could be in the favorites array further along in the array. You need to check if the new contact doesn't match ALL of the existing favorites.
Also, shouldn't the match condition be more than just checking first names?
Something like this:
BOOL contactAlreadyExists = NO;
for (int i=0; i< [favoritesArray count]; i++)
{
ContactDTO* dtoObject1 = [favoritesArray objectAtIndex:i];
if ([dtoObject.firstName isEqualToString:dtoObject1.firstName])
{
contactAlreadyExists = YES;
break;
}
}
if (!contactAlreadyExists)
{
[appDelegate addContactToFavorites:dtoObject];
}

Problem with NSMutableArray and custom NSObject

I'm really desperate on this one. I'm trying to make a Framework which you can search and play YouTube videos with. But while testing it, I'm running in to a big problem.
In the search operation I'm adding YTVideos (a subclass of NSObject) to a NSMutableArray. When I loop thru it in the main(), I'm getting nil-objects:
Method
- (NSArray *)videosInRange:(NSRange)range {
if(range.length > 50) {
[NSException raise:#"Range lenth > 50"
format:#"The range of -videosInRange: can't be bigger than 50"];
return nil;
}
if((range.location + range.length) > 999) {
[NSException raise:#"Range to big"
format:#"The given range was to big (%d, %d)", range.location, range.length];
return nil;
}
NSString *searchURLString = [[self feedURL] absoluteString];
searchURLString = [searchURLString stringBySettingURLAttribute:#"start-index" value:[NSString stringWithFormat:#"%d",range.location + 1]];
searchURLString = [searchURLString stringBySettingURLAttribute:#"max-results" value:[NSString stringWithFormat:#"%d",range.length]];
NSLog(#"%#",searchURLString);
NSURL *url = [NSURL URLWithString:searchURLString];
NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:url
options:0
error:NULL];
if(!xmlDoc)
return nil;
NSArray *videoElements = [[xmlDoc rootElement] elementsForName:#"entry"];
NSMutableArray *videos = [[NSMutableArray alloc] initWithCapacity:[videoElements count]];
register int i;
for(i = 0; i < [videoElements count]; i++) {
NSAutoreleasePool *addPool = [[NSAutoreleasePool alloc] init];
YTVideo *vid = [[YTVideo alloc] initWithXMLElement:[videoElements objectAtIndex:i]];
[videos addObject:vid];
[vid release];
[addPool drain];
}
NSArray *retValue = [NSArray arrayWithArray:videos];
[videos release];
return retValue;
}
main()
int main(int argc, const char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
YTSearchFeed *feed = [[YTSearchFeed alloc] initWithSearch:#"Eminem"];
long long results = [feed videoCount];
NSLog(#"%lld videos for search", results);
long long i = 0;
while(results != 0) {
int length = (results >= 50) ? (50) : (results);
NSArray *videos = [feed videosInRange:NSMakeRange(i, length)];
NSLog(#"L: %d", [videos count]);
int z;
for(z = 0; z < [videos count]; z++, i++) {
YTVideo *vid = [videos objectAtIndex:z];
NSString *title = [vid title];
NSLog(#"%d: %#", i+1, title);
}
results -= length;
}
[pool drain];
return NSApplicationMain(argc, argv);
}
I hope someone can take the time to look at this, and if you need anymore information, just ask.
Thank you in advance,
ief2
EDIT: YTVideo
- (id)initWithXMLElement:(NSXMLElement *)element {
self = [super init];
if(self != nil) {
_XMLElement = [element copy];
}
return self;
}
- (NSString *)title {
if(!_title) {
NSString *str = [[[self XMLElement] firstElementWithName:#"title"] stringValue];
_title = [[str stringByDecodingHTMLEntities] retain];
}
return [[_title copy] autorelease];
}
I get the title (and other video information) only when it's requested. the -stringByDecodingHTMLEntities works fine (Category on NSString).
I've rewritten the code and initialized all instance variables in the -initmethod