Sort Object inside NSArray? - ios

I have an object, as below
#import <Foundation/Foundation.h>
#interface CountriesDAO : NSObject
#property (nonatomic, retain) NSString * countryname;
#end
#import "CountriesDAO.h"
#implementation CountriesDAO
#synthesize countryname;
#end
I have saved this in Array within appDelegate.
#property (nonatomic, retain) NSArray *countriesArray;
#synthesize countriesArray;
In another controller, I fetch it like
NSArray *countriesArray = appDelegate.countriesArray; It works fine and I get array.
As I try to sort it by this way.
NSArray *countriesArray1 = appDelegate.countriesArray;
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:#"countryname" ascending:YES];
NSArray * descriptors = [NSArray arrayWithObject:valueDescriptor];
countriesArray = [countriesArray1 sortedArrayUsingDescriptors:descriptors];
I get error
[__NSCFType count]: unrecognized selector sent to instance 0xa83b4d0
2013-11-01 13:21:08.882 ECP[13597:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType count]: unrecognized selector sent to instance 0xa83b4d0'
Here countriesArray is defined as
#property (nonatomic, retain) NSArray *countriesArray;

I did it like this and it worked for me.
countriesArray = [[NSMutableArray alloc] init];
for (CountriesDAO *info in appDelegate.countriesArray) {
[countriesArray addObject:info.countryname];
}
[countriesArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

You can also try...
[countriesArray1 sortUsingSelector:#selector(compare:)];

Should work
NSMutableArray *sortedArray = [appDelegate.countriesArray mutableCopy];
[sortedArray sortUsingComparator:^NSComparisonResult(CountriesDAO *object1,
CountriesDAO *object2) {
return [object1.countryname caseInsensitiveCompare:object2.countryname];
}];
NSArray *sortedCountriesArray = [sortedArray copy];
If something went wrong, check the type of object1 and object2

Its is simple Way to sort array in iOS,it's helps to you
[countriesArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [ String_1 compare: String_2];
}];
// String_1, String_2 are NSString,it's contains in countriesArray
// use NSMutableArray to rearrange and change values in countriesArray

If the array you want to sort contains NSString (which is what I get from your description) you can replace your sorting code with this:
sortedArray = [countriesArray1 sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

Related

IOS: NSKnownKeysDictionary1 error

I have an object selectedActivity defined as follows:
#property (strong, nonatomic) Activities *selectedActivity;
At the point I need to work with it logs out as:
{
actname = "Running";
aid = 23;
}
The Activities object is an NSManaged object and its .h file looks like this.
#interface Activities : NSManagedObject
#property (nonatomic, retain) NSString * actname;
#property (nonatomic, retain) NSNumber * aid;
#end
I am trying to place one of the object properties in a variable to work with it using the following:
NSNumber *aid = _selectedActivity.aid;
However, the above line gives the following error message:
[NSKnownKeysDictionary1 aid]: unrecognized selector sent to instance 0x147842fb0
Can anyone explain this error and how to fix it?
Thanks for any suggestions.
Update:
setting of selected activity
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
_selectedActivity =([_activities objectAtIndex:row]);
NSLog(#"selectedActivity in pickerview%#",_selectedActivity);
}
//activities in .h file
#property (strong, nonatomic) NSArray *activities;
//setting of activities
self.activities= [self getActivities];
//method that gets activities
- (id) getActivities{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Activities"];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"created" ascending:NO];
[fetchRequest setSortDescriptors:#[sort]];
NSError *error = nil;
self.managedObjectContext = [Model sharedInstance].managedObjectContext;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest
error:&error];
NSMutableArray *mutableresults = [results mutableCopy];
[mutableresults removeObjectIdenticalTo:[NSNull null]];
return mutableresults;
}
The results are coming as a dictionary.
instead of the usual NSManagedObject-style value retrieval:
Objective-C
NSString *actname = _selectedActivity.actname;
NSNumber *aid = _selectedActivity.aid;
Swift
let actname:String = _selectedActivity.actname
let aid:Int = _selectedActivity.aid
Use the NSDictionary-style value retrieval, like so:
Objective-C:
NSString *actname = [_selectedActivity valueForKey:#"actname"];
NSNumber *aid = [[_selectedActivity valueForKey:#"aid"] intValue];
Swift (tested as of 3.0.1)
_selectedActivity(forKey: "actname") as! String
_selectedActivity.value(forKey: "aid") as! Int

How to filter custom object in objective-C

I have a custom object which contains data as:
#interface Students : NSObject
{
}
#property (nonatomic,strong) NSString *ID;
#property (nonatomic,strong) NSString *FirstName;
#property (nonatomic,strong) NSString *MiddleName;
#property (nonatomic,strong) NSString *LastN
I want to filter it according to the last name. For example:
I want an array which contains all the details of students having last name="Cena"
I tried this:
NSMutableArray *arrayToFilter = self.studentList;
NSString *nameformatString = #"LastName contains[c] a";
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:nameformatString];
[arrayToFilter filterUsingPredicate:namePredicate];
When I run my app I am getting this error and my app crashes:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason:
'[< Students 0x7fd25e102d20> valueForUndefinedKey:]:
this class is not key value coding-compliant for the key a.'
I am only able to get last name in array but I know this is wrong. How can I sort the custom object based on last name.
Code I am using to get lastName:
names = [[NSMutableArray alloc]init];
for (int i = 0; i < [self.studentList count] ; i++)
{
Students * studentsObj = (Students*)[self.studentList objectAtIndex:i];
[names addObject:studentsObj.LastName];
}
Update the predicate to ,
NSString *textToMatch = #"a";
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:#"LastN CONTAINS[cd] %#", textToMatch];
then
NSMutableArray *arrayToFilter = self.studentList;
NSArray *filteredArray = [arrayToFilter filteredArrayUsingPredicate:namePredicate];
for getting last name only,
NSArray *lastNames = [filteredArray valueForKey:#"LastN"];
NSArray *sortedArray = [lastNames sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

-[__NSArrayI objectForKeyedSubscript:]: unrecognized selector sent to instance IN xcode6 objective-c ios

I am trying to learn objective-c, and came across some crash I couldn't resolve.
I believe it's one of the basic problems, but I am new here and got lost in the middle.
I have :
ModelViewController.h
ModelViewController.m
Schedule.h
Schedule.m
in ModelViewController.h
#import <UIKit/UIKit.h>
#interface FetchScheduleVC : UIViewController
#property (copy, nonatomic) NSMutableArray *myMutableArray;
#end
in ModelViewController.m
#import "ModelViewController.h"
#import "Schedule.h"
#implementation Model
- (void)viewDidLoad {
[super viewDidLoad];
for(int i=0; i < 3; i++){
[_myMutableArray addObjects: [NSNumber numberWithInt: i]
}
}
- (IBAction)saveBtn:(UIButton *)sender {
Schedule *newSchedule = [[Schedule alloc]init];
[newSchedule createClassFromArray: _myMutableArray];
}
#end
in Schedule.h
#import <Foundation/Foundation.h>
#interface Schedule : NSObject
#property (strong, nonatomic) NSMutableArray *classArray;
-(void) createClassFromArray: (NSArray *) selectedArr;
#end
in Schedule.m
#import "Schedule.h"
#implementation Schedule
-(void) createClassFromArray: (NSArray *) selectedArr {
for(NSNumber *i in selectedArr){
NSLog(#"number in array is : %#", i);
}
}
#end
I simplified my codes a little, but the basic flow is the same.
When I run this, and click a button to call - (IBAction)saveBtn:(UIButton *)sender, I get:
-[__NSArrayI objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fcb61d2fd10
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fcb61d2fd10'
Anything wrong doings in sending NSArray through Method up here?
I can only tell you what's happening in your code, not where it's happening, as you've not posted the offending code.
The objectForKeyedSubscript method is called for NSDictionary subscripting, for example:
NSDictionary *dict = #{ #"key" : #"value" };
NSString *value = dict[#"key"]; // HERE
so it looks like you are doing something like this:
for(int i=0; i < 3; i++){
[_myMutableArray addObjects: [NSNumber numberWithInt: i]
}
NSNumber *num = _myMutableArray[#"3"]; // !!!!
One more thing I can tell you, it's not to do with uninitialized array as Objective-C simply ignores attempts to dereference nil objects and this exception has gone further than that.
As you have declared myMutableArray with copy semantic as-
#property (copy, nonatomic) NSMutableArray *myMutableArray;
this will sends a copy message to the array, which results in an immutable copy.
So, to use above semantics on NSMutableArray you need to override the "setter" method as -
- (void)setArray:(NSArray *)newArray
{
if ( array != newArray )
{
[array release];
array = [newArray mutableCopy];
}
}
the above setter method just assign the reference of mutable copy of the newArray to the array, which help you to mutate the objects and thus avoiding the error.
In the codes above, I forgot to include
_myMutableArray = [[NSMutableArray alloc] init];
although i had that in my actual code.
the problem was very dumb. Sorry for this misleading question. Hope you just ignore this question cuz it's due to such a careless mistake.
In my actual code, I had duplicate variable names like this:
in Schedule.h
#import <Foundation/Foundation.h>
#interface Schedule : NSObject
#property (strong, nonatomic) NSMutableArray *selectedArr;
-(void) createClassFromArray: (NSArray *) selectedArr;
#end
..very.. careless mistake.

Magical Record sorting error

I create a bunch of Group Entities:
for (NSString *groupID in result) {
group = [Group MR_createInContext:context];
group.groupID = [NSNumber numberWithInteger:[groupID integerValue]];
}
I then want to list them by a sort:
NSArray *groups = [Group MR_findAllSortedBy:#"groupID" ascending:TRUE inContext:context];
for (Group *group in groups) {
DLog(#"group.groupID: %#", group.groupID);
DLog(#"group: %#", group);
}
which produces the error:
-[__NSCFNumber caseInsensitiveCompare:]: unrecognized selector sent to instance 0x2595d2c0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber caseInsensitiveCompare:]: unrecognized selector sent to instance 0x2595d2c0'
My group Entity is auto generated:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface Group : NSManagedObject
#property (nonatomic, retain) NSNumber * groupID;
#end
#interface Group (CoreDataGeneratedAccessors)
#end
If I do the same fetch w/out Magical Record, it woks fine:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Group"];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"groupID" ascending:TRUE selector:nil];
NSArray *sorters = [NSArray arrayWithObject:sort];
[fetchRequest setSortDescriptors:sorters];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
Any ideas why I'm getting the error?
So I checked the Magical Record repo on github (https://github.com/magicalpanda/MagicalRecord) and I didn't see the method that you are using(probably because there was a bug in the documentation regarding the sorting methods for fetching the sorted entities but I saw two other methods that are recommended for fetching sorted entities.
[entity MR_findAllSortedByProperty:#"property" ascending:YES] // single property
[entity MR_findAllSortedByProperty:#"oneProperty,secondProp" ascending:YES] // mutliple properties

Objective-C IOS Xcode: Unable to modify object in NSMutableArray

My problem is that I have a class property that is of type NSMutableArray, as defined in my header file, yet when I attempt to modify one of the array elements (an NSDictionary) I receive the following runtime error:
2013-01-16 14:17:20.993 debtaculous[5674:c07] * Terminating app due
to uncaught exception 'NSInternalInconsistencyException', reason:
'-[__NSCFArray replaceObjectAtIndex:withObject:]: mutating method sent
to immutable object'
Header declaration:
// BudgetViewController.h
#import <UIKit/UIKit.h>
#interface BudgetViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
- (IBAction)afterTaxIncomeEditingDidEnd:(id)sender;
#property (strong, nonatomic) NSMutableArray *budgetArray;
#property (strong, nonatomic) IBOutlet UITextField *afterTaxIncome;
#property (strong, nonatomic) IBOutlet UITableView *budgetTableView;
#end
Method that generates the error:
-(void)applyCCCSWeights
{
NSMutableDictionary *valueDict;
NSString *newAmount;
for (id budgetElement in [self budgetArray]) {
valueDict = [[NSMutableDictionary alloc] initWithDictionary:budgetElement];
newAmount = [NSString stringWithFormat:#"%0.2f", [[self afterTaxIncome].text floatValue] * [[budgetElement objectForKey:#"cccs_weight"] floatValue]];
[valueDict setValue:newAmount forKeyPath:#"amount"];
[[self budgetArray] replaceObjectAtIndex:0 withObject:valueDict];
NSLog(#"%0.2f (%0.2f)", [[budgetElement objectForKey:#"amount"] floatValue], [[self afterTaxIncome].text floatValue] * [[budgetElement objectForKey:#"cccs_weight"] floatValue]);
}
[self.budgetTableView reloadData];
}
// Note the replaceObjectAtIndex:0 above is just a placeholder. This will be replaced with the correct index.
budgetArray is surely immutable, you have to create it mutable.
Probably you're doing something like this:
budgetArray= [NSArray arraWithObjects; obj1, obj2, nil];
And ignoring the compiler warning. Make it mutable:
budgetArray= [[NSMutableArray alloc]init];
I'm fairly certain you cannot change a mutable object during enumeration.
This SO question may help: Setting an object during fast enumeration problems
In your init method, put this:
budgetArray = [[NSMutableArray alloc] init];
Also, why not use dictionary and array literal syntax?
-(void)applyCCCSWeights {
NSMutableDictionary *valueDict;
NSString *newAmount;
for (NSDictionary *budgetElement in [self budgetArray]) {
valueDict = [budgetElement mutableCopy];
newAmount = [NSString stringWithFormat:#"%0.2f", [[self afterTaxIncome].text floatValue] * [budgetElement[#"cccs_weight"] floatValue]];
valueDict[#"amount"] = newAmount;
_budgetArray[0] = valueDict;
NSLog(#"%0.2f (%0.2f)", [budgetElement[#"amount"] floatValue], [[self afterTaxIncome].text floatValue] * [budgetElement[#"cccs_weight"] floatValue]);
}
[self.budgetTableView reloadData];
}
Notice that [[self budgetArray] replaceObjectAtIndex:0 withObject:valueDict];
becomes: _budgetArray[0] = valueDict;
You can't change an array while doing a fast iteration over the array. On the other hand, it's entirely unnecessary; the code is absolutely inefficient: Just make the elements of the array NSMutableDictionaries, then change the dictionaries directly, instead of creating a copy and then changing an element in the copy.
Noticed later that you use NSJSONSerialization; look at the flags and don't pass 0 blindly.

Resources