TableView IndexPath.row not Assignable - ios

I would like to assign tableView indexPath to one of the view controller variable. However, it is strange to me that it assigns one of them, no matter which row I choose, it always assigns 0.
As you can see below code, iVC.virdsection=indexPath.row works very well, but sVC2.evradID=indexPath.row always 0.
//
// TableViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#import "SubViewController.h"
#interface TableeViewController : UITableViewController
#property (nonatomic,strong)NSArray *contentArray;
#property (strong,nonatomic)DetailViewController *detailViewController;
#property (strong,nonatomic)SubViewController *subViewController;
#end
//
// TableViewController.m
#import "TableViewController.h"
#import "DetailViewController.h"
#import "SubViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize contentArray;
#synthesize detailViewController;
#synthesize subViewController;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *iVC = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
self.detailViewController = iVC;
iVC.virdSection = indexPath.row;
iVC.navigationItem.title=[NSString stringWithFormat:#"%d.Vird",indexPath.row+1];
SubViewController *sVC2 = [[SubViewController alloc] initWithNibName:#"SubViewController" bundle:[NSBundle mainBundle]];
self.subViewController = sVC2;
sVC2.evradID=indexPath.row;
[self.navigationController pushViewController:iVC animated:YES];
}
Here is my SubViewController.h
// SubViewController.h
#import <UIKit/UIKit.h>
#interface SubViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *evradLabel;
-(void)evradCall;
#property int evradID;
#end

The row 0 is the first row. If you log indexPath.row it will probably show all the indexes of the rows. 0 is technically correct. Try this code
NSUInteger row = 0;
NSUInteger sect = indexPath.section;
for (NSUInteger i = 0; i < sect; ++ i){
sVC2.evradID = i;
}
(I found this here)

Dumb question, but I've had it happen to me before, is sVC2 nil? You could have a problem instantiating sVC2.
It's kind of hard to tell what's going on from code posted.

Related

How to initiate a view controller from another view controller?

I have a table view controller called StackViewController, this is where I hold a list of todo's that has been created in CreateViewController...
I have an NSString property in StackViewController called currentTarget that represent the first to do in the stack:
import <UIKit/UIKit.h>
#interface StackTableViewController : UITableViewController
#property (nonatomic, strong) NSString *currentTarget;
#end
This property holds the first NSString object in the table view, I get it like this:
#import "StackTableViewController.h"
#import "Target.h"
#import "CoreDataStack.h"
#interface StackTableViewController () <NSFetchedResultsControllerDelegate>
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultController;
#end
#implementation StackTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.fetchedResultController performFetch:nil];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *target = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = target.body;
}
Now, when I log into my home page which called HomeViewController I want to initiate the StackTableViewController and get its currentTatget property value...
I know that there are delegate to help you notify other views when a change has happened, but in my case I want to get this property value before even I have been in this page (StackTableViewController), because the HomeViewController is the first view controller that is loaded (my initial view controller) and I what to access this property when I was just logged in to the app and populate a label with it.
How should I do this?
I thought maybe something like this:
#import "HomeViewController.h"
#import "CreateViewController.h"
#import "StackTableViewController.h"
#interface HomeViewController ()
#property (strong, nonatomic) IBOutlet UILabel *targetLabel;
#end
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
StackTableViewController *vc = [[StackTableViewController alloc] init];
NSString *current = vc.currentTarget;
self.targetLabel.text = current;
}
But i'm missing something here...my label is not populated...
I think there is something with the views lifecycle.
i'm a newbie please help me to figure this out...thanks
Don't do anything to do with graphics in viewDidLoad. The earliest you want to do it is in viewWillAppear (most of the time) and occasionally you will need to do it in viewDidAppear.
Try the same code in viewWillAppear and it should work.
Oh right, since your other viewController is setup in viewDidLoad, you need to call
[stackTableViewController view] on your stackTableViewController after you alloc init it. Seems weird, but this actually works. This is because the StackTableViewController doesn't have its calculation done when you initialize it, it runs through it in it's viewDidLoad delegate.
- (void)viewDidLoad {
[super viewDidLoad];
StackTableViewController *vc = [[StackTableViewController alloc] init];
[vc view];
NSString *current = vc.currentTarget;
self.targetLabel.text = current;
}

