This question already has answers here:
Replace all NSNull objects in an NSDictionary
(8 answers)
Closed 8 years ago.
I have an NSArray which contain string values, but sometimes it may contain null values also. I am getting that array like this,
(
"<null>",
"<null>",
"<null>",
"<null>",
"<null>"
)
I want to replace above by,
(
" ",
" ",
" ",
" ",
" "
)
That means I want to replace <null> by an empty string. how to achieve that ? I am aware of some string methods but that can not be implemented on array.
NSMutableArray *arr = [myNullArray mutableCopy];
for (int i=0; i < [arr count]; i++)
{
if ([[arr objectAtIndex:i] isKindOfClass:[NSNull Class]])
{
[arr inserObject:#" " atIndex:i];
}
}
NSLog(arr);
you would have to use the answer from here and iterate through each string in the array and perform the replacement of "<null>" with " "
edit: i think i misunderstood your question, if the array is containing NSNull objects, then you would still need to iterate through the array and just do a check like
for(int i = 0; i < array.count; i++){
if([array[i] isKindOfClass:[NSNull class]]){
array[i] = #" ";
}
}
disclaimer: havent tested code, just doing it off top of my head
You can try something like this.
for (NSInteger i = 0; i < array.count; i++) {
if ([array[i] isEqual:[NSNull null]] || [array[i] isEqual:#"<null>"]) {
[array replaceObjectAtIndex:i withObject:#" "];
}
}
First we need to understand, if it is a null string or the description taken from the log of an NSNull object. I suppose that array is your array. In the first case:
NSMutableArray * mutArr = #[].mutableCopy;
for (id obj in array) {
if ([obj isKindOfClass:NSString.class]) {
if ([obj isEqualToString:#"<null>"]) {
[mutArr addObject:#""];
}
else {
[mutArr addObject:obj];
}
else {
[mutArr addObject:obj];
}
}
array = mutArr.copy;
But I guess is the second:
NSMutableArray * mutArr = #[].mutableCopy;
for (id obj in array) {
if (obj == [NSNull null]) {
[mutArr addObject:#""];
}
else {
[mutArr addObject:obj];
}
}
array = mutArr.copy;
Just few hints that maybe can interest you:
If the original array is an NSArray is immutable and you can't change its content
during iteration don't remove/add object from the same array you are using for iteration or it will raise an exception
Mosto of times is the description of an NSNull object. NSNull is sneaky, because it can handle just few method and it's always source of crashes due to doesn't recognizeSelector
Fast enumeration is faster than common C for loop
swapping and substituting object in an array requires times
If you are using swift this would one way.
var stringArray = [String?]()
// Fill array with you stuff
// ...
// Check null (nil)
for string in stringArray
{
if string == nil
{
string = " "
}
}
NSMutableArray *anArray = [NSMutableArray arrayWithArray:yourArray];
for (id anObject in anArray) {
if((anObject) && (anObject != nil) && !([anObject
isKindOfClass:[NSNull class]]))
{
// if object is not nil
}
else{
anObject = #"";
}
}
yourArray = (NSArray *)anArray;
Related
I store user's answers inside NSMutableString element of array. i want to show a pop up (call popGoResultsAlert) when all of the array's element has the value and user would complete the questionary , i search over the internet but didn't succeed to find the solution for that.
here is my code :
in first class
[UserData updateUserAnswerValues:[userData objectForKey:#"userAnswerValues"]];
//second class ,part of the userData.m
static NSMutableArray *userAnswerValues;
+ (NSMutableArray *)getAnswersCompleted {
return userAnswerValues;
}
+ (void)updateUserAnswerValues:(NSArray *)newAnswerValues
{
userAnswerValues = [[NSMutableArray alloc] init];
[userAnswerValues addObjectsFromArray:newAnswerValues];
}
+ (void)updateUserAnswerValueWithIndex:(NSUInteger)index andValue:(NSMutableString*)value
{
[userAnswerValues setObject:value atIndexedSubscript:index];
}
in 3rd class:
- (void)viewWillAppear:(BOOL)animated
{
NSMutableArray *userAnswerValues = [UserData getAnswersCompleted];
for (int i=0; i<userAnswerValues.count; i++) {
id object = userAnswerValues[i];// similar to [myArray objectAtIndex:0]
if(object && [object length] !=0 && i!=0)
{
[self popGoResultsAlert];
break;
} else if (!object) {
continue;
}
}
}
Edit :
//4th class , here seems the origin data is populated to the userAnswerValues base on what user pick from PickerView , that index has the value and that value is put by selectedOptionValue variable ... I have debug the userAnswerValues and notice the value has 56 elements like userAnswerValues = ( "", "", "", "", "", "", "", "", 4, 3, 4, 3, "", ... (fill the rest with ,"" until 56 items> , "" );
so whenever a user select a value in PickerView one of the above element filled out with index number , so my question is how search through these mutable array and see if all item has value...
NSUInteger index = [self.currentQuestion.index integerValue];
[UserData updateUserAnswerWithIndex:index andValue:self.selectedOptionIndex];
Option *selectedOption = [self.currentOptions objectAtIndex:[self.selectedOptionIndex integerValue]];
NSString *selectedOptionValue = selectedOption.value;
[UserData updateUserAnswerValueWithIndex:index andValue:selectedOptionValue];
there is 3 section of questionary that store all the answer's value in a single and same array. with above code , the alert pop up whenever each of 3 section would be completed , my intend is it would only show pop up when all 3 section is completed....
I have test [object length] !=0 , ![object isEqual:[NSNull null]] , ![object isEqualToString:#""] with no luck , all of the 3 has same behaviour (show pop up after each section is completed ,
These project has not written by me from the scratch so i am trying to debug and fix some of it's bugs , when i debug userAnswerValues , i see that the items of NSMutableArray had different type in different elements type, as you see item 32th is _NSFConstantString with empty value , while the item 33th is NSTagedPointerString... please see the attached file for more details.
What I think you need is very similar to the previous answer. Here, I'll translate to your data names.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
BOOL showPopup = YES; // Assume success
NSMutableArray *userAnswerValues = [UserData getAnswersCompleted];
// Try to go all the way through the array without finding an empty string
for (int i = 0; i < userAnswerValues.count; i++) {
id object = userAnswerValues[i];
if ([object length] == 0) {
showPopup = NO; // Something is not filled in
break;
}
}
if (showPopup) {
[self popGoResultsAlert];
}
}
Bool nilBool = 0;
for (int i = 0 ; i < yourArray.count; i ++)
{
NSString *value = [yourArray ObjectAtIndex:i];
if([value isEqual: #""] || value == nil)
{
nilBool = 1;
}
}
if(nilBool)
{
//one if your values is nil!
}
else
{
//all values are filled, you are good to go
}
when search value from array am getting <__NSArrayM:> was mutated while being enumerated. Am using this code.
NSInteger strlen=[searchText length];
for (NSString *pStr in pArrBusinessName ) {
NSRange nameRange = [pStr rangeOfString:searchText options:NSCaseInsensitivePredicateOption];
if(nameRange.location != NSNotFound) {
if (strlen == 1) {
pArrFilteredTableData = pArrBusinessName;
} else {
if ([pStr isKindOfClass:[NSNull class]]) {
NSLog(#"NSNull isKindOfClass called!");
}
if (![pStr isKindOfClass:[NSNull class]]) {
[pArrFilteredTableData addObject:pStr];
}
}
} else {
if ([pArrFilteredTableData count] == 0) {
}
}
[pTblDetails reloadData];
}
Change this code:
pArrFilteredTableData = pArrBusinessName;
To this;
pArrFilteredTableData = [pArrBusinessName mutableCopy];
make sure pArrFilteredTableData is a NSMutableArray if it wasn't already
It seems to be that you are doing modifications in the main array while searching the contents inside it. It would be good if you hold your search results in a separate mutable array rather than mutating the main array using which you created your list. Filter searched records from the main array and hold them in search array.
I am using Mantle to parse some JSON data from Yelp.
For each business returned I get an NSArray of categories. This would be an example:
yelpCategories = (
(
"Wine Bars",
"wine_bars"
),
(
"Ice Cream & Frozen Yogurt",
icecream
)
);
yelpCategories is the name of the array that I save. Later on I am trying to parse the array into a string:
NSMutableString *yelpCats = [[NSMutableString alloc] init];
for (NSObject * obj in business.yelpCategories)
{
[yelpCats appendString:[NSString stringWithFormat:#"%#,",[obj description]]];
}
The issue is with the above. I am being returned a string just as "(" so I must be accessing the array incorrectly. How can I correctly access each object, ideally I would be looking for the end string o be #"Wine Bars, Ice Cream & Frozen Yogurt".
EDIT
The categories array: (
(
Pubs,
pubs
)
)
FINAL EDIT - Proposed Solution
for (NSArray *cats in business.yelpCategories)
{
NSString *category = [cats objectAtIndex:0];
if ([category length] > 0) {
category = [category substringToIndex:[category length] - 1];
}
if (cats == business.yelpCategories.lastObject) {
[yelpCats appendString:[NSString stringWithFormat:#"%#",category]];
} else {
[yelpCats appendString:[NSString stringWithFormat:#"%#, ",category]];
}
}
cell.yelpCategories.text = yelpCats;
Using the description of the object gives you what you see in the debugger, which includes extra carriage returns.
What you want to do is something like:
yelpCats = [yelpCategories componentsJoinedByString:#", "];
#jeffamaphone 's answer is the correct and best way of doing things however what your doing will almost work, I think your just confused on the contents of the array.
The yelpCategories array is an array of strings so you don't need to call stringWithFormat or call the description method. In fact [obj description] will return a string so you didn't even need stringWithFormat in your example and you would have gotten the same output. To make your original method work change to:
NSMutableString *yelpCats = [[NSMutableString alloc] init];
for (id obj in business.yelpCategories)
{
//obj is a string so we can just append it.
[yelpCats appendString:obj]];
}
Also noticed I changed NSObject *obj to just id obj, this is the idiomatic way and shorthand way of declaring NSObjects in objective-c. In this example however I would actually use (NSString *category in business.yelpCategories) instead for better readability. In this case you are declaring to everyone that you expect each object in the array to be a string and then if you wanted to use NSString methods on it inside the loop then you don't have to cast it.
for (NSArray *cats in business.yelpCategories)
{
NSString *category = [cats objectAtIndex:0];
if ([category length] > 0) {
category = [category substringToIndex:[category length] - 1];
}
if (cats == business.yelpCategories.lastObject) {
[yelpCats appendString:[NSString stringWithFormat:#"%#",category]];
} else {
[yelpCats appendString:[NSString stringWithFormat:#"%#, ",category]];
}
}
cell.yelpCategories.text = yelpCats;
I asked a similar question to test an Array of Bool values here but now I have changed it so the values are now Integer values and I want to see if any of them are positive.
Example, I add 10 new objects in a loop like below, then at some point some may change and then I need to do a test. It may be that I do not use NSNumber, as long as I cna get an int out of it.
// I create an array like
NSMutableArray *MyArray = [[NSMutableArray alloc]init];
for (int count = 0; count < 10; count++)
{
[MyArray addObject:[NSNumber numberWithInt:0]];
}
// At some point I change a value or two
[MyArray replaceObjectAtIndex:3 withObject:[NSNumber numberWithInt:5]];
....
....
....
....
[MyArray replaceObjectAtIndex:3 withObject:[NSNumber numberWithInt:7]];
if([MyArray containsPositiveObject])
{
// Get the integer
int MyValue = [MyArray[4]integerValue];
}
EDIT
I have tried this and it works but wondered if there was a faster method.
if([self containsPositiveValue:selectedItems])
{
// Do my stuff
}
And then
-(bool)containsPositiveValue:(NSArray *)numberArray
{
bool result = NO;
for (NSNumber *obj in numberArray)
{
if([obj integerValue])
{
result = YES;
break;
}
}
return result;
}
Try this.
NSArray *array = #[ #(-1) , #(-3) , #(0) , #(-4) , #(2) , #(-1) ]; // zero is not positvie or negitive
NSArray *newArray = [array filteredArrayUsingPredicate: [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return ( [evaluatedObject isKindOfClass:[NSNumber class]] && ([evaluatedObject integerValue] > 0) );
return NO;
}]];
if (newArray.count)
{
NSLog(#"There are positive values");
}
else
{
NSLog(#"There are no positive values") ;
}
Surely the simplest way would be to go:
NSArray * array = #[#(-1), #(-5), #(-5)];
for (NSNumber * number in array) {
if (number.intValue > 0) {
NSLog(#"Positive Values");
// Add custom code here
break;
}
}
This will then check if at least one item in the array is greater than zero and custom code can then be implemented.
I suppose it depends if you want to perform something if there are no positive values and something different if there is?
You could always add something like this:
NSArray * array = #[#(-1), #(-5), #(-5)];
NSInteger largestValue = 0;
for (NSNumber * number in array) {
if (number.intValue > largestValue) {
largestValue = number.intValue;
}
if (largestValue > 0) {
break;
}
}
if (largestValue > 0) {
NSLog(#"Positive Value");
}
else {
NSLog(#"All Negative Values");
}
Anyway it gets more complicated the more complicated you want it to work but it should be incredibly simple
for (int i = 0; i< [delarsInfoArray count] ; i++)
{
NSString *lattitudeValue;
NSString *longitudeValue;
if ([[delarsInfoArray objectAtIndex:i]count]>1) {
lattitudeValue = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"LATITUDE"]objectAtIndex:1];
longitudeValue = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"LONGITUDE"]objectAtIndex:0];
}
else
{
lattitudeValue = #"";
longitudeValue = #"";
}
CLLocationCoordinate2D pinLocation;
if(([lattitudeValue floatValue] != 0) && ([longitudeValue floatValue] != 0) ) {
mapRegion.center.latitude = [lattitudeValue floatValue];
mapRegion.center.longitude = [longitudeValue floatValue];
if(pinLocation.latitude !=0 && pinLocation.longitude !=0) {
myAnnotation1 = [[MyAnnotation alloc] init];
if ([[delarsInfoArray objectAtIndex:i] count] == 0) {
myAnnotation1.title = #"";
myAnnotation1.subtitle = #"";
}
else
{
// NSLog(#"====== delears array is===%#",delarsInfoArray);
NSLog(#"===== delears array count is %d",[delarsInfoArray count]);
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] !=nil)
{
myAnnotation1.title = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2];
}
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]!= nil) {
myAnnotation1.subtitle = [[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3];
}
NSLog(#"%#",[[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]);
}
[dealerMapView setRegion:mapRegion animated:YES];
[dealerMapView addAnnotation:myAnnotation1];
myAnnotation1.coordinate = mapRegion.center;
[myAnnotation1 release];
}
}
}
The above code is written in the viewWillAppear.After loading the map in to the view,when i clicked on the map.app gets crashed.How can solve this crash?
There are a lot of issues here, but the one that leaps out to the top of the list are the lines that read:
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] !=nil)
...
and
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"City"]objectAtIndex:3]!= nil) {
...
The problem is that objectAtIndex of a valueForKey of an array will never be nil. You can't store a nil in an array, so what valueForKey does, if it doesn't find a value, is it uses a NSNull object, [NSNull null]. That designates that there was no value found, but uses NSNull (which can be added to the array) instead of nil (which can't).
The problem is likely that there is some subsequent code (for example, the code that tries to figure out the size of the callout bubble) which tries to get the length of the string, but since you stored a NSNull, it's trying to call the length method and it's failing.
You could fix this a number of ways, such as:
if ([[[delarsInfoArray objectAtIndex:i]valueForKey:#"Address"]objectAtIndex:2] != [NSNull null])
...