I have a view controller PlayerViewController, I am trying to pass a NSMutableArray: stories, to the view controller PlaylistViewController
in the PlayerViewController.h file I have
#class PlaylistViewController;
in the PlayerViewController.m file I have
//stories is a NSMutableArray that does have content in it
PlaylistViewController *sVC = [[PlaylistViewController alloc] initWithNibName:#"PlaylistViewController" bundle:nil];
sVC.playSongArray = [[NSMutableArray alloc]init];
sVC.playSongArray = stories;
in the PlaylistViewController.h file I have
NSMutableArray *playSongArray;
and
#property(nonatomic,retain)NSMutableArray *playSongArray;
I also synthesize it in the .m file
But when I run the code, playSongArray in PlaylistViewController is empty. What am I doing wrong?
How are you presenting this view? I've seen multiple times where I had to present the view before setting properties like this in order for them to be applied properly. It seems the the view is not full initialized until it is presented/displayed and part of the initialization process sets the properties to nil.
Assuming you are presenting this modally try the following order instead.
//stories is a NSMutableArray that does have content in it
PlaylistViewController *sVC = [[PlaylistViewController alloc] initWithNibName:#"PlaylistViewController" bundle:nil];
[self presentModalViewController:svc animated:YES]; // if modal
[self pushViewController:svc animated:YES]; // if part of a uinavigationcontroller
sVC.playSongArray = [[NSMutableArray alloc]init];
sVC.playSongArray = stories;
Instead of :
sVC.playSongArray = [[NSMutableArray alloc]init];
sVC.playSongArray = stories;
Try
sVC.playSongArray = [[NSMutableArray alloc]initWithArray:stories];
If it's not working, in your PlaylistViewController controller, add playSongArray = [[NSMutableArray alloc]init]; in initWithNibName function then create a function :
- (void)setPlaySongs:(NSArray *)songs {
[playSongArray addObjectsFromArray:songs];
}
and load your view controller this way :
PlaylistViewController *sVC = [[PlaylistViewController alloc] initWithNibName:#"PlaylistViewController" bundle:nil];
[sVC setPlaySongs:stories];
I suspect you are checking the value of playSongArray too early. Your PlaylistViewController should look like:
#interface PlaylistViewContror {
NSMutableArray *playSongArray;
}
- (id)initWithPlaySongArray:(NSMutableArray *)array;
#property(nonatomic,retain)NSMutableArray *playSongArray;
#end
#implementation PlaylistViewContror
#synthesize playSongArray;
- (id)initWithPlaySongArray:(NSMutableArray *)array
{
if (!(self = [super initWithNibName:#"PlaylistViewController" bundle:nil]))
return nil;
playSongArray = array;
return self;
}
- (void)awakeFromNib
{
// do things with playSongArray here
}
#end
And then in your PlayerViewController, you just do:
//stories is a NSMutableArray that does have content in it
PlaylistViewController *sVC = [[PlaylistViewController alloc] initWithPlaySongArray:stories];
Related
I have a question...
I have couple(2) of ViewCotroller.
name are ViewController and DetailViewController
DetailViewController has data(Relationship in Coredata).
this is DetailViewController code.
NSSet *tags = self.bookInfo.details.tags;
tagNamesArray = [[NSMutableArray alloc] initWithCapacity:tags.count];
for (Voca_Tag *tag in tags) {
[tagNamesArray addObject:tag.mean];
}
I want using that tagNamesArray.count in ViewController.
also, I was used
DetailViewController *detailViewController = [[DetailViewController alloc]init];
[detailViewController.tageNamesArray count];
it didn't work.
I want use the Count to cell.text on UITableView.
pastebin.com/RwuR6PDt << ViewController
pastebin.com/2F345vg7 << DetaulViewController
plz Check...
You should write your delegate: In SecondViewController.H:
#protocol messageDelegate <NSObject>
#optional
-(void) sendDataCount:(NSInteger) i;
#end
#interface SecondViewController : NSString
#property (nonatomic, assign) id <messageDelegate> delegate;
#end
In SecondViewController.m:
-(void)readyToSend
{
[self.delegate sendDataCount:__YOURCOUNT__];
}
In ViewController.h:
#interface ViewController : UIViewController<messageDelegate>
#end
In ViewController.m: in
- (void)viewDidLoad {
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.delegate = self;
}
-(void) sendDataCount:(NSInteger) i
{
NSLog(#"Your Count = %d",i);
//send Data using POST method
}
Hope it will help!
This is because tafNamesArray does not have memory allocation at that time and hence this array will returns nil and its count will be zero .
If you want to get [tafNamesArray count ] ,first call that method which initilize tafNamesArray, for example :
In DetailViewController
-(void)array
{
NSSet *tags = self.bookInfo.details.tags;
tagNamesArray = [[NSMutableArray alloc] initWithCapacity:tags.count];
for (Voca_Tag *tag in tags) {
[tagNamesArray addObject:tag.mean];
}
}
then In ViewController
call :
DetailViewController *detailViewController = [[DetailViewController alloc]init];
//First call this method
[detailViewController array];
//then this line will work
int i = [detailViewController.tafNamesArray count];
I'm new to iOS development and I want to pass an NSMutableArray from one viewcontroller to another but always gives me null values
FirstViewController.h
#interface FirstViewController : UIViewController
#property (nonatomic, retain) NSMutableArray *colorArray;
-(IBAction)btn:(id)sender;
FirstViewController.m
#implementation FirstViewController
-(IBAction)btn:(id)sender
{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.animalArray = self.colorArray;
NSLog(#"%#",secondViewController.animalArray); // here its not null
[self.navigationController pushViewController:secondViewController animated:YES];
}
SecondViewController.h
#interface SecondViewController : UIViewController
#property (nonatomic, retain) NSMutableArray *animalArray;
SecondViewController.m
I only used NSLog(#"animalArray:%#",self.animalArray); in viewDidLoad to check the values but gives me null
is there anything I'm missing?
Edit :
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"indidLoad%#",self.animalArray);
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"inwillAppear%#",self.animalArray);
}
Replace with following method
-(IBAction)btn:(id)sender{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.animalArray=[[NSMutableArray alloc]initWithArray:self.colorArray];
[self.navigationController pushViewController:secondViewController animated:YES];
}
:) +1
If you call your NSLog from (void)viewWillAppear:(BOOL) animated, you should see something.
In your code example the viewDidLoad method is called straight after initWithNibName :
[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
and before you have a chance to set your property.
**FirstViewController.h**
#interface FirstViewController : UIViewController
{
NSMutableArray *SongArray;
}
#property(nonatomic,retain)NSMutableArray *SongArray;
**FirstViewController.m**
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondView.SongArray = self.SongArray;
[self.navigationController secondView animated:YES];
**SecondViewController.h**
#interface SecondViewController : UIViewController
{
NSMutableArray *SongArray;
}
#property(nonatomic,retain)NSMutableArray *SongArray;
Do it like this your values arent being retained. Please also check Pass NSMutableArray to one view controller to another
Check the value in viewWillAppear instead of viewDidLoad.
It should work
-(IBAction)btn:(id)sender
{
SecondViewController* secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"%#",secondViewController.animalArray); // here its not null
[self.navigationController pushViewController:secondViewController animated:YES];
secondViewController.animalArray = self.colorArray;
}
Sometimes if you pass value before pushing the the view it will give null value in second view
Better way is to create your NSMutableArray in Appdelegate file like below...
#property (nonatomic, retain) NSMutableArray *animalArray;//define this in Appdelegate.h file
synthesize it in Appdelegate.m file like
#synthesize animalArray;
Create Appdelegate object in prefix.pch file like below.
#define AppDel ((AppDelegate *)[UIApplication sharedApplication].delegate)
and import your Appdelegate file in prefix.pch like below..
#import "AppDelegate.h"
now where you want to use that array...just write like below..
AppDel.animalArray=//you can do whatever you want with array....
By doing this no need to pass array to other view controller, you can use that global array in whole project ,you can insert object in that array in any class and can access in any class.
Let me know it is working or not!!!
Happy coding!!!!
I have a tabBar application. In the app delegate i create one NSMutableArray, one UITableViewController and one class (lets say class B) that updates the NSMutableArray.
The tabBar contains
a) The tableViewController which shows the data in the *booksArray
b) Class B which adds data to the booksArray
The tableView works great when it is first loaded. The problem is that when the array updates, not any changes are fired in the UItableViewContoller (when I choose its tab again). Do I have to use delegation? Do I have to change my architecture?
AppDelegate:
visibleBooks = [[NSMutableArray alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:booksTableViewController];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
NSArray *viewControllers = [NSArray arrayWithObjects:navController,qrViewController, nil];
[tabBarController setViewControllers:viewControllers];
In the UITableViewController .h:
#class BookDetailedViewController;
#interface BooksTableViewController : UITableViewController {
NSMutableArray *bookSource;
}
#property (nonatomic,retain) NSMutableArray *bookSource; // IS RETAIN OK?
- (id) initWithDataSource: (NSMutableArray *) source;
#end
In the UITableViewController .m:
- (id) initWithDataSource: (NSMutableArray *) source
{
[super initWithStyle:UITableViewStyleGrouped];
[self setBookSource:source];
[[self navigationItem] setTitle:#"Books"];
return self;
}
You need to invoke [self.tableView reloadData] in UITableViewController each time when your data source is updated, or when you're showing your tableView.
This can be done in viewWillAppear: inside your BooksTableViewController, or in tabBar:didSelectItem: inside UITabBarController.
for example, add this code snippet to BooksTableViewController:
- (void) viewWillAppear:(BOOL) animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
Bear with me on this one.
I have an iphone application. It is a questionnaire application. There are several types of question, some have a slider, some have text input etc. I have developed a view controller for each type of question.
Two example types of question controllers are: TextInputQuestionViewController and SliderQuestionViewController.
I have a rootViewcontroller named QuestionnaireViewController. This is defined as follows:
#import <UIKit/UIKit.h>
#import "JSONKit.h";
#import "dbConnector.h"
#import "SliderQuestionViewController.h";
#import "TextInputQuestionViewController.h";
#import "MainMenuProtocol.h";
#interface QuestionnaireViewController : UIViewController {
NSDictionary* questions;
NSMutableArray* questionArray;
NSMutableArray* answerArray;
dbConnector* db;
SliderQuestionViewController* currQ; //need to create a generic var
TextInputQuestionViewController* currQ;
NSInteger currQNum;
NSString* qaTitle;
NSString* secId;
id<MainMenuProtocol>delegate;
}
#property(nonatomic, retain) NSDictionary* questions;
#property(nonatomic, retain) NSMutableArray* questionArray;
#property(nonatomic, retain) NSMutableArray* answerArray;
#property(nonatomic, retain) dbConnector* db;
#property(nonatomic, retain) SliderQuestionViewController* currQ;
#property(nonatomic, retain) TextInputQuestionViewController* currTI;
#property(nonatomic) NSInteger currQNum;
#property(nonatomic, retain) NSString* qaTitle;
#property(nonatomic, retain) NSString* secId;
#property(nonatomic, retain) id <MainMenuProtocol> delegate;
-(void) setQuestions;
-(void) startQuestion:(NSInteger)index isLast:(BOOL)last;
-(void) loadQuestions;
-(void) initialise;
-(void) finishQuestionnaire:(id)sender;
-(void) switchViews:(id)sender;
#end
#import "QuestionnaireViewController.h"
#import "dbConnector.h"
#import "ASIHTTPRequest.h"
#import "JSONKit.h";
#import "Answer.h";
#implementation QuestionnaireViewController
#synthesize questions, questionArray, db, currQ, currQNum, answerArray, qaTitle, secId, delegate;
-(void)viewDidLoad{
[self initialise];
answerArray = [[NSMutableArray alloc]init];
[super viewDidLoad];
self.title = qaTitle; //set to whatever section is
}
-(void) initialise {
currQNum = 0;
[self loadQuestions];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Start" style:UIBarButtonItemStylePlain target:self action:#selector(switchViews:)];
self.navigationItem.rightBarButtonItem = anotherButton;
}
-(void) loadQuestions {
db = [[dbConnector alloc]init];
//code to initialise view
[db getQuestions:secId from:#"http://dev.speechlink.co.uk/David/get_questions.php" respondToDelegate:self];
}
//called when questions finished loading
//stores dictionary of questions
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSData *responseData = [request responseData];
NSString *json = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary *qs = [json objectFromJSONString];
self.questions = qs;
[json release];
[qs release];
[self setQuestions];
}
//assigns JSON to question objects
-(void) setQuestions {
questionArray = [[NSMutableArray alloc] init];
for (NSDictionary *q in self.questions) {
/* Create Question object and populate it */
id question;
if([[q objectForKey:#"type"] isEqualToString:#"Slider"]){
question = [[SliderQuestionViewController alloc]init];
//set min max values
}else if([[q objectForKey:#"type"] isEqualToString:#"Option"]){
}else if([[q objectForKey:#"type"] isEqualToString:#"TextInput"]){
question = [[TextInputQuestionViewController alloc]init];
}else if([[q objectForKey:#"type"] isEqualToString:#"ImagePicker"]){
}else{
//comments
}
//if else to create appropriate view controller - NEED to identify question type
[question setQuestionId:[q objectForKey:#"questionId"] withTitle:[q objectForKey:#"question"] number:[q objectForKey:#"questionNumber"] section:[q objectForKey:#"sectionId"] questionType: [q objectForKey:#"type"]];
/* Add it to question (mutable) array */
[questionArray addObject:question];
[question release];
}
}
-(void) startQuestion:(NSInteger)index isLast:(BOOL)last{
//currQ = [[QuestionViewController alloc]init];
currQ = [questionArray objectAtIndex:index];
//push currQ onto navigationcontroller stack
[self.navigationController pushViewController:currQ animated:YES];
[currQ addButton:self isLast: last];
}
//pushes new view onto navigation controller stack
-(void) switchViews:(id)sender{
Answer* ans = currQ.question.answer;
ans.questionId = currQ.question.qId;
ans.entryId = #"1";//temporary;
if(currQNum < [questionArray count] - 1){
if(currQNum > 0){
//if else for different input types
NSString* qt = currQ.question.qType;
if([qt isEqualToString:#"Slider"]){
ans.answer = currQ.sliderLabel.text;
}else if([qt isEqualToString:#"Option"]){
}else if([qt isEqualToString:#"TextInput"]){
//NSLog(#"%#", currQ.inputAnswer);
ans.answer = currQ.inputAnswer.text;
}else if([qt isEqualToString:#"ImagePicker"]){
}else{
}
[answerArray addObject: ans];
[ans release];
}
[self startQuestion:currQNum isLast:FALSE];
currQNum++;
}else{
ans.answer = currQ.sliderLabel.text;
[answerArray addObject: ans];
//store data temporarily - section finished
[self startQuestion:currQNum isLast:TRUE];
currQNum++;
}
[ans release];
}
-(void) finishQuestionnaire:(id)sender{
//go back to main manual
//if else statement for answers
NSString* answ = currQ.sliderLabel.text;
[answerArray addObject: answ];
[delegate finishedSection:answerArray section:secId];
[answ release];
[self.navigationController popToRootViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.questions = nil;
self.currQ = nil;
[super viewDidUnload];
}
//hide back button in navigation bar
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (void)dealloc {
[currQ release];
[db release];
[questionArray release];
[questions release];
[super dealloc];
}
#end
the problematic lines with the above are in the switchViews function. I need to make the answer equal to the specific input component in that question view (slider value, text input value). So I need to make currQ a type that can be instantiated using any view controller.
I therefore need a generic variable to hold the current question. currQ holds the current question, but at the moment is of type SliderQuestionViewController. I tried to change this to id, but it throws a load of "Request For member...not a structure of union" and also a load of misassigned pointer issues.
Let me know if you need more code.
This reads like you want a pointer for a UIViewController, so just use that as the type. Then you can cast it down to whatever subclass you like later. For example:
-(void)myAction:(UIViewController *)vc {
SpecialViewController *svc = (SpecialViewController *)vc;
...
}
In your case, declare
UIViewController* currQ;
and then cast it as needed in the implementation to access the different properties and methods of your two subclasses.
If you're looking for a 'generic' variable, you should be able to use id. Make sure you don't define the type as id*, the asterisk should not be present.
A better idea, though, is to create a superclass for your question viewcontrollers. Create a superclass called QuestionViewController that inherits from UIViewController and have the Slider and TextInput (and any others) inherit from QuestionViewController. Then you can define your variable as: QuestionViewController* currQ; You can put any common functionality in that superclass as well and eliminate duplication.
FirstViewController.h:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
{
NSArray *listData;
}
-(IBAction) GoToInsert: (id) sender;
#property (nonatomic, retain) NSArray *listData;
#end
FirstViewController.m:
-(IBAction) upisiRezultat:(id)sender
{
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName: nil bundle: nil];
[self presentModalViewController: secondView animated: NO];
[secondView release];
}
- (void)viewDidLoad
{NSArray *array = [[NSArray alloc] initWithObjects:#"236", #"46",
#"147", #"8", #"56", #"69", #"114", #"2",
#"96", #"518", #"2", #"54", #"236", nil];
self.listData = array;
[array release];
[super viewDidLoad];
}
SecondViewontroller.h
#interface SecondViewController : UIViewController {
}
-(IBAction) insert;
#end
SecondViewontroller.m
-(IBAction) insert
{
/* Here should be the code to insert some number in listData from FirstViewController */
}
So when the app loads it loads FirstViewController.xib and shows the listData array on screen, when I click button "Go to Insert" another view is loaded (SecondViewController.xib) with button "Insert" which should add some number into the array and display the new array on the first view.
How to do that?
You can access the parent view controller with self.parentViewController. Therefore something along these lines (meaning I haven't tested this -- you should) should work:
FirstViewController *firstViewController = self.parentViewController;
NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:firstViewControl.listData];
[newArray addObject:#"42"];
[firstViewController setListData:[NSArray arrayWithArray:newArray]];
[newArray release];
However, since you want to add objects to listArray, it would be more natural to use an NSMutableArray instead. Also, you are currently adding NSStrings to the array, when it looks more like you want to have NSNumber objects.
Alternately, and maybe easier, you could have the variables in your main AppDelegate.
Put:
int myNumber;
in the projectname_AppDelegate.h file
Then in each of your view controllers, you can import your AppDelegate.h file and then do something like:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
and then read or change:
appDelegate.myNumber
===
This is not something you should be doing all the time (you don't want your appDelegate to be a giant data repository) but it could give you a quick fix when needed...
I do not know if you have imported the SecondViewController.h , and I think I have an idea an what you are trying to do.