I have declared an array in ViewController and displaying it in table view. I am passing values for an array from EditViewController. But the values are not displaying in table view. I am using following code.
ViewController.h
#property (nonatomic, strong) NSMutableArray *tableData;
ViewController.m
ViewDidLoad:
tableData = [NSMutableArray arrayWithObjects:#"",nil];
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
EditViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewController *vc;
vc = [segue destinationViewController];
NSString *str = [NSString stringWithFormat:#"%ld", selectedRow];
[vc.tableData addObject:str];
}
Please advice.
Connect the delegate and datasource to self in the viewDidLOad of editViewController
tableView.delegete=self;
tableView.Datasource=self;
If there is no data in the tableview itself, hit a breakpoint at
cellForRowAtIndexPath,
and Still if it dsnt hits the breakpoint,connect the Delegate and Data source for the tableview with the View Controller.
[EDIT]
If it is still not called, go to storyboard, check if the bounds of the tableview, is more than that of the vc, that means, check if the tableview is inside the view controller and no part of the tableview is crossing the bounds of the view controller.
Plz make sure you have
-tableView:numberOfRowsInSection:
method defined. This method should return value greater than 0 so that
-tableView:cellForRowAtIndexPath:
gets called.
you are add string to nsarray object which is not allocated.
you have to create nssarray with string and pass to the vc.tableData.
There may be a few problems with this.
First, it's best to set a the NSMutableArray property "tableData" to an existing array passed in during the segue. Right now you're adding a single string to a mutable array which, unless you wrote a custom initializer for the ViewController in which you alloc-init'ed the NSMutableArray, it can't exist until ViewDidLoad which is after the segue is performed, so you're passing the string to black abyss of "nil".
It's best to use base types as receiving properties in prepareForSegue, and then in your case to pass the ViewController's array an already existing array from the EditViewController.
Also, you may not be telling the view controller how many cells to actually create. Make sure numberOfSectionsInTableView returns a value (in this case just 1), and that numberOfRowsInSection returns "[self.tableData count]".
And if you didn't create ViewController as inheriting from UITableViewController, you'll need to set that, and connect the delegate and datasource manually in the storyboard like Light Yagami pointed out. Though it would probably be easier to just create a new custom class file that inherits from UITableViewController because it will give you some good boilerplate code.
And also make sure that in your storyboard, your TableViewController's class is set to your custom class file.
I hope you did not pass numberOfSectionsInTableView as 0. Please check that once. It must be 1 or more based on requirement. And same for numberOfRowsInSection.
Remove this line from your ViewDidLoad Method
tableData = [NSMutableArray arrayWithObjects:#"",nil];
Related
I have this NSDictionary:
{
Name =
(
"Lucas",
"Tom"
);
Surname =
(
"Jhon",
"Smith"
"Hop"
);
Name is a simple NSArray and Surname is a NSMutableArray.
Ok now my problem is this:
Starting from this dictionary, I must show in UITableView the key of each element of the NSDictionary. For example, in this case, UITableView will have two items, one call Name and the other Surname.
When I click on an element of the UITableView I will have to go to another controller that will show me all the data of the clicked cell. If for example, I click on Surname, when I open the new controller, I'll have to get it like Jhon, Smith and Hop.
To get started, I tried to show the UITableView before all the keys by writing:
self.KeyArray = [myDictionary allKeys];
and in the cellForRowAtIndexPath method:
cell.textLabel.text = [self.KeyArray objectAtIndex: indexPath.row];
But this is a wrong approach, because I'm going to lose all the information related to that specific key. Do you have any idea how I can do it?
You can use delegate to send that NSMutableArray to another controller.
Lets say your first view controller is "A" which has those name and surname keys. And second Controller is "B" which will has the array that you want to send.
Now,
1. Create a protocol in A controller.
2. Create the delegate object of that protocol.
3. Create 1 Method in A controller which can have a parameter Like :- (NSMutableArray *).
4. Implement that protocol in to B Controller.
5. Declare the method in Controller B that you defined in Controller A
6. Call that method with the help of delegate object in didSelectRowAtIndexPath and Pass that Object in that method.
7. Now you have the NSMutableArray in that method and you are free to use that values.
You can do like that in didSelectRowAtIndexPath write below code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *keyOfMainDic = [self.KeyArray objectAtIndex:indexPath.row]; // in the keyOfMainDic, you will get selected key name of your main dictionary
NSMutableArray *temArray = [yourMaindict objectForKey:keyOfMainDic] // You will get array of specific key.
// Here you just need to pass "temArray" to your destination controller.
}
First you should define a segue from your view controller that has tableview to your detail controller and give it an identifier in storyboard.
Then define a property into your detail controller header inherit from KeyArray type.
After that, just code it like below. This is just suggestion, please use a model for your array instead of dictionary.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.KeyArrayItem = [self.KeyArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"yourSegueID" sender:self.KeyArrayItem];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
AnotherController *controller = segue.destinationViewController;
controller.KeyArrayItem = sender;
}
I am new to iOS development and I am having a trouble with counting objects from Array which contains Dictionaries.
My data structure looks like this and it's located in another custom class:
Library header file
Library implementation file
There will be quite a lot of them (now only 4 just for testing) and I need to count NSStrings with key kEviela.
I need this counting to calculate number of rows required for my tableView:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ?;
Also I have a detailView where I need to show each of this String separately. So how can I do this in prepareForSegue method?
It's just
return _library.count;
which is the number of dictionaries in the array.
Anyway I recommend to map the dictionary to a custom class.
To get an array of all values for key kEviela write
NSArray *kEvielaArray = [_library valueForKey: kEviela];
This is one of the rare cases where valueForKeyis intended as a KVC method.
First of all,i think you can show number of rows by counting your dictionary objects. I use NSMutableArray converting from dictionary because it's easier for me to manipulate.It's totally personal though.
Also I have a detailView where I need to show each of this String separately.
What you can do?
There is function called didSelectRowAtIndexPath delegate method.
When you select row this function is called.In this function you grab your detailView controller and keep value to one of it's variable(NSString or Something) according to your data.
you can call segue programmatically from here after assigning value.
As an example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
DetailViewController *detailVC = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
detailVC.userName = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
}
or, If you don't want to use like this, then in prepareForSegue method (what you called)
grab your destination view controller and assign value just like previous. That's it.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
vc.dictionary = [youdictionary mutableCopy];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _library.count;
}
Above is the Way you get the count of array check it out.
Here first you have Array and then you can find out the dictionary value.
NSString *kEvielaValue = [_library valueForKey: "kEviela"];
Try this [[_library valueForKey: kEviela]count];
[_library valueForKey: kEviela] will pick up an NSArray that contains all the values of kEviela and the count message will give you the number of those elements from the main array of _library
I am trying to embed a UITableView in my View Controller (not a TableViewController).
I am unable to get any of my data to show.
Here is the relevant code:
M file:
#interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate, UITableViewDelegate, UITableViewDataSource>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSMutableArray *Device_array_name;
#end
.
.
.
- (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=self.Device_array_name[indexPath.row];
return cell;
}
I've also defined number of sections and rows, and my array does indeed have content. I'm pretty new to iOS development so I've no doubt missed something.
Thanks
Delegates & Datasources should be defined for UI Controls to get called their respective delegates.
For Instance : In your viewDidLoad function define
tableView.delegate = self
tableView.datasource = self
It will work.
Set the array allocation in your view did load.
Device_array_name=[NSMutableArray alloc]init];
Set the tableview delegates in viewdidLoad
tableview.delegate=self;
tableview.datasource=self;
After give the count of an array in Number of rows in section
return Device_array_name.count;
In your cellForRow AtIndexpath method
cell.textLabel.text=[self.Device_array_name objectAtIndex:indexPath.row];
There could be 4 reason (most probably)
1> You delegate and datasource are not set
tableView.delegate = self
tableView.datasource = self
2> Your datasource array is nil (Device_array_name)
3> Your IBOutlet is not connected with tableview
4> Your tableview frame is becoming zero due to autloayout or something else (check console at runtime)
I think you just need to initialize the delegate and dataSource for your tableView property to your ViewController.
If you embed this way, you don't have default setting for the UITableView like you have when you use UITableViewController directly. You will need to set it up by yourself. Most likely, it's because you have not wired up your delegation object. Second will be, your UITableView is invisible. That also causes the problem because the delegate methods will not be called.
i think go to storyborad and set delegate,datasource in there.if you using by storyborad.i hope will work.
Here is my list of the possible problems:
The #IBOutlet for the table view is not connected in Interface Builder. Solution: check connection in Interface Builder.
The outlet is set, but the view controller placed in the storyboard is not of your custom UIViewController subclass, but the default UIViewController. In this case, none of your code will be executed. Solution: specify the view controller's class is the identity inspector (center tab).
The dataSource property of the table view is not set to your view controller. Solution: Assign it in either Interface Builder (storyboard) or programmatically inside viewDidLoad() or later.
You are not implementing the UITableviewDataSource protocol method:
tableView(_:numberOfRowsInSection:) (i.e., the table view "thinks" it has 0 rows to display). In this case, tableView(_:cellForRowAtIndexPath:) will not be called (you can confirm this by placing a break point). Solution: Implement the method and return the count property of your model object array.
The array that serves as the data source for your table view is empty (has zero elements). Solution: Make sure the array contains your model objects.
I might have left some other common mistake out... Let me know.
Addendum: Unless you have a compelling reason not to, I would strongly suggest that you use a stock UITableViewController instead of manually adding a UITableView to a plain UIViewController. You get a lot of functionality and setup for free.
I won't go into the WHY on this one, I'll just explain what I need.
I have a property in my implementatioon file like so...
#property (nonatomic, strong) MyCustomCell *customCell;
I need to initialize this on viewDidLoad. I return it as a row in cellForRowAtIndexPath always for the same indexPath, by returning "self.customCell".
However it doesn't work, I don't appear to be allocating and initializing the custom cell correctly in viewDidLoad. How can I do this? If you know the answer, save yourself time and don't read any further.
Ok, I'll put the why here in case people are curious.
I had a table view which was 2 sections. The first section would always show 1 row (Call it A). The second section always shows 3 rows (Call them X, Y, Z).
If you tap on row A (which is S0R0[Section 0 Row]), a new cell would appear in S0R1. A cell with a UIPickerView. The user could pick data from the UIPickerView and this would update the chosen value in cell A.
Cell X, Y & Z all worked the same way. Each could be tapped, and they would open up another cell underneath with their own respective UIPickerView.
The way I WAS doing this, was all these cell's were created in the Storyboard in the TableView, and then dragged out of the View. IBOutlets were created for all. Then in cellForRAIP, I would just returned self.myCustomCellA, or self.myCustomCellY.
Now, this worked great, but I need something more custom than this. I need to use a custom cell, and not just a UITableViewCell. So instead of using IBOutlets for all the cells (8 cells, 4 (A,X,Y,Z) and their 4 hidden/toggle-able UIPickerView Cell's), I created #properties for them in my implementation file. But it's not working like it did before with the standard UITableViewCell.
I'm not sure I'm initializing them correctly? How can I properly initialize them in/off viewDidLoad so I can use them?
.m
#interface MyViewController ()
#property (strong, nonatomic) MyCustomCell *myCustomCellA;
...
viewDidLoad
...
self.myCustomCellA = [[MyCustomCell alloc] init];
...
cellForRowAtIndexPath
...
return self.myCustomCellA;
...
If only I understood your question correctly, you have 3 options:
I would try really hard to implement table view data source with regular dynamic cells lifecycle in code and not statically – this approach usually pays off when you inevitably want to modify your business logic.
If you are certain static table view is enough, you can mix this method with overriding data source / delegate methods in your subclass of table view controller to add minor customisation (e.g. hiding certain cell when needed)
Alternatively, you can create cells using designated initialiser initWithStyle:reuseIdentifier: to instantiate them outside of table view life cycle and implement completely custom logic. There is nothing particular that you should do in viewDidLoad, that you wouldn't do elsewhere.
If you have a particular problem with your code, please post a snippet so community can help you
I suggest you to declare all your cells in storyboard (with date picker at right position) as static table and then override tableView:heightForRowAtIndexPath:
Define BOOL for determine picker visibility and its position in table
#define DATE_PICKER_INDEXPATH [NSIndexPath indexPathForRow:1 inSection:0]
#interface YourViewController ()
#property (assign, nonatomic) BOOL isPickerVisible;
#end
Then setup initial value
- (void)viewDidLoad {
[super viewDidLoad];
self.isPickerVisible = YES;
}
Override tableView delegate method
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:DATE_PICKER_INDEXPATH] && !self.isPickerVisible) {
return 0;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
And finally create method for toggling picker
- (void)togglePicker:(id)sender {
self.isPickerVisible = !self.isPickerVisible;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
which you can call in tableView:didSelectRowAtIndexPath:
According to your problem, you can create pairs (NSDictionary) of index path and bool if its visible and show/hide them according to that.
Here's what I was looking for:
MyCustomCell *cell = (MyCustomCell *)[[[UINib nibWithNibName:#"MyNibName" bundle:nil] instantiateWithOwner:self options:nil] firstObject];
I try to display objects of an array in a tableview.
This is a single screen app, I'm using storyboard.
When running - the tableview appears as an empty grid. the data of the objects is not displayed. what may cause this?
Having 2 required methods numberOfRowsInSection and cellForRowAtIndexPath I suspect the last one.
The .h file contains this row:
#interface MYViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
I set the delegate & datasource via the code as you suggested. still empty grid.
This is my implementation:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [listRecipes.recipeArray count]; }
-(UITableViewCell )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString cellIdentifier = #"ListCellIdentifier"; MYCustomListCell* listCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; NSString* dataString = listRecipes.recipeArray[indexPath.row]; listCell.listName.text = dataString; listCell.imageView.image = [UIImage imageNamed:dataString]; return listCell; }
I try to display data from an array in MVC .
If the array is local - the data is displayed
Can you please advise what to do?
Thank you in advanced.
Always remember to hook up your table's delegate and datasources.
Being a UIElement on a UIViewController that conforms to these two protocols is not enough for Xcode to assume that that UIViewController should be the delegate and/or datasource for the table.
Right click on your tableview, drag from delegate & datasource to your UIViewController.
You can also set these programmatically via:
self.table.datasource = self;
self.table.delegate = self;
And if you're still having trouble after this, you'll have to show us how you're implementing the datasource protocol methods.
Check if your initialisation of tableview delegate and datasource would be before the recipeArray is initialised. In this case you will have to tableView.reload() after the items are added to recipeArray .