Populate an NSTokenField with tokens from a container of objects - objective-c

I have an NSTableView and an NSTokenField in a window. I have implemented the following delegate methods:
tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:
tokenField:representedObjectForEditingString:
tokenField:displayStringForRepresentedObject:
I want to make it so that when a row is selected in it, the NSTokenField gets populated with the tags that are contained in an NSMutableSet of the row object. How do I populate an NSTokenField with tokens if I have a container of the objects that they represent (and therefore the strings that need to be made into tokens)?

I figured it out. In the code below ms is an NSMutableSet that contains my objects.
//set the token field
NSMutableArray *ma = [[NSMutableArray alloc] init];
for (MyClass *anObject in ms){
[ma addObject:anObject];
}
//sort the array
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey: #"title" ascending: YES];
NSArray *sortDescriptorArray = [[NSArray alloc] initWithObjects:sorter, nil];
[ma sortUsingDescriptors:sortDescriptorArray];
[tokenField setObjectValue:ma];
The key is the last line: [tokenField setObjectValue:ma];

Related

NSArray copy for undo /redo purposes

If I have an nsarray full of custom objects and I make a second array using:
NSArray *temp = [NSArray arrayWithArray:original];
then work with some properties of the objects inside the original array, then decide to roll back, I am then using the reverse:
original = [NSArray arrayWithArray:temp];
I am finding the objects I changed in the array also effected my temp array. I also tried implementing copyWithZone on my custom class, and using copyItems and it did not help. What else should I try?
To be clear, in order to use copyWithZone, I changed my array creation command to:
NSArray *temp = [[NSArray alloc] initWithArray:original copyItems:YES];
My copyWithZone:
-(id)copyWithZone:(NSZone *)zone{
CustomObject *ret = [[CustomObject allocWithZone: zone] init];
//copy properties
return ret;
}

NSString, matchig name of an NSArray