How to change tableview data with button press on a different view controller?

I am having a bit of trouble getting a button pressed on a ViewController to load a specific lot of information in an array for displaying on a UITableViewController.
I know you can do it with detecting the segue but I have tried this without - I had success. I read somewhere else how I can use tags on the button to identify it and I tried to use this but it only displays one set of data no matter what button I have pressed. I've tried swapping a lot of things around to try and get it to work but to no avail. I have a ViewController with the buttons on it, a TableViewController to display the arrays and a CellViewController to display the better description of the tableview info.
My code is pretty 'all over the shop' at the moment. I haven't included the Cell View controllers as I don't think they have that much relevance with what I want to do at this stage.The buttonviewcontroller is just a normal UIViewController and both buttons are linked as 'Button1'class in the storyboard. They have been given tags 0 and 1 which I believe is in under the 'view' subheading in the storyboard. Please alert me if this is wrong and I am missing something really obvious but that was the only place I could find 'tag'.
Honestly I don't know exactly what I'm doing in xcode as I'm not very familiar with it but seem to understanding parts of it. However, I'm not sure exactly what I'm doing wrong at the moment.
Code:
ButtonViewController.M (this is where the buttons are)
#import <UIKit/UIKit.h>
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController : UIViewController
-(IBAction) button_Clicked:(id)sender;
#property (strong, nonatomic) IBOutlet UIButton *Button1;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
-(IBAction) button_Clicked:(id)sender
{
//something here that is going wrong
tableViewController *tableVC = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
if(_Button1.tag==0)
{
tableVC.buttonSelected = 0;
}
else if(_Button1.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVC animated:YES];
[tableVC.tableView reloadData];
#end
tableViewController.h
#import <UIKit/UIKit.h>
#interface tableViewController : UITableViewController
#property (nonatomic, assign) int buttonSelected;
#property (nonatomic, strong) NSArray *Title;
//#property (nonatomic, strong) NSMutableArray *Title;
#property (nonatomic, strong) NSArray *Description;
//#property (nonatomic, strong) NSMutableArray *Description;
//Not sure if Mutable or normal array
#end
tableViewController.m
#import "tableViewController.h"
#import "TableCell.h"
#import "DetailViewController.h"
#import "ButtonViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_buttonSelected == 0)
{
_Title = #[#"Hamstring Muscle Tear",#"Lower Back Pain"];
_Description = #[#"Blahahaha", #"blahahaha2",#"blalalala3"];
[self.tableView reloadData];
}
else if (_buttonSelected == 1)
{
_Title = #[#"1",#"2",#"3"];
_Description = #[#"dededdededde", #"deddedede2",#"blalalala3"];
[self.tableView reloadData];
}
#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 _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row]];
}
}
#end
There are two ways to doing same.
Implement delegate method and call it on event.
You can fire NSPostNotification event from one controller to another controller.
Change the data, then post an NSNotification that it changed.
The table view data source observes the notification and calls [tableView reloadData]
You can find details how to do this in apple's sample code.

How can I link a button in iOS to change an array for a list view?

