So, I have a UIPicker view which gets populated from a NSMutableArray as long as the input is not "NULL".
So my picker shows all the values except NULL.
Now, I have a UITextField box and a button. So whatever I type in the text field, and I click the button, if it matches to anything which was there in the NSMutableArray ( which was used to populate UIPickerView ), it sets it to NULL and refreshes the UIPicker so that it doesn't get displayed anymore.
For some reason, I'm able to set the value to NULL(checked using NSLog), but the picker never gets updates, and neither does the NSMutable Array.
-(void) loadthepicker
{
NSMutableArray *getarray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"FilerNamesArray"]];
pickerLoaderArray=[[NSMutableArray alloc] init];
for (int j=0; j<20; j++) {
if ([[getarray objectAtIndex:j] isEqualToString:#"NULL"])
{
// do nothing..don't load
}
else // add that filter to pickerLoaderArray
{
[pickerLoaderArray addObject:[getarray objectAtIndex:j]];
}
} // end of for
[pickerView reloadAllComponents];
[pickerView selectRow:0 inComponent:0 animated:NO];
}
-(NSInteger)numberOfComponentsInPickerView:(NSInteger)component
{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component
{
return [pickerLoaderArray count];
}
-(NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [pickerLoaderArray objectAtIndex:row];
}
The button:
- (IBAction)deleteButton:(id)sender {
NSUserDefaults *CheckFiltersUsed = [NSUserDefaults standardUserDefaults];
NSInteger myInt = [CheckFiltersUsed integerForKey:#"FiltersUsed"];
if (myInt<=20 && myInt>0) {
NSLog(#"number of filters used before deleting %ld",(long)myInt);
[CheckFiltersUsed setInteger:myInt-1 forKey:#"FiltersUsed"];
[CheckFiltersUsed synchronize];
// get names array
NSMutableArray *getarray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"FilerNamesArray"]];
NSArray *get=getarray;
// at location where name matches with selectedfilter..put NULL
for (int j=0; j<20; j++) {
if ( [[getarray objectAtIndex:j] isEqualToString:_filterToDelete.text] && isFilterDeleted==NO )
{
NSLog(#"------currently %d is %#",j,[getarray objectAtIndex:j]);
[getarray insertObject:#"NULL" atIndex:j];
NSLog(#"------now %d is %#",j,[getarray objectAtIndex:j]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"" message: #"Deleted" delegate: nil cancelButtonTitle:#"Ok" otherButtonTitles:nil]; [alert show];
isFilterDeleted=YES;
[[NSUserDefaults standardUserDefaults] setObject:getarray forKey:#"FilerNamesArray"];
[[NSUserDefaults standardUserDefaults]synchronize];
[self loadthepicker];
}
else
{
NSLog(#"No matching filter name");
}
} // end of for
//now save this array back.
}
else
{
NSUserDefaults *CheckFiltersUsed = [NSUserDefaults standardUserDefaults];
NSInteger myInt = [CheckFiltersUsed integerForKey:#"FiltersUsed"];
NSLog(#"Wrong number of filters!!!... %d",myInt);
}
}
If i get what you are trying to do, you want to delete the equal string from the array and the picker as well. But instead of that you just insert another NSString object into index 'j'
In the deleteButton method:
Instead of this line
[getarray insertObject:#"NULL" atIndex:j];
Call
[getarray removeObjectAtIndex:j];
**Update
In the loadPicker just remove the if statment to check if the string is equal to #"NULL"
So instead of:
for (int j=0; j<20; j++) {
if ([[getarray objectAtIndex:j] isEqualToString:#"NULL"])
{
// do nothing..don't load
}
else // add that filter to pickerLoaderArray
{
[pickerLoaderArray addObject:[getarray objectAtIndex:j]];
}
}
Do:
for(NSString *pickerValue in getarray){
[pickerLoaderArray addObject:pickerValue];
}
Related
In my app a user can change the number of picker view elements by clicking some buttons. Everything is ok with that. But after that I want to show a word in it but the picker view is probably not ready and the app just crashes. Here is the cod for that
- (IBAction)changeNumberOfLettersToShow:(id)sender {
int numberOfLetters = (int)((UIBarButtonItem *)sender).tag;
switch (numberOfLetters) {
case 0:
[self setNumberOfLetters:[NSNumber numberWithInt: 10] andLanguage:nil];
break;
default:
[self setNumberOfLetters:[NSNumber numberWithInt: numberOfLetters] andLanguage:nil];
break;
}
[self showTheFirstWordForNumberOfLetters:numberOfLetters];
}
- (void) showTheFirstWordForNumberOfLetters: (int) numberOfLetters{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:numberOfLetters], [NSNumber numberWithInt:0], nil] forKey:#"currentPositon"];
NSArray *words = [allWordsForCurrentLanguage objectForKey:[NSString stringWithFormat:#"%#%d",[[NSUserDefaults standardUserDefaults] objectForKey:#"language"], numberOfLetters]];
[self displayWord:[[words objectAtIndex:0] uppercaseString] animated:YES];
}
- (void) setNumberOfLetters:(NSNumber *)numberOfLetters andLanguage: (NSString *) language {
[pickerHelper setNumberOfLettersToShow:numberOfLetters andLanguage:nil];
[self.picker reloadAllComponents];
}
- (void) displayWord:(NSString *)word animated:(BOOL)animated {
pickerHelper.pickerWorkingAutomatically = YES;
for (NSUInteger i = 0; i < [word length]; i++) {
NSString *letter = [NSString stringWithFormat:#"%c", [word characterAtIndex:i]];
[self displayLetter:letter
atComponent:i
animated:animated];
}
pickerHelper.pickerWorkingAutomatically = NO;
}
The picker looks similar to the one on the picture:
http://sourcefreeze.com/wp-content/uploads/2015/03/uipickerview-multi-selected-row.png
So I actually want to make a word from the fragments of a picker containing letters (which also user to work fine before I started doing it) and it actually works on a simulator.
UPDATED:
- (void) displayLetter:(NSString *)letter atComponent:(NSUInteger)component animated:(BOOL)animated {
NSUInteger row;
if (animated){
NSUInteger selectedRow = [self.picker selectedRowInComponent:component];
row = selectedRow + ([self.alphabet count] - selectedRow % [self.alphabet count]) + [self.alphabet indexOfObject:letter];
}
else
row = ((UINT16_MAX) / (2 * [self.alphabet count]) * [self.alphabet count]) + [self.alphabet indexOfObject:letter];
[self.picker selectRow:row
inComponent:component
animated:animated];
}
So I have a double picker where the user sets each wheel to what they want, and then press a button which will display their choice. Easy clean and simple, but I want to store that data for later so that it does not disappear after they close the app and re-open it again. Now, I know how to do it with a datePicker, but not a doublePicker. So my question is how do I tweak my code from saving and retrieving a datePickers info into a doublePicker?
Here is my code for the datePicker:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Pulling the date out of my picker
NSDate *selectedDate = [self.datePicker date];
[defaults setObject:selectedDate forKey:#"DatePickerViewController.selectedDate"];
And then retrieving it again:
- (void)viewDidLoad
{
[super viewDidLoad];
// Get the date. I'm going to use a little shorthand instead of creating
// a variable for the instance of `NSUserDefaults`.
NSDate *storedDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"DatePickerViewController.selectedDate"];
// Setting the date on the date picker. I'm passing `NO` to `animated:`
// because I'm performing this before the view is on screen, but after
// it has been loaded.
[self.datePicker setDate:storedDate animated:NO];
}
Any help would be appreciated, thx :)
In your UIPickerViewDelegate:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:row forKey:[NSString stringWithFormat:#"DoublePickerViewController.%i", component]];
}
To get the data out:
for (int i = 0; i < doublePicker.numberOfComponents; i++) {
NSInteger *storedInteger = [[NSUserDefaults standardUserDefaults] integerForKey:[NSString stringWithFormat:#"DoublePickerViewController.%i", i];
[doublePicker selectRow:storedInteger inComponent:i animated:NO];
}
For storing multiple values:
In your UIPickerViewDelegate:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *oldArray = [defaults arrayForKey:[NSString stringWithFormat:#"DoublePickerViewController.%i", component]];
//Make a mutable version so we can change it
NSMutableArray *newArray = [oldArray mutableCopy];
if (!newArray) {
newArray = [NSMutableArray array];
}
//Add The Latest Row To The end of the array. We wrap it in an NSNumber so it can be in an array
[newArray addObject:[NSNumber numberWithInteger:row]];
//If you want to have a limit on the amount of values that can be stored then use this
int maxValues = 5;
if (newArray.count >= maxValues) {
//Remove the oldest object
[newArray removeObjectAtIndex:0];
}
[defaults setObject:newArray forKey:[NSString stringWithFormat:#"DoublePickerViewController.%i", component]];
}
To get the data out:
for (int i = 0; i < doublePicker.numberOfComponents; i++) {
NSArray *storedIntegers = [[NSUserDefaults standardUserDefaults] arrayForKey: [NSString stringWithFormat:#"DoublePickerViewController.%i", i];
//I don't know what values you want, but to get an int out of the array:
//int integer = [(NSNumber *)[storedIntegers objectAtIndex:0] intValue];
//And to set the row for a component:
//[doublePicker selectRow:storedInteger inComponent:i animated:NO];
}
It's driving me crazy, I did a log and I see the objects are different, but when I get then back from NSUserDefaults, all of the objects are the same.
My code:
- (void)breakTrapsToSave:(NSDictionary*)trapsDict firstTimeUpdate:(Boolean)firstTimeUpdate
{
// If traps already save
// we will get them from NSUserDefaults
// and then update them
if (!firstTimeUpdate)
{
allTraps = [self.sharedPrefs objectForKey:#"arrayOfAllTraps"];
}
// JSON Parsing
tempA = trapsDict[#"Envelope"];
tempB = tempA[#"Body"];
tempC = tempB[#"getTrapsResponse"];
tempD = tempC[#"getTrapsResult"];
tempE = tempD[#"TRAPS"];
self.lastUpdate = tempE[#"lastUpdate"];
[[NSUserDefaults standardUserDefaults] setObject:self.lastUpdate forKey:#"last_update"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Traps latest updated at: %#", self.lastUpdate);
tempF = tempE[#"TRAP"];
if (tempF.count <= 0)
{
newTrapsUpdates = false;
NSLog(#"NO NEW TRAPS!");
}
else
{
newTrapsUpdates = true;
NSLog(#"NEW TRAPS FOUND");
[tempF enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
tempA = tempF[idx];
NSString *finalResult;
NSString *key;
NSMutableDictionary *singleTrap = [[NSMutableDictionary alloc] init];
for (int i=0; i < node.count; i++)
{
finalResult = tempA[node[i]];
key = node[i];
if ([finalResult length] <= 0)
{
finalResult = #"0";
}
singleTrap[key] = finalResult;
}
if (allTraps.count <= 0)
{
allTraps = [[NSMutableArray alloc] initWithObjects:singleTrap, nil];
}
else
{
[allTraps addObject:singleTrap];
}
counter = idx;
}];
allTraps = [[IDANNetroads sharedInstance] removeDuplicatedFromArray:allTraps];
// Save all traps
[[NSUserDefaults standardUserDefaults] setObject:allTraps forKey:#"arrayOfAllTraps"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Total Traps: %d", allTraps.count);
NSLog(#"Total New Traps: %d", counter);
}
}
I did a log and I see allTraps[idx] = singleTrap; is different as it should be, but when I print the log for NSLog(#"allTraps: %#", allTraps); I see all of the objects are the last object.
EDIT:
Eventually, I replaced the singleTrap allocation and now it's inside the enumeration block:
NSMutableDictionary *singleTrap = [[NSMutableDictionary alloc] init];
And I added this code:
if (allTraps.count <= 0)
{
allTraps = [[NSMutableArray alloc] initWithObjects:singleTrap, nil];
}
else
{
[allTraps addObject:singleTrap];
}
So, the final code is edited.
Whatever singleTrap is, you're repeatedly mutating it and storing another reference to the same object in your allTraps array. You need to create (instantiate) a new item for each entry you want in your allTraps list.
It looks like singleTrap is an array of strings, so try:
allTraps[idx] = [singleTrap copy];
I made the following method to remove doubles, however it doesn't fully work. Any suggestions?
Thank you for the help,
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSMutableArray *noDuplicates =[[NSMutableArray alloc]init];
for (int i=0; i<[array count]; i++) {
int counter =0;
Car *car =(Car*)[array objectAtIndex:i];
if ([noDuplicates count]==0) {
[noDuplicates addObject:car];
}
for (int i=0; i<[noDuplicates count]; i++) {
Car *car2 =(Car*)[array objectAtIndex:i];
if (![car.name isEqualToString:car2.name]) {
counter++;
}
}
if (counter==[noDuplicates count]) {
[noDuplicates addObject:car];
}
}
NSLog(#"number of results = %i",[noDuplicates count]);
return noDuplicates;
}
Create an array called "addedCars" - you will use it to store the name of each unique car.
In each iteration, use [NSArray containsObject:] to check if the current name has already been added to "addedCars". If not, add the name to "addedCars" and the car to "noDuplicates". Otherwise, skip this item, as it has already been added to noDuplicates.
be sure [isEqual:] and [hash] is implemented as you expected
-(NSMutableArray*)removeDuplicateCars:(NSMutableArray*)array{
NSOrderedSet *set = [[NSOrderedSet alloc] initWithArray:array];
NSMutableArray *newArr = [NSMutableArray arrayWithCapacity:[set count]];
for (id obj in set) {
[newArr addObject:obj];
}
return newArr;
}
You used ![car.name isEqualToString:car2.name] to compare objects so I believe you want to filter objects with same name? Than you need to override [isEqual:] for Car
- (BOOL)isEqual:(id)other {
if ([other isKindOfClass:[self class]]) {
return [self.name isEuqalToString: [other name]];
}
return NO;
}
- (NSUInteger)hash {
return [self.name hash];
}
also check this question The best way to remove duplicate values from NSMutableArray in Objective-C?
I am using SudzC to get webservices, that webservice give me data, I tried to save the data in a property, but when I use to fill a tableview the property don't have any data. I use the debugger to view the property.
This es my handler
- (void) ConsultarUnidadesOrganizacionalesPorEmpresaHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
NSMutableArray *unidadOrganizacional = [[NSMutableArray alloc] init];
self.myData = [NSMutableArray array];
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
[unidadOrganizacional addObject:[empresa Descripcion]];
}
self.myData = unidadOrganizacional;
}
And this is the part where I use the web service
- (void)viewDidLoad
{
// Do any additional setup after loading the view from its nib.
EWSEmpresaWebServiceSvc *service = [[EWSEmpresaWebServiceSvc alloc]init];
[service ConsultarUnidadesOrganizacionalesPorEmpresa:self action:#selector(ConsultarUnidadesOrganizacionalesPorEmpresaHandler:) EmpresaId:self.empresaID];
[super viewDidLoad];
}
And the tableview is empty. Why does this happen? How can I use the data and fill my tableview?
Try to change your code this way :
self.myData = [[NSMutableArray alloc] init]autorelease];
// your loop
[sel setMyData:unidadOrganizacional];
try loading it in a dictionary:
dict = [resp objectForKey:#"YourKey"];
if( ( dict == nil ) || ![dict isKindOfClass:[NSDictionary class]] ) {
NSLog( #"WARNING: %#", [dict description]);
return;
}
empID = [[dict objectForKey:#"empresaID"]copy];
NSLog(#"Your Value: %#", empID);
I found the answer, I just have to put
[_myTableView reloadData]
at the end of the method.