How to add value in NSMutableArray when button is pressed - ios

for my iOS app I want to initiate an NSMutableArray and change the Object the array holds during runtime with buttons. So far I was able to initiate an array in viewDidLoad {} in the ViewController.m but now i can't access it in my buttonPressed method. How can I make the array accessible for the hold file?
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSMutableArray *toCalculate = [#[#0] mutableCopy];
}
- (IBAction)numbersButtonsPressed:(UIButton *)sender {
NSLog(#"%ld\n", sender.tag);
[toCalculate addObject:[NSNumber numberWithLong:sender.tag]];
}

Declare variable as global(class variable) not in local variable(function).
What is global variable?
Solution for the problem is:
#import "ViewController.h"
#interface ViewController (){
NSMutableArray *toCalculate;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
toCalculate = [#[#0] mutableCopy];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)numbersButtonsPressed:(UIButton *)sender {
NSLog(#"%#",toCalculate);
[toCalculate addObject:[NSNumber numberWithLong:sender.tag]];
}
#end

Thanks Paul,
it work like he said if you implement it as a #property in the ViewController.h file.
#interface ViewController: UIViewController
#propety NSMutableArray *giveItAName
#end

Related

iOS SDK - Track viewDidLoad method

I am working on a SDK, where I will have to make a call to our server whenever viewDidLoad method of any UIViewController is called in the app integrated with our SDK. I am trying to use Categories as shown below:
#import "DymmyViewController.h"
#interface DymmyViewController ()
#end
#protocol DummyDelgate;
#interface UIViewController (DummyAddition)
-(void)viewDidLoad;
#end
#implementation DymmyViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
#end
#implementation UIViewController (DummyAddition)
-(void)viewDidLoad{
//server call
}
#end
Nothing happens with this and I get a warning saying "Category is implementing a method which will also be implemented by its primary class"
I understand this is not the way to get this done. Is there any other way I can do this? May be using NSNotification?
This is the way to use protocols and delegates. Delegated are good techniques to respond from one class to another class.
DummyView.h
#import <UIKit/UIKit.h>
#class DummyView;
#protocol DummyViewDelegate <NSObject>
- (void)addItemViewController;
#end
#interface DummyView : UIViewController
#property (nonatomic, weak) id <DummyViewDelegate> delegate;
#end
DummyView.m
#import "DummyView.h"
#interface DummyView ()
#end
#implementation DummyView
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backButtonClicked:(id)sender {
[self.delegate addItemViewController];
}
ViewController.h
#import <UIKit/UIKit.h>
#import "DummyView.h"
#interface ViewController : UIViewController <DummyViewDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
DummyView *acController;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
acController.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)addItemViewController{
}
Why not just make a tracking view controller available in the SDK. The app dev should then make all of their view controllers of this base type. You might need a couple of base classes (e.g. if you're also using TableViewControllers).
In SDK:
#interface TrackingViewController : UIViewController
#end
#implementation TrackingViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Make the call here
// ....
}
In app:
#import "SDK.h"
#interface MyViewController : TrackingViewController ...

I need to pass a string from a NSObject class to a UIViewController with a delegate

I need to pass a string from a NSObject class to a UIViewController, I understand that the best way is delegation but the delegate method isn't being called. I'm trying to set the UILabel an DieFacesViewController as the selectedOption from TemporarySelection.
A tableview shows the value of CustomOptionStore, once it's tapped passes its value to TemporarySelection and opens the modal view DieFacesViewCountroller which should, at least in my mind, take the label value from TemporarySelection. The reason I created TemporarySelection is because the DieFacesViewController will be used by other classes, not only by CustomOptionStore, and it will need to load the label from all those classes when different tableViews are selected.
I tried to set the delegate as self in both viewDidLoad and viewWillAppear with no luck, I don't understand if the view loads before being able to call the delegate method or if there's something wrong the way I set the method up.
I've been stuck here for two days, this is the first time I post a question so please forgive me if it's a bit confused.
my delegator class TemporarySelection.h is
#import <Foundation/Foundation.h>
#import "CustomOptionsStore.h"
#class DieFacesViewController;
#protocol TemporarySelectionDelegate <NSObject>
-(void)sendSelection;
#end
#interface TemporarySelection : NSObject
#property (nonatomic, weak) id <TemporarySelectionDelegate> delegate;
#property (nonatomic, strong) NSString *selectedOption;
-(void)addSelection: (CustomOptionsStore *) selection;
#end
and my TemporarySelection.m is
#import "TemporarySelection.h"
#implementation TemporarySelection
-(void)addSelection: (CustomOptionsStore *) selection{
self.selectedOption = selection.description;
[self.delegate sendSelection];
}
#end
the delegate class DiewFacesViewController.h is
#import <UIKit/UIKit.h>
#import "SelectedStore.h"
#import "TemporarySelection.h"
#interface DieFacesViewController : UIViewController <TemporarySelectionDelegate>
#property (strong, nonatomic) IBOutlet UILabel *SelectionName;
#end
and the DieFacesViewController.m is
#import "DieFacesViewController.h"
#interface DieFacesViewController ()
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
TemporarySelection *ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
TemporarySelection *ts = [[TemporarySelection alloc]init];
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}
You are not setting the delegate object properly.Check the above code
#import "DieFacesViewController.h"
#interface DieFacesViewController ()<TemporarySelectionDelegate>
{
//global object
TemporarySelection *ts;
}
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
//Use the object to extract
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}

