NSDictionary syntax explanation - ios

I have UITableView and NSDictionary. It populated like follow:
currentAlbumData = [album tr_tableRepresentation];
Where albums is simple NSObject class:
// h.file
#interface Album : NSObject
#property (nonatomic, copy, readonly) NSString *title, *artist, *genre, *coverUrl, *year;
-(id)initWithTitle:(NSString*)title artist:(NSString*)artist coverUrl:(NSString*)coverUrl year:(NSString*)year;
//m.file
-(id)initWithTitle:(NSString *)title artist:(NSString *)artist coverUrl:(NSString *)coverUrl year:(NSString *)year{
self = [super init];
if (self){
_title = title;
_artist = artist;
_coverUrl = coverUrl;
_year = year;
_genre = #"Pop";
}
return self;
};
And tr_tableRepresentation is category of Album class, returning NSDictionary:
//h.file
#interface Album (TableRepresentation)
- (NSDictionary*)tr_tableRepresentation;
#implementation Album (TableRepresentation)
//.m file
- (NSDictionary*)tr_tableRepresentation
{
return #{#"titles":#[#"Artist", #"Album", #"Genre", #"Year"],
#"values":#[self.artist, self.title, self.genre, self.year]};
}
That is the code i take from tutorial, so, in following lines we populate tableView data with NSDictionary values:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
//... Cell initialization code
cell.textLabel.text = currentAlbumData[#"titles"][indexPath.row];
cell.detailTextLabel.text = currentAlbumData[#"values"][indexPath.row];
}
Now I'm stuck. because I'm getting confused when i see syntax like that.
cell.textLabel.text = currentAlbumData[#"titles"][indexPath.row];
cell.detailTextLabel.text = currentAlbumData[#"values"][indexPath.row];
What exactly is going on here? What this lines of code do? I can understand that we accessing #"titles" and #"values" somehow, could you please rewrite that lines in more readable manner, without square brackets?
And how could we even get #"titles" and #"values" using just indexPath (integer number)? That may sound kind of silly, but I'm not get it. I thought we have to put string as a parameter to access NSDictionary values, not an integer.

It is just a short way of writing code:
currentAlbumData[#"titles"][indexPath.row] is same asĀ [[currentAlbumData objectForKey:#"titles"] objectAtIndex:indexPath.row]. Here, currentAlbumData is a dictionary. You get it's object for key titles, which is (supposedly) an array. Then you get the object at index indexPath.row of this array.

titles is the key for an NSArray of NSStrings. So is values.
currentAlbumData[#"titles"] asks the dictionary for the value at the titles keypath. This returns an NSArray that is indexed by NSUIntegers, such as indexPath.row.

Titles is an array so to get value at particular index you can use
cell.textlabel.text = [[currentAlbumData valueForKey:#"titles"] objectAtIndex:indexPath.row];
If you find this confusing then better store Titles inside an array and then use it below
NSArray *titles = [currentAlbumData valueForKey:#"titles"];
cell.textlabel.text = [titles objectAtIndex:indexPath.row];

Related

Finding index of NSMutableDictionary inside an NSMutableArray

I have an NSMutableDictionary with a specific key and value. This dictionary is inside an NSMutableArray. I want to update the dictionary with a specific key which is at a certain index inside the array. I want to find the index of this dictionary object. Currently, my dictionary is at index 0 and my editingIndexPath is 1 which is of NSIndexPath type, so editingIndexPath.row doesn't help me.
My code is as follows:
//UpdatedDateAndTime is the NSMutableArray.
//selectedDay is a NSString object.
//dateKeySelected is also a string key.
[[updatedDateAndTime objectAtIndex:editingIndexPath.row] setObject:selectedDay forKey:dateKeySelected];
My problem is that I want to get the right index of the dictionary that is found.
The answer used to be a for loop with a counter, but you're in luck: NSArray has a new method, indexOfObject:, which should do the trick just fine:
NSUInteger i = [myArray indexOfObject:#{myKey:myValue}];
Swift: index(of:)
If your array contains just one special NSMutableDictionary then use below code. I didn't test it but the idea is to search NSMutableDictionary class in the array. And you have to do this search in indexPath which equals to the cell that you want to assign some data.
#interface ViewController (){
NSMutableArray *array;
NSMutableDictionary *dictionary;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (indexPath.row == 1) {
for (int i = 0; i < array.count; i++) {
if ([updatedDateAndTime[i] objectForKey:#"open_house_updated_date"] == selectedDay) {
NSLog(#"%i th index contains NSMutableDictionary that you want",i);
//do whatever needed
break;
}
}
}
else{
//define other cells which doesn't contain NSMutableDictionary
}
return cell;
}
#end
I hope this is what you are looking for.

UITableview cell data dynamically

I have implemented a UITableView in ViewController1,and I am passing the TableView cell content through the Array and display it.
_tableData=[[NSMutableArray alloc]initWithObjects:#"1",#"2" ,#"3",#"4",nil];
cell.detailTextLabel.text=[_tableData objectAtIndex:indexPath.row];
Now, that I have passed the data through statically, I want to implement it through a dynamic way by using Model Class.
How can I alter the Array through Model Class Array?
1) Create Model Class like this
#Interface SomeClass: NSObject
#property(nonatomic, Strong) NString* someValue;
2) Add model objects in the Datasource array ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
for(i=1,i<5,i++)
{
SomeClass *someObj = [SomeClass alloc]init];
someObj.someValue = [NSString stringWithFormat:#"%d",i];
[_tableData addObject:someObj];
}
}
3) In cell for Row set the data to textLabel
SomeClass *someObj = [_tableData objectAtIndex:indexPath.row];
cell.detailTextLabel.text = someObj.someValue
Note - I have the model objects with hard coded data. You can use the data from webservice or data from core data.
Only thing you need to do is to refresh your table view whenever your datasource array changes
_tableData = [....some value....];
[tableView reloadData];

Save random number generated in Table View

My app is currently generating random numbers (see code below). What I want is to save that number once the user hits the "Save" button and show it on a table view.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.clickyButton setTitle:#"Generate" forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)handleButtonClick:(id)sender {
// Generates numbers 1 to 49, without creating duplicate numbers.
NSMutableSet * numberSet = [NSMutableSet setWithCapacity:5];
while ([numberSet count] < 7 ) {
NSNumber * randomNumber = [NSNumber numberWithInt:(arc4random() % 49 + 1)];
[numberSet addObject:randomNumber];
}
NSArray * numbers = [numberSet allObjects];
self.n1.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:0]];
self.n2.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:2]];
self.n3.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:3]];
self.n4.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:4]];
self.n5.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:5]];
self.n6.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:6]];
}
#end
Please explain me how I can save it on a table view. xcode beginner.
You should create a variable that's accessible within the scope of the whole class rather than just the specific -handleButtonClick: method, and then add the generated numbers to that variable - an array, set, etc...
From there, you can implement the table view to read the values from the variable via var[indexPath.row] (assuming it's an array), and display it. You will need to call [tableView reloadData]; once the array has been filled with objects to make sure that the tableview displays the data.
create a NSMutableArray for UITableViewDataSource and cache the number.
when a number created by the user,add this number into NSMutableArray.
reload UITableView and show all numbers.
If you use only one number you should think about displaying it in another UI element, preferably a UILabel I would say.
If you want to use a UITableView you will either have to create it with static cells (e.g. in a Storyboard) or configure the data source and delegate object for it (which doesn't really seem what you want right now, unless maybe if you wanted to display multiple random numbers in a list...)
Before anything you should make the array numbers as a variable. In that way it is much easier than creating n1,n2,n3,.... I will show you how to solve your problem based on an existing numbers NSArray variable defined.
You need to implement the UITableView delegates in your header file. So let's suppose this is your header file after implementing the delegates:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
Then take your tableview (IBOutlet or programatically) and set the dataSource and delegate in the implementation file. You should do this in the viewDidLoad: method like this:
[_tableView setDelegate:self];
[_tableView setDataSource:self];
After you have done this you need to implement the delegate methods for the UITableView. This ones:
This method will tell the Table View how many rows it needs to show. In your case is the size of the NSArray called numbers:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return numbers.count;
}
This method will tell the Table View what to show on each cell (DON'T FORGET TO ASSING THE CELL IDENTIFIER OF THE CELL IN THE INTERFACE BUILDER TO "Cell")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [numbers objectAtIndex:indexPath.row];
return cell;
}
Use this method if you want to do something when the user touches a cell in the table view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
Finally to add numbers to the list as the user touches the button you just need to add these lines of code to your method triggered by the button:
- (IBAction)handleButtonClick:(id)sender {
// Generates numbers 1 to 49, without creating duplicate numbers.
NSMutableSet * numberSet = [NSMutableSet setWithCapacity:5];
while ([numberSet count] < 7 ) {
NSNumber * randomNumber = [NSNumber numberWithInt:(arc4random() % 49 + 1)];
[numberSet addObject:randomNumber];
}
//In case you want to delete previous numbers
[numbers removeAllObjects];
numbers = [numberSet allObjects];
[_tableView reloadData];
}

Selecting Variable Dynamically

Hello and thank you for your time. Im fairly new to IOS/Objective C.
I have multiple variables setup globally at the top of my viewcontroller.
NSMutableArray * A;
NSMutableArray * B;
NSMutableArray * C;
Now when someone selects a cell in a tableview I would like to use the name of that cell to select one of the global variables. I found something for doing this with viewcontrollers, but I need something for misc variables as well. I am reffering to:
id myNewController = [[NSClassFromString(selected) alloc] init];
[[self navigationController] pushViewController:myNewController animated:YES];
So it would be something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Save text of the selected cell:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
stringVariable = cell.textLabel.text;// value=A,B or C
// match string to array and load that array.
??
}
Thanks in advance for any help, and sorry if this has been asked but I couldn't find anything that worked so as a last resort im asking for help :)
You may be better off storing your arrays as keys on a dictionary, instead of as individual fields. For example:
NSDictionary* dictionary;
dictionary = #{
#"A": [[NSMutableArray alloc] init],
#"B": [[NSMutableArray alloc] init],
#"C": [[NSMutableArray alloc] init]
};
Then when your row is selected, you could lookup the array by key:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString* key = cell.textLabel.text;// value=A,B or C
NSMutableArray* array = dictionary[key];
....

