incorrect textfield input obj c - objective-c

i have a problem with the management between app and sdk for a function. my app is divided into two parts: sdk and app.
this is my class for "sdk":
- (void)statusCheckPin: (User *)pinUser
card: (Card *)pinCard
viewController: (UIViewController *) viewController
delegate: (id<LoyaltyCardsSDKCompleteDelegate>)delegate{
self.delegate = delegate;
SDKHandler* sdkHandler = [[SDKHandler alloc] initWithUserId:pinUser.userId fiscalCode:nil sessionToken:pinUser.sessionToken];
[sdkHandler doStatusCheckPin:pinUser.userId card:pinCard.pan viewController:viewController
success:^(StatusCheckPinResponse* changePin) {
Result<StatusCheckPinResponse *> *response = [[Result<StatusCheckPinResponse*> alloc] initWithStatusCode:MOBILE_GENERIC_ERROR_MSG andResponse:changePin];
[self callDelegateForCommand:CMD_CHANGE_PIN WithResponse:response];
} failure:^(Result *failureResult) {
[self callDelegateForCommand:CMD_CHANGE_PIN WithResponse:failureResult];
}];
PRLog(#"SDK> Received cmd: STATUS CHECK PIN");
}
- (void) doStatusCheckPin: (NSString *) pinUser card: (NSString *) pinCard viewController: (UIViewController *) viewController success:(successSDKType)success failure:(failureSDKType)failure{
self.mcCardEnrollmentSuccessCallback = success;
self.mcCardEnrollmentFailureCallback = failure;
self.user = [[User alloc ]init];
self.card = [[Card alloc ]init];
// self.testViewController = [[TestViewController alloc] init];
self.testViewController = [[TestViewController alloc] initWithNibName:#"TestViewController" bundle:[NSBundle bundleForClass:[TestViewController class]]];
if([self.testViewController.panPersonalTextField isEqual: #"0"] ||
[self.testViewController.panPersonalTextField isEqual: #"1"] ||
[self.testViewController.panPersonalTextField isEqual: #"2"] ||
[self.testViewController.panPersonalTextField isEqual: #"3"] ||
[self.testViewController.panPersonalTextField isEqual: #"4"] ||
[self.testViewController.panPersonalTextField isEqual: #"5"]){
StatusCheckPinResponse *statusCheckPin = [[StatusCheckPinResponse alloc] init];
[statusCheckPin setErrorCase:#"NOT_ENROLLED"];
Result *errore = [[Result alloc] initWithStatusCode:#"2" andResponse:statusCheckPin];
self.mcCardEnrollmentFailureCallback(errore);
} else if ([self.testViewController.panPersonalTextField isEqual: #"6"] ||
[self.testViewController.panPersonalTextField isEqual: #"7"] ||
[self.testViewController.panPersonalTextField isEqual: #"8"] ||
[self.testViewController.panPersonalTextField isEqual: #"9"]){
StatusCheckPinResponse *statusCheckPin = [[StatusCheckPinResponse alloc] init];
[statusCheckPin setErrorCase:#"ENROLLED"];
Result *errore = [[Result alloc] initWithStatusCode:#"1" andResponse:statusCheckPin];
self.mcCardEnrollmentFailureCallback(errore);
}
}
and this is my "app":
case CHECK_PIN:{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
self.user = [[User alloc ]init];
self.card = [[Card alloc ]init];
self.user.userId = self.userIdPersonalTextField.text;
self.user.sessionToken = self.sessionTokenPersonalTextField.text;
self.user.fiscalCode = self.fiscalCodePersonalTextField.text;
self.user.phoneNumber = self.phoneNumberPersonalTextField.text;
self.user.callerApp = self.callerAppPersonalTextField.text;
self.card.pan = self.panPersonalTextField.text;
self.card.driverCode = self.driverCodePersonalTextField.text;
[self.loyaltySDK statusCheckPin:self.user card:self.card viewController:self delegate:self];
});
}
that based on the number entered in the "pan" textfield, let me display 2 or 3 different answers.
the function I have to write better is this:
if([self.testViewController.panPersonalTextField isEqual: #"0"] ||
[self.testViewController.panPersonalTextField isEqual: #"1"] ||
[self.testViewController.panPersonalTextField isEqual: #"2"] ||
[self.testViewController.panPersonalTextField isEqual: #"3"] ||
[self.testViewController.panPersonalTextField isEqual: #"4"] ||
[self.testViewController.panPersonalTextField isEqual: #"5"]){
StatusCheckPinResponse *statusCheckPin = [[StatusCheckPinResponse alloc] init];
[statusCheckPin setErrorCase:#"NOT_ENROLLED"];
Result *errore = [[Result alloc] initWithStatusCode:#"2" andResponse:statusCheckPin];
self.mcCardEnrollmentFailureCallback(errore);
} else if ([self.testViewController.panPersonalTextField isEqual: #"6"] ||
[self.testViewController.panPersonalTextField isEqual: #"7"] ||
[self.testViewController.panPersonalTextField isEqual: #"8"] ||
[self.testViewController.panPersonalTextField isEqual: #"9"]){
StatusCheckPinResponse *statusCheckPin = [[StatusCheckPinResponse alloc] init];
[statusCheckPin setErrorCase:#"ENROLLED"];
Result *errore = [[Result alloc] initWithStatusCode:#"1" andResponse:statusCheckPin];
self.mcCardEnrollmentFailureCallback(errore);
}
that to tell the truth it doesn't work at all, because it always gets nil the textfield despite inserting the user in number ..

It looks as though you are comparing a UITextField* with a NSString* , which would definitely not be doing what you intend.
NSString* text = self.testViewController.panPersonalTextField.text;
if( [text isEqualToString: #"0"] ||
[text isEqualToString: #"1"] ||
[text isEqualToString: #"2"] ||
[text isEqualToString: #"3"] ||
[text isEqualToString: #"4"] ||
[text isEqualToString: #"5"] )
{
// do things
}
else if ( [text isEqualToString: #"6"] ||
[text isEqualToString: #"7"] ||
[text isEqualToString: #"8"] ||
[text isEqualToString: #"9"] )
{
// do other things
}
Might be enough to start you off, but it's hard to say without knowing more about the textfield. If your user's input is not limited to a single digit, you might want to add checking for that. Also, if there is a chance that this could be called when the textfield has no content, I usually like to compare strings this way, if there are constants involved:
if ( [#"constant string" isEqualToString:nullableVar] )
{
// do things
}
There also isn't enough information in your question to see why these need to remain as NSStrings at all, otherwise you might consider adding all these codes to an enum, which would make your comparisons even easier.

Related

unrecognized selector sent to instance:processing JSON api

I am trying to check if some keys are not present from response of an api and adding it but am getting unrecognized selector sent to instance error what am i doing wrong and is the the best solution
- (NSArray *) examinationFromArray :(NSArray *) arrayBeforeProcessing {
NSMutableArray *examinationMutable = [[NSMutableArray alloc] init];
if (arrayBeforeProcessing) {
for (NSDictionary *dict in arrayBeforeProcessing) {
NSMutableDictionary *theWholeAudit = [dict objectForKey:#"auditData"];
NSMutableDictionary *summary = [theWholeAudit objectForKey:#"summary"];
if([summary objectForKey:#"cases"] == nil || [summary objectForKey:#"percentageOfCases"] == nil || [summary objectForKey:#"fDateValidation"] == nil){
summary[#"cases"] = 0;
summary[#"percentageOfCases"] = 0;
summary[#"fDateValidation"] = false;
}
if([theWholeAudit objectForKey:#"duplicate"] == nil){
theWholeAudit[#"duplicate"] = false;
}
Audit *audits = [self setAttributesFromMap:dict];
[examinationMutable addObject:audits];
}
}
return [examinationMutable copy];

ARC conversion issue with handleSearchForTerm delegate method

since converting to ARC (automatically) i have noticed with my uisearchviewcontroller delegate an issue somewhere (i think in the first if statement below). It was changed as a result but either way my app crashes when i try to perform a search:
The current code:
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (KABrand *currentBrand in [self brands])
{
if ([currentBrand.name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
if (![searchResults containsObject:currentBrand])
[[self searchResults] addObject:currentBrand];
}
}
}
The previous code:
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
[array release], array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (KABrand *currentBrand in [self brands])
{
if ([currentBrand.name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
if (![searchResults containsObject:currentBrand])
[[self searchResults] addObject:currentBrand];
}
}
}
}
Thanks for your help in advance!
Thanks guys
Here is one potential problem: -rangeOfString:options: may return an NSNotFound. But you are checking if the range.location != NSNotFound.
If is if the return value of -rangeOfString:options: is NSNotFound, your if statement becomes NSNotFound.location != NSNotFound. I don't believe that's allowed.

FMDB Result set ruturning nil

So here is the deal, I am using FMDB SQLite Wrapper for my DB app. I know Cord Data is there but My database is really really huge and all I want to do is read it. No new records are going to be inserted / updated via iOS app. At one point in this app I am trying to pull records from DB which are name of player and thier Id based on searchTerm and searchPosition. searchTerm works perfectly fine. searchPosition query works in sqlite3 but not in iOS app. I don know where I am going wrong. Help me out. Code for both methods are as follows:
-(IBAction)searchTerm
{
searchTermValue=self.term.text;
self.fmdbUtils = [[[FMDBUtils alloc] initWithDatabase:#"Colts.sql"] autorelease];
FMDatabase *db = [self.fmdbUtils sharedDB];
FMResultSet *rs = nil;
NSString *AgentId = nil;
NSString *PlayerName = nil;
NSString *PlayerId = nil;
ScoutAppDelegate *appDelegate = (ScoutAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.playerList = [[NSMutableArray alloc] init];
NSString * query = #"SELECT * FROM Player WHERE LENGTH (lastname)>0 AND LENGTH (firstname)>0 AND ( lastname LIKE '%' || ? || '%' OR firstname LIKE'%' || ? || '%' OR Height LIKE '%' || ? || '%' OR Weight LIKE '%' || ? || '%') ORDER BY lastname,firstname";
rs = [db executeQuery:query,searchTermValue,searchTermValue,searchTermValue,searchTermValue];
[query release];
while([rs next])
{
PlayerId = [rs stringForColumn:#"player_id"];
//NSString *PlayerName = [rs stringForColumn:#"Player Name"];
if ([rs stringForColumn:#"Player Name"]!= NULL)
{
PlayerName = [rs stringForColumn:#"Player Name"];
}
else
PlayerName=#"";
if ([rs stringForColumn:#"agent_id"]!= NULL)
{
AgentId = [rs stringForColumn:#"agent_id"];
}
else
AgentId=#"0";
Player *temp =[[Player alloc]initPlayerID:PlayerId Name:PlayerName Agent:AgentId];
[appDelegate.playerList addObject:temp];
[temp release];
}
[rs close];
[db close];
PlayersListTableViewController *temp=[[PlayersListTableViewController alloc]initWithNibName:#"PlayersListTableViewController" bundle:nil];
temp.title=#"Players";
self.playersListTableViewCtrl=temp;
[temp release];
[self.navigationController pushViewController:playersListTableViewCtrl animated:YES];
}
Here is theIBAction used to search players based on their playing position.
-(IBAction)SearchPosition
{
searchTermValue= searchPositionValue;
self.fmdbUtils = [[[FMDBUtils alloc] initWithDatabase:#"Colts.sql"] autorelease];
FMDatabase *db = [self.fmdbUtils sharedDB];
FMResultSet *rs = nil;
NSString *AgentId = nil;
NSString *PlayerName = nil;
NSString *PlayerId = nil;
ScoutAppDelegate *appDelegate = (ScoutAppDelegate *)[[UIApplication sharedApplication] delegate];
//appDelegate.playerList = [[NSMutableArray alloc] init];
NSString * query = #"SELECT * FROM Player WHERE LENGTH (lastname)>0 AND LENGTH (firstname)>0 AND ( College_Position LIKE '%' || ? || '%' OR Pro_Position LIKE'%' || ? || '%') ORDER BY lastname,firstname";
rs = [db executeQuery:query,searchPositionValue,searchPositionValue];
[query release];
while([rs next])
{
PlayerId = [rs stringForColumn:#"player_id"];
//NSString *PlayerName = [rs stringForColumn:#"Player Name"];
if ([rs stringForColumn:#"Player Name"]!= NULL)
{
PlayerName = [rs stringForColumn:#"Player Name"];
}
else
PlayerName=#"";
if ([rs stringForColumn:#"agent_id"]!= NULL)
{
AgentId = [rs stringForColumn:#"agent_id"];
}
else
AgentId=#"0";
Player *temp =[[Player alloc]initPlayerID:PlayerId Name:PlayerName Agent:AgentId];
[appDelegate.playerList addObject:temp];
[temp release];
}
[rs close];
[db close];
PlayersListTableViewController *temp=[[PlayersListTableViewController alloc]initWithNibName:#"PlayersListTableViewController" bundle:nil];
temp.title=#"Players";
self.playersListTableViewCtrl=temp;
[temp release];
[self.navigationController pushViewController:playersListTableViewCtrl animated:YES];
}
This method just gives selected playing position for search in pickerview.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
self.searchPositionValue = [playingPositions objectAtIndex: row];
}
Try to debug the SQL-Statement (after the executeQuery: call) by printing the error:
if ([db hadError]) {
NSLog(#"DB Error %d: %#", [db lastErrorCode], [db lastErrorMessage]);
}
For developing I would recommend to enable general logging of errors:
db.logsErrors = YES;

Need help in finding a memory leak in copying Sqlite Database to Mutable array

I seem to be having a 1.19 KB leak somewhere in the following code. opening up the call tree in instruments, I have narrowed down the leaks to the following:
61.8% of the leaks are coming from +[NSString stringWithUTF8String:]
38.1% of the leaks are coming from +[NSNumber numberWithDouble:]
-(void) readMinesFromDatabase
{
NSLog(#" Setup the database object");
sqlite3 *database;
// Init the Array
northernMines = [[NSMutableArray alloc] init];
nCentralMines = [[NSMutableArray alloc] init];
centralMines = [[NSMutableArray alloc] init];
southernMines = [[NSMutableArray alloc] init];
//NSLog(#" pre if statement");
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "SELECT * FROM mines";
//NSLog(#"pre 2nd if statement");
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK)
{
NSLog( #"Error: Failed to prepare stmt with message %s", sqlite3_errmsg(database));
}
else
{
// Loop through the results and add them to the feeds array
NSLog(#"pre loop");
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *name;
NSString *com;
NSString *county;
NSNumber *lat;
NSNumber *longit;
// Read the data from the result row
//deals with null strings in the name and commodity fields of the database
//NSLog(#"ered the loop");
if (sqlite3_column_text(compiledStatement, 3) != NULL) {
name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
}
else {
name = #"";
}
if (sqlite3_column_text(compiledStatement, 10) != NULL) {
com = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 10)];
}
else {
com = #"";
}
//latitude and longitudes
lat = [NSNumber numberWithDouble:(double )sqlite3_column_double(compiledStatement, 4)];
longit = [NSNumber numberWithDouble:(double )sqlite3_column_double(compiledStatement, 5)];
//NSLog(#"long %#",longit);
// Create a new object with the data from the database
Mine *mine = [[Mine alloc] initWithMineName:name latitudeInitial:lat longitudeInitial:longit commodity:com];
// Add the object to the animals Array
county = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 8)];
if([county isEqualToString:#"Butte"] || [county isEqualToString:#"Plumas"] || [county isEqualToString:#"Yuba"] || [county isEqualToString:#"Sierra"])
{
[northernMines addObject:mine];
}
else if([county isEqualToString:#"Nevada" ]|| [county isEqualToString:#"Placer"] || [county isEqualToString:#"El Dorado"] || [county isEqualToString:#"Sutter"])
{
[nCentralMines addObject:mine];
}
else if([county isEqualToString:#"Amador"] || [county isEqualToString:#"Sacramento"] || [county isEqualToString:#"Calaveras"] || [county isEqualToString:#"San Joaquin"] || [county isEqualToString:#"Stanislaus"])
{
[centralMines addObject:mine];
}
else if([county isEqualToString:#"Tuolumne"] ||[county isEqualToString:#"Mariposa"] || [county isEqualToString:#"Madera"] || [county isEqualToString:#"Merced"])
{
[southernMines addObject:mine];
}
else
{
}
[mine release];
//[name release];
//[com release];
//[county release];
//[lat release];
//[longit release];
}
NSLog(#"done with loop");
//[mines addObject:#"nil"];
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
the mine object implementation file is:
#import "Mine.h"
#implementation Mine
#synthesize mineName, latitudeInitial, longitudeInitial, commodity;
-(id)initWithMineName:(NSString *)n latitudeInitial:(NSNumber *)l longitudeInitial:(NSNumber *)g commodity:(NSString *)c
{
self.mineName = n;
self.latitudeInitial = l;
self.longitudeInitial = g;
self.commodity = c;
return self;
}
#end
Well, it is a little hard to tell because of the indentation where the function ends (is this the entire function?) but I believe you are forgetting to release the 4 arrays that you are allocating at the beginning of the function. By leaking the arrays you are also leaking their contents.
Edit - for the initializer code you added:
I am not sure if this has anything to do with the memory leaks but I noticed that the initializer is not implemented correctly:
you should call init on super and update self (more details here)
of this I am not 100% sure, but I think you should not send messages (call methods) to the current object from inside the init method, and by using the dot notation you are actually calling the setter methods (but again, I am not really sure of this one)
I suppose that the properties are declared as (retain) and that you release them in the dealloc method. Which would be correct.
I can't really see anything else wrong with the code you showed. Maybe the problem is not exactly here (just an idea).
Edit 2 - example initializer
You should spend some time reading the Apple documentation, it has plenty of examples.
Here is my version (I hope it doesn't have too many mistakes):
-(id)initWithMineName:(NSString *)n latitudeInitial:(NSNumber *)l longitudeInitial:(NSNumber *)g commodity:(NSString *)c {
// Assign self to value returned by super's designated initializer
// Designated initializer for NSObject is init
self = [super init];
if (self) {
mineName = [n retain];
latitudeInitial = [l retain];
longitudeInitial = [g retain];
commodity = [c retain];
}
return self;
}
Just a thought, but could the memory leak be in the Mine object initializer ( -[Mine initWithMineName: latitudeInitial: longitudeInitial: commodity:] ) ??

UITableView and SearchBar problem

I'm trying to add a Search bar to my UITableView. I followed this tutorial: http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html.
I'm getting this error if I type a letter in the search box: Rooster(10787,0xa05ed4e0) malloc: *** error for object 0x3b5f160: double free
*** set a breakpoint in malloc_error_break to debug.
This error occurs here:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self handleSearchForTerm:searchString];
return YES;
}
(on the second line)
- (void)handleSearchForTerm:(NSString *)searchTerm {
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
[array release];
}
//Empty the searchResults array
[[self searchResults] removeAllObjects];
//Check if the searchTerm doesn't equal zero...
if ([[self savedSearchTerm] length] != 0) {
//Search the whole tableList (datasource)
for (NSString *currentString in tableList) {
NSString *klasString = [[NSString alloc] init];
NSInteger i = [[leerlingNaarKlasList objectAtIndex:[tableList indexOfObject:currentString]] integerValue];
if(i != -1) {
klasString = [klassenList objectAtIndex:(i - 1)];
}
//Check if the string matched or the klas (group of school)
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound ||
[klasString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound) {
//Add to results
[[self searchResults] addObject:currentString];
//Save the klas (group of school). It has the same index as the result (lastname)
NSString *strI = [[NSString alloc] initWithFormat:#"%i", i];
[[self searchResultsLeerlingNaarKlas] addObject:strI];
[strI release];
}
[klasString release];
}
}
}
Can someone help me out?
Regards,
Dodo
The double free error means you have released an object more than needed. Here the suspicious object is klasString.
From your code:
NSString *klasString = [[NSString alloc] init];
...
if(i != -1) {
klasString = [klassenList objectAtIndex:(i - 1)];
}
...
[klasString release];
The assignment inside the if statement
loses reference to the newly allocated NSString, introducing a memory leak
makes the later release apply to the object from klassenList. When klassenList releases its elements, a double free error will occur.