Method dont change the value of variable - ios

First, sorry for this question, but I am new on iOS development, and i am stuck on this all afternoon, I'm trying to change the value of a int variable using one slider located in a another viewController.
The slider of the row is located in a modal window inside the view, i think that this is the problem, but i don't know.
This is the code:
#interface ViewController ()
#property int row, column, actualGame;
#end
- (IBAction)rowChanged:(id)sender {
UISlider *slider = (UISlider *)sender;
int val = slider.value;
[self setRow: val];
self.rowLabel.text = [NSString stringWithFormat:#"%d",val];
}
- (IBAction)columnChanged:(id)sender {
UISlider *slider = (UISlider *)sender;
int val = slider.value;
_column = val;
self.collumLabel.text = [NSString stringWithFormat:#"%d",val];
}

In order to pass data between view controllers, there are a couple of different options available to you. The simplest would be to just store a reference to the first view controller on your second view controller. You can set the property in the `prepareForSegue' method of your first view controller.
FirstViewController.h (the view controller that's presenting the modal VC):
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#property (nonatomic) float sliderValue;
#end
FirstViewController.m
#import "FirstViewController.h"
#import "ViewController.h"
#implementation FirstViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"mySegueDefinedInStoryboard"]) {
ViewController *destinationViewController = (ViewController *)segue.destinationViewController;
destinationViewController.firstViewController = self;
}
}
#end
ViewController.h (the modal view controller):
#import <UIKit/UIKit.h>
#class FirstViewController;
#interface ViewController : UITableViewController
#property (nonatomic, weak) FirstViewController *firstViewController;
#end
ViewController.m
#import "ViewController.h"
#import "FirstViewController.h"
#implementation ViewController
- (IBAction)columnChanged:(UISlider *)sender {
float value = sender.value;
self.firstViewController.sliderValue = value;
}
#end
The downside of this method is that it creates tightly coupled code - ViewController needs to know about FirstViewController, which isn't optimal. Once you get a little bit more practiced, you'll learn about creating your own delegate, so that you can send messages to other view controllers without caring what their class is or what their properties are.
Apple Documentation on the Delegate Pattern

Related

What are the methods to pass forward data from one View Controller to another using button action?

I'm just a beginner in iOS Devp and stuck with this problem since last 2days. What I am trying to do is I've two view controllers, the first View Controller consists of 2 buttons and I want to load a specific type of data in next View controller on respective button action.
What I did is as follows :
I've two ViewControllers connected using segue with id "showDetailSegue",
1. ViewController
2. SecondVC
I want to update label on SecondVC when the button on ViewController is tapped.
//ViewController.h
#import <UIKit/UIKit.h>
#import "SecondVC.h"
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *textField;
#end
//ViewController.m
#import "ViewController.h"
#import "SecondVC.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
NSString *str = #"my string data..";
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showDetailSegue"]){
SecondVC *controller = segue.destinationViewController;
controller.getString = str;
controller.testLabel.text = str;
}
}
#end
//SecondVC.h
#import <UIKit/UIKit.h>
#interface SecondVC : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#property (nonatomic, strong) NSString *getString;
#end
//SecondVC.m
Please help me with a straightforward and clear explanation.
Thanks in advance.!
There are many ways to pass data to desired ViewController.
1. Using segue
Let suppose you have to pass a string to another VC.
#import "ViewController.h"
#import "SecondVC.h"
#interface ViewController ()
// all instance global variable should be declare here
NSString str;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
str = #"my string data..";
}
// segue delegate method
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"segueIdentifireName"]) {
SecondVC *destViewController = segue.destinationViewController;
destViewController.getString = str;
}
}
#end
Now you must have to create NSString object inside destinationVc .h file like below.
#interface SecondVC : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#property (nonatomic, strong) NSString *getString;
#end
Inside .m file get string data like:
#interface ViewController ()
#end
#implementation SecondVC
- (void)viewDidLoad {
[super viewDidLoad];
self.testLabel.text = getString; // we passed `str` data inside `getString` object so it can be refelect here using `getString` variable.
NSLog(#"string data %#", getString);
}
2. Using storyboard id:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
YourViewControllerClassName *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"viewContIdentifire"];
vc.getString = str;
[self.navigationController pushViewController:vc animated:YES];
Inside .h file:
#property (nonatomic, strong) NSString *getString;
Inside .m file get string data like:
NSLog(#"string data %#", getString);
In Swift3
let controller = UIStoryboard().getControllerInstance(storyBoardName: "MainStoryboard", identifire: "viewContIdentifire")
controller.getString = str;
self.navigationController?.pushViewController(controller, animated: true)
To get data back:
Create protocol where you need to send data back.
// dec var on top
var delegate: YourDelegate!
protocol YourDelegate {
func delegateFunction(value: String)
}
Call delegate func on tap action:
delegate.delegateFunction(value: "My sample string")
Receiving controller
Confirm the delegate to self when navigate
Implement the YourDelegate on top.
func delegateFunction(value: String){
print("Got: ", value)
}
3. Using NSUserDefaluts (Not recommended).
4. Using local DB.

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;
}

UISplitViewController using delegate to pass a string

I'm using a Split View Controller for an iPad app. I'm trying to send a label change to the detailReceiving Controller from the rootSending Controll when a button is pushed. I've read through tutorials on protocols and came up with the code below. When I click the button on rootSending, nothing happens to the label on detailReceiving. Do I have to do something else with a splitViewContoller so that the label will update? Shouldn't detailReceiving change the label when it receives the message?
rootSending.h
#import <UIKit/UIKit.h>
#protocol TestDelegate <NSObject>
-(void)tester:(NSString*)testString;
#end
#interface rootSending : UIViewController
#property (nonatomic, assign) id <TestDelegate> delegate;
#end
rootSending.m
#import "rootSending.h"
#implementation rootSending
#synthesize delegate;
-(void)viewDidLoad{
}
-(IBAction)buttonPressed:(id)sender{
[delegate tester:#"button pressed"];
}
#end
detailReceiving.m
#import "detailReceiving.h"
#import "rootSending.h"
#interface detailReceiving ()<TestDelegate>{
IBOutlet UILabel *label2;
}
#end
#implementation detailReceiving
-(void)viewDidLoad{
rootSending *obj = [rootSending alloc];
obj.delegate = self ;
}
-(void)tester:(NSString *)testString{
label2.text = testString;
}
#end
First of all, never ever have an alloc without an init! But in this case, even if you did use alloc/init, it still wouldn't work because that just creates a new instance of rootSending, not the one that you have in your split view. You need to get a reference to the one you have, which you can get from the split view controller,
-(void)viewDidLoad{
rootSending *obj = (rootSending *)self.splitViewController.viewControllers.firstObject;
obj.delegate = self;
}
After Edit:
If your mate controller is embedded in a navigation controller, then you need to get the navigation controller's topViewController to get your reference.
-(void)viewDidLoad{
UINavigationController *nav = (UINavigationController *)self.splitViewController.viewControllers.firstObject;
xmlListOfItems *obj = (xmlListOfItems *)nav.topViewController;
obj.delegate = self;
}

Passing data between UIViewController and UITableViewController not connected via segue

I followed the advice at this link Changing the value of a property of another UIViewController
I have a Login page that is connected to a github project that I downloaded called SWRevealViewController. It essentially provides a slide out menu for the application. I need to pass a value from my Login Page to the initial Page that is loaded with the SWRevealViewController. Can't seem to get it working. Can anyone point me in the right direction? What I have tried is the following:
LoginViewController.m
#import "LoginViewController.h"
#import "ProfileTableViewController.h"
#interface LoginViewController ()
#property (strong, nonatomic) ProfileTableViewController *secondViewController;
#end
#implementation dbViewController
-(id)init
{
if (self = [super init]) {
self.secondViewController = [[ProfileTableViewController alloc] init];
}
return self;
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if([identifier isEqualToString:#"Login"]){
[self login:sender];
self.secondViewController.idNumber = _IDNumber;
_secondViewController.idNumber = _IDNumber;
return YES;
}
}
LoginViewController.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#import "ProfileTableViewController.h"
#interface LoginViewController : UIViewController
#property (strong, nonatomic)NSString *IDNumber;
#end
ProfileTableViewController.h
#import <CoreLocation/CoreLocation.h>
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#interface ProfileTableViewController : UIViewController <CLLocationManagerDelegate, UITextFieldDelegate>
#property (nonatomic) NSString *idNumber;
#end
ProfileTableViewController.m
#import "ProfileTableViewController.h"
#import "SWRevealViewController.h"
#import "ProfileEditFieldController.h"
#interface ProfileTableViewController ()
#end
#implementation ProfileTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(_idNumber);
}
#end
Just to add clarification, the two blue controllers are the Login, and the three controllers on the right, one of them is the controller I would like to pass the value for
You should do it like this instead:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ProfileTableViewController *pvc = (ProfileTableViewController*)[segue destinationViewController];
pvc.idNumber = _IDNumber
}
Hope that works! :)
UPDATE:
I think what you need is NSUserDefaults, use it, and store the ID. You gonna need it in more than one controller I believe, and its easy to store data on.
NSUserDefaults
It's not 100% clear from what you've shown but I'm assuming that these view controllers are defined in a storyboard and that the "Login" segue is also defined in the storyboard and causes a transition from LoginViewController to ProfileTableViewController.
One thing I am confused about is why the #implementation line in LoginViewController.m says "dbViewController" but I'm assuming that's a typo and that it should be "#implementation LoginViewController".
So, assuming all of that is true, there are a couple of problems in your code. First, you shouldn't be creating the ProfileTableViewController in LoginViewController's init method. iOS will automatically alloc and init the ProfileTableViewController when the segue is performed.
Second, instead of using shouldPerformSegueWithIdentifier:sender:, you want to use prepareForSegue:sender:. When that method is called, iOS will have already created the ProfileTableViewController and you can set your property.
So, what you want is something like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Login"])
{
ProfileTableViewController * viewController = segue.destinationViewController;
viewController.idNumber = _IDNumber;
}
}

Updating UILabel in Child View 1 after Global Variable Update in Child View 2

I have made a simple app to test this and cannot figure it out. I have an iPad storyboard where I have put two container views as shown below. I have a label in one view and a button in another. My button will increment the label, 1 number at a time.
My problem is not passing the value or incrementing, but getting the view to load the new value.
Each container has its own ViewController
Some code below, although very sparse as Ive written a bunch and deleted as it didn't work. Please help with the correct format. I would like to keep this general format, updating global variable within button and it updating the label.
LabelViewController.h
#import <UIKit/UIKit.h>
#interface LabelViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *checkLabel;
-(void)loadLabel;
#end
LabelViewController.m
#import "LabelViewController.h"
#import "ParentViewController.h"
#interface LabelViewController ()
#end
#implementation LabelViewController
#synthesize checkLabel;
-(void)loadLabel{
checkLabel.text = [NSString stringWithFormat:#"%d",value];
[self.view setNeedsDisplay];
}
- (void)viewDidLoad
{
[self loadLabel];
[super viewDidLoad];
}
ButtonViewController.h
#import <UIKit/UIKit.h>
#interface ButtonViewController : UIViewController
- (IBAction)checkButton:(id)sender;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "ParentViewController.h"
#import "LabelViewController.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
- (IBAction)checkButton:(id)sender {
value++;
NSLog(#"%d",value);
LabelViewController *fnc = [[LabelViewController alloc] init];
[fnc loadLabel];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
Picture at:
http://farm4.staticflickr.com/3822/9469907420_746db25b23_b.jpg
In ButtonViewController, you don't want to be alloc init'ing an instance of LabelViewController -- the one that's on screen already exists. Both child view controllers are instantiated just before the parent controller is. So, what you need to do is get a reference to the LabelViewController that's on screen. You can do that with self.parentViewController.childViewControllers[0] (that 0 might have to be 1 -- I don't know which controller is which).
LabelViewController *fnc = self.parentViewController.childViewControllers[0];
[fnc loadLabel];

Resources