delegate respondsToSelector:selector not working

I saw a lot of this kind of questions and answers here, but couldn't find solution to my problem. I'm trying to send data from one view controller to another and use delegate. But don't know why my postDelegate doesn't responds to selector. Is something wrong with this code or what is the problem?
PostViewController.h file
#protocol GetDataDelegate <NSObject>
-(void)getPassedInfo:(NSString*)info;
#end
#interface PostViewController : UIViewController
#property (nonatomic, weak) id <GetDataDelegate> postDelegate;
#end;
PostViewController.m file
#import "PostViewController.h"
- (IBAction)postData:(id)sender {
if ([_postDelegate respondsToSelector:#selector(getPassedInfo:)]) {
[self.postDelegate getPassedInfo:#"data"];
NSLog(#"responds");
}
[self dismissViewControllerAnimated:YES completion:nil];
}
in second view controllers .h file
#import "PostViewController.h"
#interface MainViewController : UITableViewController <GetDataDelegate>
and in .m file
#implementation MainWindowTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
PostViewController * postController = [[PostViewController alloc]init];
postController.postDelegate = self;
}
and here is delegate method:
-(void)getPassedInfo:(NSString *)info{
NSLog(#"info is %#", info);
}
You need to make postController a property or an ivar. Currently it is a local variable in the viewDidLoad method which will be deallocated after viewDidLoad completes as #CodaFi said above.
#import "PostViewController.h"
#interface MainViewController : UITableViewController <GetDataDelegate>
#property (nonatomic, strong) PostViewController *postController;
#end
Then:
- (void)viewDidLoad
{
[super viewDidLoad];
self.postController = [[PostViewController alloc]init];
self.postController.postDelegate = self;
}

UITextFieldDelegate not working

I'm trying to separate the UITextViewDelegate methods from the main class of my project, I created a class to manage the delegate methods, but I can not change the values of the IBOulets from the main class.
I made a test project with a ViewController and a TextFieldController, in the Storyboard I add a text field and a label. What I want to do is change the text of the label when I start to write in the text field. Here is the code:
ViewController.h:
#import <UIKit/UIKit.h>
#import "TextFieldController.h"
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UILabel *charactersLabel;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
TextFieldController.h:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : UIViewController <UITextFieldDelegate>
#end
Text Field Controller.m:
#import "TextFieldController.h"
#interface TextFieldController ()
#property ViewController *viewController;
#end
#implementation TextFieldController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
_viewController.charactersLabel.text = #"hello";
return YES;
}
#end
When I start writing in the text field the message "Hello" is printed in the log, but the text of the label does not change. I want to know how to change the label text value from the other class.
First change the TextFieldController.h like this:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : NSObject <UITextFieldDelegate>
{
}
#property (nonatomic, assign) ViewController *viewController;
#end
Then change your TextFieldController.m file like this:
#import "TextFieldController.h"
#interface TextFieldController ()
#end
#implementation TextFieldController
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
self.viewController.charactersLabel.text = #"hello";
return YES;
}
#end
In the ViewController.m do like that:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textFieldController.viewController = self;
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
This will work but I personally dont like that way you took.
Good luck :)
It's failing because _viewController is nil. You need to assign the viewController property in your delegate in order to support the two way communication.
Also, I'd strongly recommend you make your delegate object a subclass of NSObject, and not UIViewController. It does nothing with controlling views. You can just manually instantiate it in your ViewController objects viewDidLoad.
In TextViewController I don't see where the viewController property (_viewController ivar) is being set so it is probably nil. You should set it when you create the TextViewController instance.
When you are navigating to other controllers using storyboad's segue then you need to implement prepareForSegue method to initialised its properties as follows
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"segue for textFieldController"])
{
TextFieldController *_textFieldController = [segue destinationViewController];
_textField.delegate = _textFieldController;
}
}
But I was wondering, why are you setting textFieldDelegate here, why can't you set in TextFieldController's viewDidLoad method as then you didn't you to implement above prepareForSegue method call?
Besides you are keeping strong reference of each other and you are creating strong retain cycle.
One more thing, following code
_textField.delegate = _textFieldController;
will not work, until textFieldController is loaded and its viewDidLoad method is being called as you are only initialising it but its outlets will not be connected until view is loaded into navigation stack.