Not sure if the above is even my question as I am basically new to using objective-c and iOS and not sure if that's the right wording but anyway...
Basically I have completed this tutorial https://www.youtube.com/watch?v=ITUI7fukRO8 for using a tableView with an array of data.
The substance of the program consists of a navcontroller, tableviewController and a viewController for the extra detail of the table data.
Currently I have a button (from another viewcontroller) that is linking to my tableView.
How would I go about setting up and IF statement in regards to the button pressed (-as I need to link other buttons from other controllers) so that if a specific button is pressed, the array that is displayed in the tableView is different.
I'm currently thinking of doing a bunch of if, then, else statements and just manually changing the detail of the arrays.
Is this the way to go??
Or should I just set up another table view for each of my buttons.
I have a set of .h and .m for the tableCell, tableCellController, and the ViewController.
That probably didn't make a whole lot of sense but if you somewhat understand help would be appreciated.
Cheers
Edit: As you can see my code is pretty 'all over the shop' at the moment. I haven't included the Cell View controllers as I don't think they have that much relevance with what I want to do at this stage.The buttonviewcontroller is just a normal UIViewController and both buttons are linked as 'Button1'class in the storyboard. They have been given tags 0 and 1 which I believe is in under the 'view' subheading in the storyboard. Please alert me if this is wrong and I am missing something really obvious but that was the only place I could find 'tag'. ARRRG Objective-c is frustrating when you don't the language at all./
Updated Code as 21/03.
ButtonViewController.M (this is where the buttons are)
#import <UIKit/UIKit.h>
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController : UIViewController
-(IBAction) button_Clicked:(id)sender;
#property (strong, nonatomic) IBOutlet UIButton *Button1;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
-(IBAction) button_Clicked:(id)sender
{
//something here that is going wrong
tableViewController *tableVC = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
if(_Button1.tag==0)
{
tableVC.buttonSelected = 0;
}
else if(_Button1.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVC animated:YES];
[tableVC.tableView reloadData];
#end
tableViewController.h
#import <UIKit/UIKit.h>
#interface tableViewController : UITableViewController
#property (nonatomic, assign) int buttonSelected;
#property (nonatomic, strong) NSArray *Title;
//#property (nonatomic, strong) NSMutableArray *Title;
#property (nonatomic, strong) NSArray *Description;
//#property (nonatomic, strong) NSMutableArray *Description;
//Not sure if Mutable or normal array
#end
tableViewController.m
#import "tableViewController.h"
#import "TableCell.h"
#import "DetailViewController.h"
#import "ButtonViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_buttonSelected == 0)
{
_Title = #[#"Hamstring Muscle Tear",#"Lower Back Pain"];
_Description = #[#"Blahahaha", #"blahahaha2",#"blalalala3"];
[self.tableView reloadData];
}
else if (_buttonSelected == 1)
{
_Title = #[#"1",#"2",#"3"];
_Description = #[#"dededdededde", #"deddedede2",#"blalalala3"];
[self.tableView reloadData];
}
#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 _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row]];
}
}
#end
Do a CTRL - drag in Storyboard to create a IBAction for the button.
In the IBAction method, get the data you want for your data arrays (Images, Title, Description ref the tutorial you linked). Then call:
[tableview reloadData]
This will repopulate the tableview.

iOS Protocol Issues

