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];
Related
I have defined the protocol in Customer.h file which is shown below:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#end
The MasterViewController (left side) invokes the didSelectCustomer method as shown below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Customer *selectedCustomer = [customers objectAtIndex:[indexPath row]];
[self.delegate didSelectCustomer:selectedCustomer];
}
Now, I need to tell the DetailViewController (right side) to do something. The DetailViewController complies with the CustomerDelegate protocol.
#interface DetailViewController : UIViewController<UISplitViewControllerDelegate,CustomerDelegate>
{
}
-(void) didSelectCustomer:(Customer *)customer
{
NSLog(#"sssdasdasdasd");
}
The didSelectCustomer method is never invoked. I think I need to set the masterViewController.delegate = self but I am not sure where to set this thing up.
UPDATE 1:
I added the instance of MasterViewController inside the DetailViewController but it did not work:
- (void)viewDidLoad
{
[super viewDidLoad];
MasterViewController *master = [[MasterViewController alloc] init];
master.delegate = self;
}
SOLUTION:
In AppDelegate:
else
{
UISplitViewController *splitViewController = (UISplitViewController *) self.window.rootViewController;
splitViewController.delegate = [splitViewController.viewControllers lastObject];
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
// splitViewController.delegate = (id)navigationController.topViewController;
DetailViewController *detail =(DetailViewController *) [splitViewController.viewControllers lastObject];
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
MasterViewController *master = (MasterViewController *)masterNavigationController.topViewController;
master.delegate = detail;
}
You never explicitly declare yourself as the delegate to the Consumer class. Merely conforming to it won't cut it. Declare it in -viewDidLoad by creating an instance of Consumer, possibly like this:
-(void)viewDidLoad {
Consumer *consumer = [[Consumer alloc]init];
[consumer setDelegate:self];
}
You also don't declare a property for your delegate object in Consumer, so it can never actually be accessed. Do this first:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#property (weak) id <CustomerDelegate> delegate; //use assign or __unsafe_unretained if targeting <5.0.
#end
You can check if your class conforms to your protocol like so:
if (![delegate conformsToProtocol:#protocol(CustomerDelegate)]) {
[NSException raise:#"Delegate Exception"
format:#"Parameter does not conform to CustomerDelegate protocol at line %d", (int)__LINE__];
}
the split view controller's last object.
this object is return a UI navigation controller.
you know, then you can do yourself.
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];
I was wondering what is the best way to go about adding a new cell to a tableview in iOS. Let's say I have a firstviewcontroller and a secondviewcontroller. On the firstviewcontroller I have a tableview already populated with some data, I also have a navigation bar with an add button on the top. Tapping the add button will present a new view and then I want to pass data from that secondviewcontroller to firstviewcontroller and populate my tableview with it.
Thanks,
Sam
You secondViewController should create a delegate protocol. Your firstViewController should then be assigned as its delegate.
Once secondViewController saves the data it calls a method that your firstViewController should implement
A good exemple here:
How do I create delegates in Objective-C?
To get you started: secondViewController.h
#protocol secondViewControllerDelegate;
#interface secondViewController : UIViewController{
id<secondViewControllerDelegate> __unsafe_unretained delegate;
}
#property (nonatomic, unsafe_unretained) id<secondViewControllerDelegate> delegate;
#end
#protocol secondViewControllerDelegate <NSObject>
- (void)dataSaved;
#end
You can add a new class with tableView data source. initiate it with nesessary data (from both View controllers. use delegate to cooperate them) and after anu data chaging call [tableView setDataSource:]:
// DataSourceAtoZ.h
#import <Foundation/Foundation.h>
#import "MallsViewController.h"
#interface DataSourceCategory : NSObject <UITableViewDataSource> {
NSMutableArray *data;
UITableView *tableView;
}
#property (nonatomic, retain) NSMutableArray *data;
- (id)initWithData:(NSMutableArray *)d;
#end
then, anywhere in your code, compose data you wish to be in tableView and set dataSource:
NSMutableArray *dt = [[NSMutableArray alloc] init];
for (int i = 0; i < [categories count]; i++) {
NSMutableArray *names = [[NSMutableArray alloc] init];
[names addObject:[[categories objectAtIndex:i] objectAtIndex:0]];
for (int j = 1; j < [[categories objectAtIndex:i] count]; j++) {
NSRange match = [[[categories objectAtIndex:i] objectAtIndex:j] rangeOfString:[params objectAtIndex:0]];
if (match.length != 0) {
[names addObject:[[categories objectAtIndex:i] objectAtIndex:j]];
}
}
[dt addObject:names];
[names release];
}
dsCategory = [[DataSourceCategory alloc] init];
dsCategory = [dsCategory initWithData:dt];
[dt release];
You should create your arrays in the App delegate and then call them and change them however you want from there..
MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
once you have this line you can connect between two classes and call any methods on the delegate for example:
[appDelegate populateMyArray];
you don't add "new cells" like you described it, you use the same cells and populate them with different data.
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.