Passing data between ViewControllers is working, but not with Tab Bar Controller

Could anyone please help me in the following problem?
I new in Xcode, I'm still learning it, but I could figure out how to pass data between ViewControllers.
Here is my working code:
FirstViewController.h:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
- (IBAction)displayView:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *lblFirst;
#end
FirstViewController.m:
#import "FirstViewController.h"
#import "SecondViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize lblFirst;
SecondViewController *secondViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.forwarded_lblFirst = lblFirst;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)displayView:(id)sender {
[self.view addSubview:secondViewController.view];
}
#end
SecondViewController.h:
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
#property (nonatomic, retain) UILabel *forwarded_lblFirst;
#property (weak, nonatomic) IBOutlet UITextField *txtSecond;
- (IBAction)btnReturn:(id)sender;
- (IBAction)txtSecond_DidEndOnExit:(id)sender;
- (IBAction)btnSecond:(id)sender;
#end
SecondViewController.m:
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize forwarded_lblFirst;
#synthesize txtSecond;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnReturn:(id)sender {
[self.view removeFromSuperview];
}
- (IBAction)txtSecond_DidEndOnExit:(id)sender {
forwarded_lblFirst.text = txtSecond.text;
[txtSecond resignFirstResponder];
[self.view removeFromSuperview];
}
- (IBAction)btnSecond:(id)sender {
forwarded_lblFirst.text = txtSecond.text;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[txtSecond resignFirstResponder];
}
#end
This code is working perfectly, the text what I enter on the SecondViewController's textbox (after pressing the btnSecond or simply the Return key on the keyboard) appears as the text of the Label on the FirstViewController.
My problem is, that when I do the exact same thing, but with a Tab Bar Application, the Label on the First tab won't change.
I can use the exact same code (except the changing-views part, because I handle on the first app with programmed buttons, but for the Tab-Bar-App there are already the buttons), there are also two ViewControllers for the Tab Bar App, too (one for each tabs).
So the code is the same, line by line, character by character, and the files are the same, too, for both apps (View-Based, Tab-Bar).
Why isn't my code working? How can I solve this problem?
Thank you!
You need to read some articles about transferring data between views:
Passing Data between View Controllers
Storyboard
passing data between views
iPhoneDevSDK
Talking about your problem, try this approach:
Add the property to your Application Delegate.
When assigning the property do something like:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.myProperty = #"My Value";
then, in your different tabs, you can retrieve this property in the same manner:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *valueInTab = delegate.myProperty;
A different approach to this problem is to use an independent data model.
Create an object that provides access and manipulation methods for all the data that your application needs to save, load, share, or use in any non-trivial way. Make the object available either as a Singleton or as a property of the application delegate. When changes happen, have the data model update application state. When something needs to be displayed, have the controller fetch it from the data model and send it to the view (MVC!).
If you don't store things in controllers that actually belong in the model, you never need to worry about passing information from controller to controller.
You need to use tabbardelegate in your secondview controller, assuming that you use this schema
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#property (strong, nonatomic) NSString *content;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tabBarController.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if ([viewController isKindOfClass:[FirstViewController class]]){
FirstViewController *vc =( FirstViewController *) viewController;
vc.content = #"your content";
}
return TRUE;
}

Resources