Im developing an iOs application and i have an array of objects each object has a name, id, amd describtion. i want to display the name in the table view cell and the description in the detailview controller.
I know there are plenty of tutorial it wouldnt work for my case i think.
Where should implement the array in which class the view controller or the class model or the array class model.
May be you can start to hard init your array of objects in your tableViewController viewDidLoad.
#import "TableViewController.h"
#interface TableViewController ()
#property (strong, nonatomic) NSMutableArray *myData;
#end
#implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myData = [[NSMutableArray alloc]init];
YourObectClass *myObject;
for (int i = 0; i < 20; i++) {
myObject = [[YourObectClass alloc] init];
myObject.name = [NSString stringWithFormat:#"Object:%d",i];
[self.myData addObject:myObject];
]
//here you are... now use self.myData as your data source...
}
....
#end
Related
I am trying to display the contents of an array by calling a method in a different class that loops through the array and appends a string. However it is not displaying anything when i segue to that view. I have added breakpoints to check if there is anything in the array and the data is definitely being stored inside.
Is there a reason why this is happening?
Portrait class where i want all the array contents to be displayed
portrait.h
#import <UIKit/UIKit.h>
#import "Brain.h"
#interface PortraitTape : UIViewController
#property (weak, nonatomic) IBOutlet UITextView *equationView;
#property (nonatomic,strong) Brain *brain;
#end
portrait.m
#import "PortraitTape.h"
#interface PortraitTape ()
#end
#implementation PortraitTape
#synthesize brain = _brain;
#synthesize equationView;
- (Brain *) brain{
if (!_brain)_brain =[[Brain alloc]init];
return _brain;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *tape;
tape = [self.brain gettape];
equationView.text = tape;
}
Brain.m class method that hashe array and data is being inserted into. This method is called in the portrait class.
-(NSString*) gettape {
NSMutableString *tape = [[NSMutableString alloc]init];
for(NSString * myStr in _equation) {
//tape = myStr;
[tape appendFormat:#"\n%#",myStr];
}
return tape;
}
Super basic questions, which i'm having problems with.
How do i add multiple objects to my NSMutableArray? (Now i only add one with self.itemsArray[0] = iPhoneItem; )
How do i retrieve for the first objects property (itemName)?
I have a calss: Item - which looks like follows.
Item.h
#interface Item : UITableViewController
#property (nonatomic, copy) NSString *itemTitle;
- (id)initWithItemTitle:(NSString *)aTitle;
#end
Item.m
#interface Item ()
#end
#implementation Item
- (id)initWithTitle:(NSString *)aTitle {
self = [super init];
if (self) {
self.itemTitle = aTitle;
}
return self;
}
#end
And now i just want to create a few objects, add them in to an NSMutableArray and retrieve the itemTitle property.
ViewController.m - (.h has no additional changes from standard "create singel view application"
#import "ViewController.h"
#import "Item.h"
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *itemsArray;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Item *iPhoneItem = [[Item alloc] initWithItemTitle:#"iPhone"];
Item *iPadItem = [[Item alloc] initWithItemTitle:#"iPad"];
Item *macBookPro = [[Item alloc] initWithItemTitle:#"MacBookPro"];
self.itemsArray[0] = iPhoneItem;
NSLog(#"%#", self.itemsArray[0].itemTitle); //How would i do this?
}
#end
Best regards, iOS-rookie.
You can simply check iOS reference, no need to ask questions: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/instm/NSMutableArray/addObjectsFromArray:
Anyway, here is an example:
[itemsArray addObjectsFromArray: #[obj1, obj2]]; //adding multiple objects
((Item *)[itemsArray firstObject]).itemTitle //get title of your object
It is bad practice to access properties for an object in an array directly like :
self.itemsArray[0].itemTitle
It is cleaner to:
Item iPhoneItem = (Item)[itemsArray objectAtIndex:0];
NSLog(#"%#", iPhoneItem.itemTitle);
Also keep in mind that you can use [itemsArray firstObject]; and [itemsArray lastObject];
In my iPhone app I want to show a table view with section headers.
I have a datasource like this(Example)
(
{date : 12-10-2014 rowdata:abc},
{date : 12-10-2014 rowdata:pqr},
{date : 12-10-2014 rowdata:xyz},
{date : 13-10-2014 rowdata:123},
{date : 13-10-2014 rowdata:780},
{date : 14-10-2014 rowdata:tuv},
)
I want to show the section header as the date - and have to show row data in it like this
(just consider it as a format of table view-dates are it header views and below rows)
12-10-2014
abc
pqr
xyz
13-10-2014
123
780
13-10-2014
tuv
please give me a logic to do how to change or create new arrays with my data source, I am clear working with sectioned tableview and header views.
i can create a seperate array with dates for header view, but how can I show rowdata under every section, because in every section row starts with index 0.
You are basically asking how to categorise your rowdata data by its date key.
Simple. You need to do the following:
Create data models for your data couplets so that its nicer to populate your table with and store in arrays :)
Create a dictionary that will store the date as keys - you can imagine them as categories - and the row data as objects stored in an array for each category.
Step 1:
Create your custom data model to make data management more easier and cleaner.
Create two new files called rowDataModel.h and rowDataModel.m. They will be a subclass of the NSObject class.
This is what your .h file would look like:
#import <Foundation/Foundation.h>
#interface rowDataModel : NSObject
#property (nonatomic, retain) NSString * rowDataDate;
#property (nonatomic, retain) NSString * rowDataInformation;
-(id)initWithJSONData:(NSDictionary*)data;
#end
and in your .m file you will have this:
#import "rowDataModel.h"
#implementation rowDataModel
#synthesize rowDataDate;
#synthesize rowDataInformation;
-(id)initWithJSONData:(NSDictionary*)data{
if (self = [super init]) {
self.rowDataDate = [data objectForKey:#"date"];
self.rowDataInformation = [data objectForKey:#"rowdata"];
}
return self;
}
#end
We are doing this as this will contain easy to work with containers. Its a good way to manage your custom json objects too.
Step 2
Now in your view controller where you will be populating the database and categorising your data, make sure you import your custom rowDataModel.h file
NSMutableDictionary *myData = [[NSMutableDictionary alloc] init];
//Have a for loop that iterates through your array
for(NSDictionary *currentItem in serverArray){
RowData *newItem = [[RowData alloc] initWithJSONData:currentItem];
//If category the date key does not exist, then create a new category for it
if([myData objectForKey:newItem.rowDataDate] == nil){
//We want to create an array for each category that will hold all the row datas
[myDate setObject:[NSMutableArray new] forKey:newItem.rowDataDate];
}
//Grab the array from a particular category and add the current item to this category
[[myDate objectForKey:newItem.rowDataDate] addObject:newItem];
}
Now when you are populating your table delegate methods, in your titleForHeader tableview delegate methods, you simply grab the category titles: the dates from your myData dictionary using the allKeys property, and call the `objectForIndex: method for the section counter in your delegate method, ad you use that string to set the title of your header view by using the titleForHeader table view delegate method.
And in your cellForRowAtIndexPath: delegate method, you simply grab the correct category in your myData array by using the keys, and then access the individual objects in the array based on the row count.
And thats all bro. Goodluck
disclaimer, I have not tested this code, this should work right off the bat :)
The best way to do this would be creating a custom object, let's call it MyDate. My date would have two properties: a date, and an array.
#interface MyDate
#property NSDate *date;
#property NSArray *items;
#end
You parse the string, and for each information bit, you check the date. If the date is not in the array you add it. Then you add the other string to the items array for the appropriate MyDate object.
This way, every object in items starts with index 0, just like the rows in each section. So managing your model this way makes it easy to handle the user interface.
You could do this with arrays and dictionaries but it get's a little messy and you are probably best of creating new objects that can handle this.
I would probably start with something that looks a little like this
#interface NMKSection : NSObject
#property (nonatomic, strong) NSDate *date;
#property (nonatomic, strong) NSArray *rows;
#end
#interface NMKDataSource : NSObject
#property (nonatomic, strong) NSArray *data;
#property (nonatomic, strong) NSArray *sectionSortDescriptors;
#property (nonatomic, strong) NSArray *rowSortDescriptors;
- (NMKSection *)sectionAtIndex:(NSInteger)index;
- (void)processData;
#end
This would then mean that your UITableViewDataSource can look very simple
- (void)methodToSetupDataSource
{
self.dataSource = [[NMKDataSource alloc] init];
self.dataSource.data = data
self.dataSource.sectionSortDescriptors = // optional;
self.dataSource.rowSortDescriptors = // optional;
[self processData];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NMKSection *section = [self.dataSource sectionAtIndex:section];
return [self.dataFormatter stringFromData:section.date];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = // get cell
id row = [self.dataSource sectionAtIndex:indexPath.section].rows[indexPath.row];
// configure cell
return cell;
}
To achieve this all the heavy lifting is hidden in the NMKDataSource. The implementation fo NMKSection can just be left blank as it will contain no logic
#implementation NMKSection
#end
All the hard work is started from processData
#interface NMKDataSource ()
#property (nonatomic, strong) NSArray *sections;
#end
#implementation NMKDataSource
- (id)init;
{
self = [super init];
if (self) {
_sections = [[NSMutableArray alloc] init];
}
return self;
}
- (NMKSection *)sectionAtIndex:(NSInteger)index;
{
return self.sections[index];
}
- (void)processData
{
if (self.sectionSortDescriptors) {
self.sections = [self.unsortedSections sortedArrayUsingDescriptors:self.sectionSortDescriptors];
} else {
self.sections = [self.unsortedSections copy];
}
}
- (NSDictionary *)groupedData;
{
NSMutableDictionary *groupedData = [[NSMutableDictionary alloc] init];
[self.data enumerateObjectsUsingBlock:^(NSDictionary *row, NSUInteger idx, BOOL *stop) {
NSString *key = row[#"date"];
NSMutableArray *rows = groupedData[key];
if (!rows) {
groupedData[key] = rows = [[NSMutableArray alloc] init];
}
[rows addObject:row[#"rowdata"]];
}];
return groupedData;
}
- (NSArray *)unsortedSections;
{
NSMutableArray *unsortedSections = [[NSMutableArray alloc] init];
[self.groupedData enumerateKeysAndObjectsUsingBlock:^(NSDate *date, NSArray *rows, BOOL *stop) {
[unsortedSections addObject:({
NMKSection *section = [[NMKSection alloc] init];
section.date = date;
section.rows = rows;
if (self.rowSortDescriptors) {
section.rows = [rows sortedArrayUsingDescriptors:self.rowSortDescriptors];
}
section;
})];
}];
return [unsortedSections copy];
}
#end
This was written in the browser so it's not been tested. The code it just an example of where I would probably start and develop this further until I was happy
I've read through many posts here but I can't seem to make my array available in another class.
I want to access the array plusTransactions in CPPHistoryViewController (a table controller, in a container as a child of CPPSecondViewController) from class CPPSecondViewController.
CPPSecondViewController.h
#import <UIKit/UIKit.h>
#interface CPPSecondViewController : UIViewController <UIWebViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedController;
#property (weak, nonatomic) NSMutableArray *plustransactions;
#property (weak, nonatomic) NSMutableArray *campustransactions;
#property (weak, nonatomic) NSMutableArray *mealtransactions;
#end
CPPSecondViewController.m
#import "CPPSecondViewController.h"
#interface CPPSecondViewController ()
#implementation CPPSecondViewController
#end
#synthesize plustransactions = _plustransactions;
#synthesize campustransactions = _campustransactions;
#synthesize mealtransactions = _mealtransactions;
...
_plustransactions = newPlustransactions;
NSLog(#"%#", newPlustransactions);
NSLog(#"%#%lu", #"That's how many: ", (unsigned long)_plustransactions.count);
CPPHistoryViewController *historyView = [[CPPHistoryViewController alloc]init];
[historyView.tableView reloadData];
This is good, returns all of my array items and count is 7.
CPPHistoryViewController.h
#import <UIKit/UIKit.h>
#interface CPPHistoryViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
#end
CPPHistoryViewController.m
#import "CPPHistoryViewController.h"
#import "CPPSecondViewController.h"
#import "CPPPlusTransaction.h"
#import "CPPCampusTransaction.h"
#import "CPPMealTransaction.h"
#import "CPPHistoryCell.h"
#interface CPPHistoryViewController ()
#end
#implementation CPPHistoryViewController
...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
CPPSecondViewController *secondView = [[CPPSecondViewController alloc] init];
NSMutableArray *plusTransactions = [[NSMutableArray alloc]init];
plusTransactions = secondView.plustransactions;
NSMutableArray *campusTransactions = [[NSMutableArray alloc]init];
campusTransactions = secondView.campustransactions;
NSMutableArray *mealTransactions = [[NSMutableArray alloc]init];
mealTransactions = secondView.mealtransactions;
NSLog(#"Table formatting called");
NSLog(#"%ld", (long)secondView.segmentedController.selectedSegmentIndex);
switch (secondView.segmentedController.selectedSegmentIndex) {
case 0:
NSLog(#"%#%lu", #"PlusTransactions", (unsigned long)plusTransactions.count);
return plusTransactions.count;
break;
case 1:
NSLog(#"%#%lu", #"CampusTransactions", (unsigned long)campusTransactions.count);
return campusTransactions.count;
break;
case 2:
NSLog(#"%#%lu", #"MealTransactions", (unsigned long)mealTransactions.count);
return mealTransactions.count;
break;
}
return 1;
}
...
#end
Here's where things get weird. Any array I call from here returns with a count of 0. Any ideas?
I assume what you want is to get the array data stored in CPPSecondViewController to be availalbe in CPPHistoryViewController. But as per the code you posted,
CPPHistoryViewController *historyView = [[CPPHistoryViewController alloc]init];
[historyView.tableView reloadData];
This just create new instance and the tableView inside the view is reloaded. But in cellForRowAtIndexPath, you are creating new instance of CPPSecondViewController, thats wrong.
What you can do is, simply pass the CPPSecondViewController instance before reloading tableView.
In CPPHistoryViewController.h, create a property for keeping secondView like this
#property (strong, nonatomic) CPPSecondViewController *secondView;
then, change your code in CPPSecondViewController like below:
CPPHistoryViewController *historyView = [[CPPHistoryViewController alloc]init];
historyView.secondView = self;
[historyView.tableView reloadData];
Also, remove alloc init statements from cellForRowAtIndexPath, just use secondView.plustransactions here.
Hope this helps!
CPPSecondViewController *secondView = [[CPPSecondViewController alloc] init];
Here you are creating a new object, So all values are nill.
Here you can only set values in to second view controller.
in your History class, you nedd to create a property of a second class they you can set value in to Second class
#property (nonatomic, retain) Secondclass* secondclass;
[secondClass setAry: ary];
CPPSecondViewController *secondView = [[CPPSecondViewController alloc] init];
in this code, the view controller is just init, the properties is all nil, it's a new view controller instance.
setup properties in init method, or access the second view's view property, to load view, to trigger the property initialize.
if you want reference the second view controller from history view controller, you can add a property in history view controller refer to second view controller.
in CPPHistoryViewController.h
#property (weak, nonatomic) CPPSecondViewController *secondViewController;
and set this property in your show code.
in CPPSecondViewController.m
_plustransactions = newPlustransactions;
NSLog(#"%#", newPlustransactions);
NSLog(#"%#%lu", #"That's how many: ", (unsigned long)_plustransactions.count);
CPPHistoryViewController *historyView = [[CPPHistoryViewController alloc]init];
historyView.secondViewController = self;
[historyView.tableView reloadData];
Goal of program: Enter numbers on a viewController. When the user hits Submit button, the data entered by user is passed on to a different class for displaying on a different viewController.
Problem: I am trying to access an instance variable (numberList) in an instance method (-(void)insertNewNumber:(Numbers *)tempNumber), but it never gives me the correct output. But when I access the same variable through a protocol method of UITableViewDataSource, I get the correct answer. I figured this by using NSLog in instance method and protocol method.
Since I have declared numberList as a property variable, I was thought that I can access it from anywhere in the program and get the correct value stored in it. But compiler returned 0 for the NSLog statements when they were called from instance method. When the NSLog statements from protocol method, showed the correct result.
Please help me understand why is this occurring and how can I add elements into an array from any method in a program.
Thank you!
Here's the relevant code I am working on:
Numbers.h:
#interface Numbers:NSObject
#property (strong, retain) NSString *ID;
#property (strong, retain) NSInteger *number;
#end
Numbers.m
#implementation Numbers
#synthesize ID, number;
#end
DisplayNumbers.h
#import <UIKit/UIKit.h>
#import "Numbers.h"
#interface DisplayNumbers : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) NSMutableArray *numberList;
- (void)insertNewNumber:(Numbers *)tempNumber;
#end
DisplayNumbers.m:
#implementation DisplayNumbers
#synthesize numberList;
- (void)viewDidLoad
{
[super viewDidLoad];
numberList = [[NSMutableArray alloc] init];
Numbers *num0 = [[Numbers alloc] init];
Numbers *num1 = [[Numbers alloc] init];
num0.ID = [NSString stringWithFormat:#"ID 0"];
num0.number = 1111111111;
num1.ID = [NSString stringWithFormat:#"ID 1"];
num0.number = 2222222222;
[numberList addObject:num0];
[numberList addObject:num1];
}
- (void)insertNewNumber:(Numbers *)tempNumber
{
NSLog(#"numberList.count (in -(void)insetNewNumber) = %d", numberList.count);
[numberList addObject:tempNumber];
NSLog(#"numberList.count (in -(void)insetNewNumber) = %d", numberList.count);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"numberList.count (in -(NSInteger)tableView:...) = %d", numberList.count);
Numbers *temp = [[Numbers alloc] init];
temp.ID = #"hi";
temp.Number = 1234;
[numberList addObject:temp];
NSLog(#"numberList.count (in -(NSInteger)tableView:...) = %d", numberList.count);
return numberList.count;
}
#end
Edit 1: Calling of insertNewNumber:.
This method is being called from a different class.
InputNumber.h:
#import <UIKit/UIKit.h>
#import "DisplayNumbers.h"
#interface InputNumber:UIViewController
#property (retain, strong) NSInteger *enteredNumber;
-(void)enteredNumber;
#end
InputNumber.m
#implementation InputNumber
#synthesize enteredNumber;
-(void)enterNumber
{
DisplayNumber *temp = [[DisplayNumber alloc] init];
[temp insertNewNumber:enteredNumber];
}
#end
Since you allocate your numberList in the ViewDidLoad method, be sure to call your insertNewNumber method after the call to ViewDidLoad.
I believe that
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
Numbers *temp = [[Numbers alloc] init];
temp.ID = #"hi";
temp.Number = 1234;
[self insertNewNumber:temp];
return contactList.count;
}
works, right?
If you need to call your insertNewNumber method before the call to ViewDidLoad, allocate your numberList
numberList = [[NSMutableArray alloc] init];
in an overloaded initWithNibName:bundle: method.
Your code doesn't have an ivar called numberList. You need to call the property like this:
self.numberList = [NSMutableArray array];
No need to alloc/init since you're already using a strong reference.
Every time you refer to that numberList object, you need to use self.numberList.
[self.numberList addObject:num0];
[self.numberList addObject:num1];