ios - struggling to populate a UITableView from an NSArray

I have this code:
#interface MyBusinessesController : UIViewController
{
NSDictionary *businesses;
NSArray *items_array;
}
#property (weak, nonatomic) IBOutlet UILabel *messageLabel;
- (IBAction)plan:(id)sender;
#property (weak, nonatomic) IBOutlet UITableView *itemList;
#end
and I set the UITableView and the NSArray in the header area of the .m file. Then I have a remote server call and get back JSON. I get the JSON data into an array like this:
items_array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
Then I loop through the items like this:
for (int i = 0; i<= items_array.count - 1; i++)
{
NSDictionary *dict = [items_array objectAtIndex:i];
NSString *item_title = [dict objectForKey:#"item_title"];
NSString *item_id = [dict objectForKey:#"item_id"];
...
and then I would like to add it as a row in my UITableView, but I am struggling with how to do it now.
What I would want is to display the item_title to the user, and when the user presses the title that I would be able to know how to get the item_id of that item_title.
Thank you!
You need to implement the required methods in the UITableViewDataSource protocol, and set the dataSource property of the tableView to self.
Accordingly, implement the appropriate UITableViewDelegate methods, and set the delegate property of your tableView to self.
See the documentation for details on which methods are required, and which optional methods you might want to implement.
Don't forget to advertise in your .h file that your Class conforms to both protocols:
#interface MyBusinessesController : UIViewController <UITableViewDataSource, UITableViewDelegate>
You can make the tableView refresh its content by calling [itemList reloadData].
Table views work differently to what you appear to be used. You don't loop over your data and fill the table. Instead, you set yourself as table's delegate and then the table will ask you:"How much data do you have, what data do you want at row 5" and so on.
I'd really suggest you go over this great tutorial here:
http://kurrytran.blogspot.com/2011/10/ios-5-storyboard-uitableview-tutorial.html
Instead of looping through the array and pulling out the string values you can let the data source methods for UITableView handle this. So in cellForRowAtIndexPath method you would index your items_array with the index path as such:
NSDictionary *dict = [items_array objectAtIndex:[indexPath row]];
Then you would pull the strings out of the dictionary like you did in the loop and set the title for the cell to the string. For selecting the cell, you can write your code in the didSelectRowAtIndexPath method.
Here is an example from a project I was working on:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [items_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault)
reuseIdentifier:#"cell"];
NSDictionary *dict = [items_array objectAtIndex:[indexPath row]];
cell.textLabel.text = [dict objectForKey:#"item_name"];
return cell;
}
The first method specifies the number of sections you want in your table. If you want a very simple table this will be 1. The second method is the number of rows. This will be the number of items in your items_array so: [items_array count]. The third method creates a cell based on the index. It will go from section 0 to the number of sections you specify and from row 0 to number of rows per section you specify. So now instead of looping you can just index out your array. [indexPath section] gives the section number and [indexPath row] gives the row number.
*I know I should probably dequeue cells before making new ones but my array is very small.

Resources