I have been staring at code too long and know i am doing something silly here with my Protocols if someone could enlighten me that would be great.
Trying to get my areaNameLabel to change to cell.nameLabel.text across viewcontrollers.
FirstTableViewController.h
#import <UIKit/UIKit.h>
#import "FirstTableCell.h"
#import "SecondViewController.h"
#interface FirstTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, passNames>
#property (nonatomic, strong) NSString *passedNameString;
#property (strong, nonatomic) NSMutableArray *names;
FirstTableViewController.m
#import "FirstTableViewController.h"
#interface FirstTableViewController ()
#end
#implementation FirstTableViewController
#synthesize names;
#synthesize passedNameString;
- (void)viewDidLoad
{
[super viewDidLoad];
names = [NSMutableArray arrayWithObjects:#"Bondi", #"Miranda", nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
FirstTableCell *cell = (FirstTableCell *)[tableView cellForRowAtIndexPath:indexPath];
if ([cell.nameLabel.text isEqualToString:#"Bondi"]) {
SecondViewController *mapController = [[SecondViewController alloc] init];
NSString *passedName = cell.nameLabel.text;
mapController.passedNameString = passedName;
[mapController setDelegate:self];
self.tabBarController.selectedIndex = 1;
NSLog(#"Hola");
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Protocol Methods
-(void)setAreaName:(NSString *)areaName {
passedNameString = areaName;
}
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol passNames <NSObject>
-(void)setAreaName:(NSString *)areaName;
#end
#interface SecondViewController : UIViewController <RMMapViewDelegate>
#property (retain) id <passNames> delegate;
#property (nonatomic, strong) NSString *passedNameString;
#property (weak, nonatomic) IBOutlet RMMapView *mapView;
#property (weak, nonatomic) IBOutlet UILabel *areaNameLabel;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstTableViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController #synthesize areaNameLabel; #synthesize delegate, passedNameString;
- (void)viewDidLoad {
[super viewDidLoad];
passedNameString = areaNameLabel.text;
[[self delegate] setAreaName:passedNameString];
if ([areaNameLabel.text isEqualToString:#"Bondi"]) {
NSLog(#"You got it!");
}
}
Any other critiques feel free to throw in - I've had a look at some other Protocol questions and examples but i know it is something obvious i am missing.
The problem is that your SecondViewController has no relationship to the passNames protocol (being declared in the same header does not count).
Since protocol methods need to be implemented (or their implementation be inherited from the base) and your SecondViewController does not do that, you cannot call setAreaName: without triggering an error.
If you would like to use a common protocol in two view controllers, you need to do this:
Give passNames protocol a more conventional name that starts in a capital letter, and put it in a separate header file
Include that header in both view controllers (the #import "SecondViewController.h" in the FirstTableViewController.h does not look right)
Put implementations of setAreaName: in both view controllers.
Note that you cannot put the common functionality in a superclass, because your view controllers inherit from different bases (i.e. UIViewController and UITableViewController).

How to correctly access a variable from another class in Objective C

I have looked at various forums trying to find a solution to this problem. I currently have 2 classes, BluetoothViewController and AccountViewController. What I am trying to do is pass an account that the user selects from the AccountViewController to BluetoothViewController, so I can use that string later in the BluetoothViewController. What I have done is create an instance of AccountViewController in BluetoothViewController.h and I have created a property for the string in the AccountViewController.h file. The string that I am trying to access is "account8"
My AccountViewController.h file:
#interface AccountViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *tableData;
int cellValue;
NSString *cellContents;
NSString *account8;
}
#property (nonatomic, retain) NSArray *tableData;
#property (nonatomic, retain) NSString *cellContents;
#property (nonatomic, retain) NSString *account8;
My AccountViewController.m file:
#import "AccountViewController.h"
#interface AccountViewController ()
#end
// Implementing the methods of ViewController
#implementation AccountViewController
#synthesize tableData;
#synthesize cellContents;
#synthesize account8;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
My BluetoothViewController.h
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
My BluetoothViewController.m file:
#import "AccountViewController.h"
#import "BluetoothViewController.h"
#interface BluetoothViewController ()
#end
// Implementing the methods of ViewController
#implementation BluetoothViewController
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
classobj = [[AccountViewController alloc] init];
accountSelected = classobj.account8;
accountSelection.text = accountSelected;
}
When the user selects the row from a table, the contents will be saved in the variable account8. BluetoothViewController will then be called. Now, when BluetoothViewController loads up, the account that was selected by the user is supposed to be shown. However the label returns blank. I am wondering why it does not correctly access the variable saved in AccountViewController.
What you can do is to create an instance variable in Bluetoothcontroller and then after instantiating that object you set it from your AccountViewController. For example:
AccountViewController:
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
bluetoothViewController.accountVariable = _account8;
BluetoothViewController:
#property (nonatomic, copy) NSString *accountVariable;
Or are there any other reason you need to have classobj?
Please check code given below:
AccountViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
BluetoothViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>
#property(nonatomic, retain) AccountViewController *classObj;
AccountViewController.m file:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[bluetoothViewController.view setAlpha:1.0f];
[bluetoothViewController setClassObj:self];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
BluetoothViewController.m file:
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
// Here classObj is already assigned to a reference so you can directly use that one
}
Hope this will help you.
Using your XCode you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "AccountViewController.m" would look in the following way:
#import AccountViewController.h
#import BluetoothViewController.h;
#interface AccountViewController ()
...
#property (nonatomic, strong) BluetoothViewController *bluetoothViewController;
...
#end
#implementation AccountViewController
//accessing the variable from balloon.h
...bluetoothViewController.variableFromBluetoothViewController...;
...
#end

Resources