I am new to Objective C coming from C# .NET, I have this scenario :
Assume I have 5 NSArrays corresponding to 5 UIButtons. the UIButtons have the exact same name
as the NSArray, so for example one UIButton is called mainScreen, and there is an NSArray called mainScreen.
Those Five buttons are linked to one IBAction where I do the following :
- (IBAction)btnClick:(id)sender {
NSString *category = [(UIButton *)sender currentTitle];
NSLog(category);
//Here I need to call the NSArray which has the same name as category
}
Now I can get the actual name of the UIButton, but how can I get the NSArray same as that title? without getting into a lot of if else or switch statements?
What I would do is store the arrays inside an NSDictionary. You can then set the 'key' as the name of your array and then the value would be the array itself.
That way you could say:
- (IBAction)btnClick:(id)sender {
NSString *category = [(UIButton *)sender currentTitle];
NSLog(category);
//Here I need to call the NSArray which has the same name as category
NSArray *theArray = (NSArray*)[self.myDictionary valueForKey:category];
}
Hope this helps!
The easiest way to associate names with objects is using an NSDictionary (or it's mutable subclass NSMutableDictionary). Dictionaries map a unique key to an object. Keys can be any object (that implements the NSCopying protocol), but are very often NSStrings
Have a look at the NSDictionary Reference and the Programming with Objective-C guide.
Note that if you use the button title this might break if you localise your app.
What you do is not the best way. You should provide tag for each button, say from 1 to 5. Also you should put your five arrays into one array. Now all you need is:
- (IBAction)btnClick:(id)sender
{
NSInteger index = [sender tag] - 1;
NSArray *array = [bigArray objectAtIndex:index];
}
That's it.
Assign different tags to all UIButtons and then access them explicitly using their tags.
- (IBAction)btnClick:(id)sender {
int tagIs = [(UIButton *)sender tag];
switch (tagIs) {
case 1:
// Access first button array
break;
case 2:
// Access second button array
break;
default:
break;
}
}
Or you can use AssociationObjects method for associating data with objects as following:
Firstly import :
#import <objc/runtime.h>
then create keys as :
static char * firstBtnKey = "firstBtnKey";
static char * secondBtnKey = "secondBtnKey";
-- - other keys same way ---
then use :
// Do any additional setup after loading the view, typically from a nib.
NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects:#"object1",#"object 2", nil];
objc_setAssociatedObject((UIButton *)[self.view viewWithTag:1],
firstBtnKey,
firstArray,
OBJC_ASSOCIATION_RETAIN);
NSMutableArray *secondArray = [[NSMutableArray alloc] initWithObjects:#"object1",#"object 2", nil];
objc_setAssociatedObject((UIButton *)[self.view viewWithTag:2],
secondBtnKey,
secondArray,
OBJC_ASSOCIATION_RETAIN);
`
and then access these arrays as :
- (IBAction)btnClick:(id)sender {
int tagIs = [(UIButton *)sender tag];
switch (tagIs) {
case 1:
// Access first button array
NSMutableArray *tempArr = (NSMutableArray *)objc_getAssociatedObject((UIButton *)sender, firstBtnKey);
break;
case 2:
// Access second button array
NSMutableArray *tempArr = (NSMutableArray *)objc_getAssociatedObject((UIButton *)sender, secondBtnKey);
break;
default:
break;
}
}
Hope it helps.
In most programming languages objects don't have names.[1] Just because UIButtons have the exact same name as the NSArray(mainScreen), doesn't mean that your object is "called" mainScreen.
Use NSDictionary , array as object and button title as key.
or use button tag
title1= [[NSArray alloc] initWithObjects:#"1",nil];
title2= [[NSArray alloc] initWithObjects:#"2",nil];
title3= [[NSArray alloc] initWithObjects:#"3",nil];
title4= [[NSArray alloc] initWithObjects:#"4",nil];
title5= [[NSArray alloc] initWithObjects:#"5",nil];
dict = [[NSDictionary alloc] initWithObjectsAndKeys:title1,#"title1",title2,#"title2",title3,#"title3",title4,#"title4",title5,#"title5",nil];
- (IBAction)btnClick:(id)sender {
NSString *category = [(UIButton *)sender currentTitle];
NSArray *arr = [dict objectForKey:category];
}

Populating TableView with NSMutableSet

I am using core data and trying to populate a UITableView with an NSMutableSet. I have two entities, Teams and Players. On my addTeamsController I am saving a player to the team as follows
-(void)saveButtonWasPressed {
self.team =[NSEntityDescription insertNewObjectForEntityForName:#"Team" inManagedObjectContext:self.managedObjectContext];
Player *newPlayer = (Player *)[NSEntityDescription insertNewObjectForEntityForName:#"Player"
inManagedObjectContext:self.managedObjectContext];
team.schoolName = _schoolName.text;
team.teamName = _teamName.text;
team.teamID = _teamName.text;
team.season = _season.text;
team.headCoach = _headCoach.text;
team.astCoach = _assistantCoach.text;
[self.team addPlayers:_tempSet];
[self.managedObjectContext save:nil];
[self.navigationController popViewControllerAnimated:YES];
}
On another viewController I am trying to populate a tableview with that teams players. To do that I am doing as follows
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"firstName" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
_array = [[_team.players allObjects] sortedArrayUsingDescriptors:sortDescriptors];
and then on my cell for row and index path I am doing the following
cell.textLabel.text = [_array objectAtIndex:indexPath.row];
And I get the error
[Player isEqualToString:]: unrecognized selector sent to instance
I am wondering what the best approach to filling the tableview sorted by the players first names is.
The best way to populate a table from a core data store is to use an NSFetchedResultController. But that is not going to fix the problem you're having, the problem is that your trying to set cell.textLabel.text to an NSManagedObject, which doesn't work. You can set
cell.textLabel.text = Player.someStringAttribute

Can't access NSDictionary values

I have an NSDictionary called equiposDic, which I need to retrieve using a value from another NSDictionary (value dip from ) but I can't' access it:
equiposDic = [[NSDictionary alloc] initWithObjectsAndKeys:#"FC Barcelona Regal", #"49", #"Real Madrid", #"50", #"Caja Laboral", #"51", #"Banca CĂ­vica", #"52", #"Gescrap Bizkaia",#"53", #"Valencia Basket", #"13",#"Lucentum Alicante",#"54",#"Lagun Aro GBC",#"4",#"CAI Zaragoza", #"55", #"Assignia Manresa",#"2", #"FIATC Mutua Joventut",#"8",#"Unicaja",#"56",#"Gran Canaria",#"57",#"Mad-Croc Fuenlabrada",#"9",#"Blusens Monbus",#"59",#"UCAM Murcia",#"58", #"Asefa Estudiantes",#"60", #"Blancos de Rueda Valladolid", #"11", nil];
NSDictionary *posicion = [[NSDictionary alloc] initWithDictionary: [ligaArray objectAtIndex:indexPath.row]];
NSString *equipo = [posicion valueForKey:#"idp"];
NSString *idp = [posicion valueForKey:#"idp"];
NSLog(#"equipo %#", [equiposDic objectForKey:#"49"]);
Many thanks
If posicion is a NSDictionary, you have to use objectForKey in order to get the string.
NSString *idp = [posicion objectForKey:#"idp"];
Is ligaArray available in the context ?
I explain, your ligaArray var maynot be available when you expect it. You have to store ligaArray in your class with a retain
.h :
#interface MyClass {
NSMutableArray *ligaArray;
}
.m :
-viewDidLoad{
[super viewDidLoad];
ligaArray = [[NSMutableArray array] retain];
// OR
ligaArray = [[NSMutableArray alloc] init];
}
-dealloc{
[ligaArray release];
}
If this is not the case, try it. If it's already the case, check the retain/release calls.
This way, you will not loose reference to ligaArray values in your tableview methods.

Objective-c NSMutableArray release behaviour

Does the release, recursively releases all inner objects? or must it be done manualy?
Can I do just this?
NSMutableArray *list = [[NSArray alloc] init];
// ...
// fill list with elements
//...
[list release];
Or must I release all inner objects one by one before releasing the NSMutableArray? // Suposing there isn't any other reference to the contained objects, except on the list itself.
Yes it does. It retains them when added, and releases them when dealloc'd. This is actually one of the most common questions I see here.
If you are owning the object then you will have to release it.
NSMutableArray *list = [[NSArray alloc] init];
NSString *str = [[NSString alloc] init] // you are the owner of this object
[list addObject:str];
[str release]; // release the object after using it
[list release];
If you are not the owner of the object then you should not release.
NSMutableArray *list = [[NSArray alloc] init];
NSString *str = [NSString string]; // you are not owning this object
[list addObject:str]; // str retain count is incremented
[list release]; // str retain count is decremented.
This is the concept which even array also uses. When you add any object to the array, array will retain it. In the sense it becomes the owner of that object and It will release that object when you release the array.