Hy I have a problem accessing variables in another class.
Im making an app that makes note and let you study from the notes you make, for example the user makes a note that says "Oceanic dolphins: are members of the cetacean...", and when the user press a button to study it appears something like this "what are Oceanic Dolphins" then the user press a button it appears something like this "they are members of the cetacean..." the problem I have is this When i enter the ViewController that makes the question it appears empty I think the problem lies on one of the next codes
I make the Variable Globals like this
QueRes.h
#import <Foundation/Foundation.h>
#interface QueRes : NSObject
#property NSString *question;
#property NSString *response;
#end
QueRes.m
#import "QueRes.h"
#implementation QueRes
#end
I divide the NSString of the note like this
NSArray *card = [_argumentTextView.text componentsSeparatedByString:#":"];
QueRes *make = [[QueRes alloc] init];
if ([card count] >= 2)
{
make.question = card [0];
make.response = card [1];
}
the I apply the variable question and response in a ViewController like this
- (void)viewDidLoad
{
[super viewDidLoad];
QueRes *make = [[QueRes alloc] init];
_questionTextView.text = make.question;
}
then in other view controller i have the same code but apply with the response variable
Please help me I been stuck in this for weeks (I have Xcode 5 and the app runs in IOS 7)
(if you need more of the code of the program to help me fix it just tell me )
You are making a new instance of a QueRes in your viewDidLoad method. Unless the init method of QueRes sets its question and response properties to something, they will be uninitialized, which is why you are not seeing anything in your text view: there is nothing to show.
Naming the QueRes instance you make in the third code block you posted make does not make it the same instance as the instance in the viewDidLoad method, and it is not a global variable at all. It is a separate instance of QueRes.
Related
I'm can see that there is a lot of questions regarding this already, but none of them seems to have given me an explanation to why I cannot access my array from another class.
Here's where I wan't to access the array
(XYZPaymentViewController.m)
- (void)viewDidLoad
{
[super viewDidLoad];
XYZMateOverviewViewController *test = [[XYZMateOverviewViewController alloc] init];
NSMutableArray *t = test.mates;
NSLog(#"Count of ThatArray: %d", [t count]);
}
Nomatter what - the log writes out 0 !!
In another class (XYZMateOverviewViewController.h) I declare the array
#property (retain) NSMutableArray *mates;
I synthesize the array in the implementation area in XYZMateOverviewViewController.m
#synthesize mates;
I hope you can help me understand what I'm doing wrong :)
If you want to access an array from another ViewController you have to pass the array between the ViewControllers.
For example:
You have two ViewControllers. 'A' and 'B', so u have to do this:
In the 'A' ViewController, is where you have the array that you want to send to another ViewController. Then create an instance of 'B' ViewController and send the array to him:
CODE OF 'A' ViewController:
NSMutableArray *arrayToSend = [[NSMutableArray alloc]init];
BViewController *bViewController = [[BViewController alloc]initWithNibName:#"BViewController" bundle:nil];
BViewController.arrayReceived = arrayToSend;
[self.view addSubView:BViewController.view];
After, in your BViewController you just have to take your arrayReceived and use it.
CODE OF 'B' ViewController:
NSLog(#"%#", [arrayReceived objectAtIndex:0]); // For example.
Hope i did help you, if u have any question tell me.
What are you doing with the mates array in the XYZMateOverviewViewController init method?
If you're not adding any data to it a count of 0 is just right.
With the line
XYZMateOverviewViewController *test = [[XYZMateOverviewViewController alloc] init];
you are creating a completely new instance of XYZMateOverviewViewController—one that has nothing to do with any other part of your application*. What you should be doing instead is getting a reference to the already-set-up instance of the view controller. That instance presumably has its mates property set up with the data you want.
The general topic of sharing data between different parts of your application—and between different view controllers, in particular—should be covered somewhere toward the beginning of any “introduction to iOS programming” book or tutorial.
* Unless you’re doing something funky with singletons or shared state, of course, but I doubt that’s the case here.
Do you alloc/init the mutable array in the init method?
Okay, so I was reading here declaring global variables in iPhone project and I noticed the line with this code: [[[UIApplication sharedApplication] delegate] myNSString];.
Basically, I want a user to input something in a text field on the flipside view, then have it stored in a variable which is accessed on the main view. Ideally, the main view would be able to just read the text field from the flipside view, but this seems to be impossible (I've spent several hours each day for the past few days scouring the web and various books for an answer about how to do this and no one seems to be able to give a definitive answer). Therefore, I'm resorting to using a global variable to tackle this.
Will the code that I printed above somehow allow me to do this? I've been trying to adapt it for the past hour, but have come up with nothing except No known instance method for selector 'myNSString' and I'm not quite sure what that means in this case.
Can someone please help me out? I feel like I can keep trying different things but without some sort of help, I'm just shooting in the dark here. Thank you!
You may want to think about using a singleton to hold your data if you're set on using a global variable. There's a good tutorial on singletons here: http://www.galloway.me.uk/tutorials/singleton-classes/ -basically it's a class that can be shared throughout the application and accessed/modified by different controllers. You'd be able to create a property on it, write to that property from the flip view, and then access that property from your main view.
#import "Singleton.h"
#implementation Singleton
#synthesize yourTextField;
#pragma mark Singleton Methods
+ (id)sharedManager {
static Singleton *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
yourTextField = #"";
}
return self;
}
You could call it in code by importing its header file and:
Singleton *mySingleton = [Singleton sharedManager];
the mySingleton object will have the text field attached. It can be accessed by:
mySingleton.yourTextField;
.h file:
#import <Foundation/Foundation.h>
#interface Singleton : NSObject
#property (nonatomic, strong) NSString *yourTextField;
+ (id)sharedManager;
#end
Singleton (remember about dispatch_once), static variables or NSUserDefaults. It really depends what you really need.
If you are using storyboards and just want to pass data between VC, then you can use "prepareForSegue" method (described here https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/prepareForSegue:sender:).
Segue has "destinationController" property, so you can setup VC before showing it.
I have 2 classes which names are A and B, I have UIScrollView with pagecontroller in class A and I have a UILabel and NSMutableArray in B.
I used this event for get pagecontroller's page and i am sending number of page to classB for use array's element.
//ClassA
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.imageScrollView.frame.size.width;
int page = floor((self.imageScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
ClassB *obj = [[ClassB alloc]init];
[obj changeDiscount:page];
}
//ClassB
- (void)viewDidLoad
{
numbers = [[NSMutableArray alloc]initWithObjects:#"15",#"25",nil];
}
-(void) changeDiscount:(int)currentPagePresentation{
NSLog(#"currentI = %i",currentPagePresentation);
_discountLabel.text = [NSString stringWithFormat:#"%# Discount",[numbers objectAtIndex:currentPagePresentation]];
}
I can call the changeDiscount method but array is coming null every time and I can't set the string to label.
What am I doing wrong?
Thanks for your answer and advice.
The reason why your _discountLabel.text's string is equal to null is because the numbers array that you are accessing has not even been initialised.
The reason why your numbers array has not been initialised is because the viewDidLoad method only gets called as the method states: WHEN the view has loaded ;)
If you want to access the array after creating an instance of your class, its best to setup the numbers array in an init method or so.
All you've done is:
//This creates a new instance of your second class B.
ClassB *obj = [[ClassB alloc]init];
//Youre trying to access the numbers array when you havent even loaded the view
//All you've done is create an instance of it and then calling a method with an empty numbers array.
[obj changeDiscount:page];
And that doesn't sit well with your existing code. Please continue to read to understand why.
You also definitely don't want to be creating new instances of your class every time your scroll view delegate method is called. I highly suggest you revisit that code and find an appropriate place for that code.
Solution
I suggest you revise the view controllers programmers guide on the apple website before doing anything else.
Follow step 1.
Follow step 1 again.
Then something you can do is:
Method 1: - lazy method In class B you could create an instance method like so:
//.h
-(void)setupArray;
//.m
-(void)setupArray{
numbers = [[NSMutableArray alloc]initWithObjects:#"15",#"25",nil];
}
//Then you can do something like this in class a
ClassB *obj = [[ClassB alloc]init];
[obj setupArray];
[obj changeDiscount:page];
Method 2: more appropriate If you want to do it in one go you can do this, and create an init method.
//.h
//in your Class B .h file you create an instance method like so:
-(void)init;
//.m file
-(id)init{
self=[super init];
if(self)
numbers = [[NSMutableArray alloc]initWithObjects:#"15",#"25",nil];
return self;
}
//Then in your class a method you can do this:
//Like before.
ClassB *obj = [[ClassB alloc]init];
[obj changeDiscount:page];
Ok, there are a few things causing issues here:
You are creating an instance of ClassB within the scope of scrollViewDidScroll of classA.
As soon as that method completes, that new object will be deallocated.
ClassB initialises the numbers array in viewDidLoad. This method will be called only when a UIViewController subclass loads it’s UIView, so ClassB must be a UIViewController subclass and you need to have presented it.
viewDidLoad is called when you first time access view property of that viewController.until then view is nil.
So your numbers array wont be initialised because you are calling changeDiscount method before viewDidLoad is executed.
So, move the initialising from viewDidLoad to init or initWithNib.
-(id)init{
self=[super init];
if(self)
numbers = [[NSMutableArray alloc]initWithObjects:#"15",#"25",nil];
return self;
}
I have an application where A View Controller (A)is called twice in close succession. Now each time it is called, an NSString object is created, and I need this value to be stored in an NSMutableArray that is a public property of ANOTHER View Controller (B).
In A, I create an instance of the second View Controller (B), and using that instance, add the NSString objects into the NSMutableArray which I've created as a public property. Later, when I am inside View Controller B and print the contents of the NSMutableArray property, the array is empty. Why? Here is the code that is inside View Controller A:
-(void)viewDidLoad {
ViewControllerA *aVC = [[ViewControllerA alloc] init];
if (aVC.stringArray == nil) {
aVC.stringArray = [[NSMutableArray alloc] init];
}
[aVC.stringArray addObject:#"hello"];
[aVC.stringArray addObject:#"world"];
for (NSString *wow in aVC.stringArray) {
NSLog(#"The output is: %#", wow);
}
}
Inside my View Controller B class, I have the following code:
- (IBAction)buttonAction:(UIButton *)sender {
NSLog(#"Button selected");
for (NSString *test in self.stringArray) {
NSLog(#"Here are the contents of the array %#", test);
}
}
Now the buttonAction method gets called, as I do see the line Button selected in the system output, but nothing else is printed. Why? One thing I want to ensure is that View Controller A is called twice, which means I would like to see in the output, "Hello World", "Hello World" (i.e. printed twice), and not "Hello World" printed just once.
The other thing I wish to point out is that View Controller B may not be called at all, or it may be called at a later point in time. In any case, whenever View Controller B is called, I would like to have the values inside the array available, and waiting for the user to access. How do I do this?
Your approach is not ideal, potentially leading to a memory cycle, with two objects holding strong pointers to each other.
You can instead achieve your goal in two ways;
Delegate Protocol
This method allows you to set delegates and delegate methods to pass data back and forth between view controllers
in viewControllerA.h
#protocol viewControllerADelegate <NSObject>
- (void)addStringToNSMutableArray:(NSString *)text;
#end
#interface viewControllerA : UIViewController
#property (nonatomic, weak) id <viewControllerADelegate> delegate;
in viewControllerB.m
// create viewControllerA class object
[self.viewControllerA.delegate = self];
- (void)addStringToNSMutableArray:(NSString *)text
{
[self.mutableArray addObject:text];
}
in viewControllerA.m
[self.delegate addStringToNSMutableArray:#"some text"];
Utility Classes
Alternatively you can use a utility class with publicly accessible methods (and temporary data storage). This allows both viewController classes to access a shared data store, also if you use class methods, you don't even need to instantiate the utility class.
in XYZUtilities.h
#import <Foundation/Foundation.h>
#interface XYZUtilities : NSObject
+ (void)addStringToNSMutableArray;
#property (strong, nonatomic) NSMutableArray *array;
#end
in XYZUtilities.m
+ (void)addStringToNSMutableArray
{
NSString *result = #"some text";
[self.array addObject:result];
}
+ (NSArray)getArrayContents
{
return self.array;
}
in viewControllerA.m
NSString *stringFromObject = [XYZUtilities addStringToNSMutableArray];
in viewControllerB.m
self.mutableArray = [[NSMutableArray alloc] initWithArray:[XYZUtilities getArrayContents]];
I'm not sure what kind of a design pattern you are trying to follow but from the looks of it IMHO that's not a very safe one. However, there are many, many ways this could be accomplished.
One thing though, you said that View Controller B may never get allocated and if it is alloc-ed, it will be down the road. So you can't set a value/property on an object that's never been created.
Since you already aren't really following traditional patterns, you could make a static NSMutableArray variable that is declared in the .m of your View Controller B Class and then expose it via class methods.
So it would look like this:
viewControllerB.h
+(void)addStringToPublicArray:(NSString *)string;
viewContrllerB.m
static NSMutableArray *publicStrings = nil;
+(void)addStringToPublicArray:(NSString *)string{
if (publicStrings == nil){
publicStrings = [[NSMutableArray alloc]init];
}
if (string != nil){
[publicStrings addObject:string];
}
}
Then it would be truly public. All instances of view controller B will have access to it. This, of course is not a traditional or recommended way of doing it—I'm sure that you will have many replies pointing that out ;).
Another idea would be to use a singleton class and store the values in there. Then, when or if view controller B is ever created, you can access them from there.
I am writing the iPhone application and I would like to ask about the the passing parameters in Objective-C.
I create 2 view controller. In the first one, I have a button, when a user press the button, it will call the -(IBAction) pressButton (user-defined), and after 5-6 second (have to process and retrieve the data in the NSMutableArray *), it will display a table. However, I don't know how to pass the NSMutableArray to the table class. Can I do this?
// situation
// ---------------------------------------------
// In MyViewController.m
// class variable
NSMutableArray * arr;
- (IBAction) pressButton: (id)sender {...}
// I retrieve the data and store in the arr
// In TableView.m
// I want to pass the arr to here and use
I know how to create the table, but I don't know how to pass the parameters from a class (MyViewController.m) to another class (TableView.m).
In TableView.h, declare a method:
- (void)doWhateverWithArray: (NSArray *)anArray;
In TableView.m, implement the method to do whatever you need it to do.
In MyViewController.m, near the top of the file (outside of #implementation ... #end) write #import "TableView.h"
Send -doWhateverWithArray: to your table view when necessary.
Function calls are a fundamental part of procedural programming languages like C; message dispatches (AKA method calls) are a fundamental part of object-oriented programming languages like Objective-C.
The nature of this question suggests you're just starting to get into programming (if I'm wrong, please don't take this as an insult--it's not.) I'm sure folks can recommend any number of introductory texts to C or Objective-C, but I'd go further if I were in your shoes.
If available to you, I recommend that you take college-level programming courses, or even enroll in a computer science degree at the university level if you have the time and dedication. :)
In your TableView ViewController create NSMutableArray like this
IBOutlet NSMutableArray *PassedArray;
#property(nonatomic,retain) NSMutableArray *PassedArray;
#synthesize PassedArray;
[PassedArray release];
Now you can pass NSMutableArray value from your Myviewcontroller to tableviewcontroller using this
tableviewcontroller *objInstance = [[tableviewcontroller alloc]initWithNibName:#"tableviewcontroller" bundle:nil];
objInstance.PassedArray = NSMutableArray;//Here you declare your passed NSMutableArray
[self.navigationController pushViewController:objInstance animated:YES];
[objInstance release];
Another method is Declare NSMutableArray *yourArray is global in MyViewController.h and extern those variables in tableviewcontroller.m like this
extern NSMutableArray *yourArray;