Question

I have experience with Java and Android development, and am now attempting to learn Objective-C and iPhone/iPad development. In order to help teach myself, I am re-writing an application I made for android over to iPhone.

The specific problem I am having has to do with using the NSScanner class. In my android application, I read in a txt file(with multiple lines) and built "member" objects that get loaded into an array. Each member has general contact info being a first name, last name, phone number, email, pledge class and major. This text file was written by me so I know the exact formatting. Below is an example of one line in the text file.

Fawzy   Jake    8144425471  someemail@gmail.com Beta    Criminal Justice & Psych Minor

In Java/android I was able to load the desired results by using multiple scan.Next() and then a scan.nextLine() for the major. Can anyone help point me in the right direction of how to use NSScanner/objective-c to perform a similar operation? Specifically, I would like to know how to properly scan through the text file/string, then build my member object with the information I grabbed from the string.

Below is an example of my code that I have been working on, but am having trouble putting what I want to do logically into syntax as I am not familiar with objective-c.

- (NSString *)loadFileToString{
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"akpsi_contact_list"
                                                     ofType:@"txt"];
NSError *error = nil;
NSString *fileContent = [NSString stringWithContentsOfFile:filePath
                                                  encoding:NSUTF8StringEncoding
                                                     error:&error];
if(error)
{
    NSLog(@"ERROR while loading from file: %@", error);
}
return fileContent;
}

-(void)readFileString{
NSScanner *scanner = [NSScanner scannerWithString: self.loadFileToString];
while ([scanner isAtEnd] == NO) {

    //member object
    AKPsiMember *member;

    //temporary variables
    NSString *thisFirstName;
    NSString *thisLastName;
    NSString *thisPhoneNum;
    NSString *thisEmail;
    NSString *thisPledge;
    NSString *thisMajor;

    //scan one line, save 
    [scanner scanUpToString:@" " intoString:&thisFirstName];
    [scanner scanUpToString:@" " intoString:&thisLastName];
    [scanner scanUpToString:@" " intoString:&thisPhoneNum];
    [scanner scanUpToString:@" " intoString:&thisEmail];
    [scanner scanUpToString:@" " intoString:&thisPledge];
    [scanner scanUpToString:@" " intoString:&thisMajor];
    //build member object with temporary variables
    // implementation must continue to next line...
}    

}

Also my member object/class

.h

@interface AKPsiMember : NSObject{
NSString *firstName;
NSString *lastName;
NSString *emailAddress;
NSString *pledgeClass;
NSString *major;
NSString *phoneNum;


}

@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSString *emailAddress;
@property (nonatomic, strong) NSString *pledgeClass;
@property (nonatomic, strong) NSString *major;
@property (nonatomic, strong) NSString *phoneNum;


@end

And my .m

@implementation AKPsiMember

@synthesize firstName = _firstName;
@synthesize lastName = _lastName;
@synthesize phoneNum = _phoneNum;
@synthesize emailAddress = _emailAddress;
@synthesize pledgeClass = _pledgeClass;
@synthesize major = _major;

- (NSString *)phoneNum:(NSNumber *)num
{
if(num == 0)
{
    NSString *temp1 = [self.phoneNum substringWithRange:NSMakeRange(0, 3)];
    NSString *temp2 = [self.phoneNum substringWithRange:NSMakeRange(3, 6)];
    NSString *temp3 = [self.phoneNum substringWithRange:NSMakeRange(6, 9)];

    NSString *formatNum = [NSString stringWithFormat: @"(%@) %@-%@", temp1, temp2, temp3];
    return formatNum;
}
else{
    return self.phoneNum;
}
}

@end
Was it helpful?

Solution

After you scanned all your fields you should scan the newline character in order to proceed to the next line:

NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
[scanner scanUpToCharactersFromSet:whitespace intoString:&thisFirstName];
[scanner scanCharactersFromSet:whitespace intoString:nil];        
[scanner scanUpToCharactersFromSet:whitespace intoString:&thisLastName];
[scanner scanCharactersFromSet:whitespace intoString:nil];
[scanner scanUpToCharactersFromSet:whitespace intoString:&thisPhoneNum];
[scanner scanCharactersFromSet:whitespace intoString:nil];
[scanner scanUpToCharactersFromSet:whitespace intoString:&thisEmail];
[scanner scanCharactersFromSet:whitespace intoString:nil];
[scanner scanUpToCharactersFromSet:whitespace intoString:&thisPledge];
[scanner scanCharactersFromSet:whitespace intoString:nil];

NSCharacterSet *newLineCharacterSet = [NSCharacterSet newlineCharacterSet];
[scanner scanUpToCharactersFromSet:newLineCharacterSet intoString:&thisMajor];
[scanner scanCharactersFromSet:newLineCharacterSet intoString:nil];

Create the NSMutableArray before the loop.

NSMutableArray *members = [NSMutableArray array];

Set the values inside the loop and add your Object to the members array.

AKPsiMember *member = [[AKPsiMember alloc] init];
member.firstName = thisFirstName;
// ... set other properties
[members addObject:member];

This code will break when there are whitespaces in between the first fields of your dataset. Obviously this could be broken down into methods and results should be checked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top