Move from one controller to another with segue and story boards - iphone

I have finished the first tutorial in the apple developer tool resources where you make an input, label and button what I want is to make it so when you press the button it takes you to a new scene so i have set up the segue, and i'd it as "testPush" now how do i actually get it to move when i push the button i get an error saying
**Thread 1: signal SIGABRT**
And the code that it is replying to is this
return UIApplicationMain(argc, argv, nil, NSStringFromClass([HelloWorldAppDelegate class]));
Anyone got any idea's i know u need to add in code for the segue to work however everything i have seen doesn't make sense or its jsut a block of code with little to none instruction on what it means how u get it to work etc. Thanks for any and all help
Other stuff you might need i'm not to sure
Scene one is called: HelloWorldViewController
Scene two is called: HelloWorldViewController2
EDIT
Heres the code from my scripts encase you need that thanks.
HelloWorldViewController.m
#import "HelloWorldViewController.h"
#interface HelloWorldViewController ()
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UILabel *label;
- (IBAction)changeGreeting:(id)sender;
#end
#implementation HelloWorldViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)changeGreeting:(id)sender {
self.userName = self.textField.text;
NSString *nameString = self.userName;
if ([nameString length] == 0) {
nameString = #"World";
}
NSString *greeting = [[NSString alloc] initWithFormat:#"Hello, %#!", nameString];
self.label.text = greeting;
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
}
return YES;
}
#end
HelloWorldViewController.h
#import <UIKit/UIKit.h>
#interface HelloWorldViewController : UIViewController <UITextFieldDelegate>
#property (copy,nonatomic) NSString *userName;
#end
And main.m
#import <UIKit/UIKit.h>
#import "HelloWorldAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([HelloWorldAppDelegate class]));
}
}

try adding a performseguewithidentifier in your IBAction, something like the following:
- (IBAction)changeGreeting:(id)sender {
self.userName = self.textField.text;
NSString *nameString = self.userName;
if ([nameString length] == 0) {
nameString = #"World";
}
NSString *greeting = [[NSString alloc] initWithFormat:#"Hello, %#!", nameString];
self.label.text = greeting;
[self performSegueWithIdentifier:#"segueId" sender:nil];
}
that should push the new for you.

Related

Am I on the right track with my singleton?

I asked a question yesterday regarding my table view and linking unique detail views to each cell in the table view. I believe I got a good answer to my question here. (Hopefully you can read that post and see what I need). Basically I wanted to know if I am making my singleton correctly. Here is my code:
timerStore.h
#import "Tasks.h"
#interface timerStore : NSObject
{
NSMutableDictionary *allItems;
}
+(timerStore *)sharedStore;
-(NSDictionary *)allItems;
-(NSTimer *)createTimerFor:(Tasks *)t inLocation: (NSIndexPath *)indexPath;
-(void)timerAction;
#end
timerStore.m
#implementation timerStore
+(timerStore *)sharedStore{
static timerStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[super allocWithZone:nil]init];
return sharedStore;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedStore];
}
-(id)init {
self = [super init];
if (self) {
allItems = [[NSMutableDictionary alloc]init];
}
return self;
}
-(NSDictionary *)allItems{
return allItems;
}
-(NSTimer *)createTimerFor:(Tasks *)t inLocation: (NSIndexPath *)indexPath {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:t.timeInterval target:self selector:#selector(timerAction) userInfo:nil repeats:1.0];
[allItems setObject:timer forKey:indexPath];
return timer;
}
-(void)timerAction{
//custom properties here
}
#end
I'm kind of confused because I was under the impression that a cell's index path gets recycled as you scroll down (dequeue). I may be wrong though. Anyway, am I on the right path to making a singleton as the guy in the link suggested?
The best way to implement App Singleton is as follows
Header file
#import <Foundation/Foundation.h>
#interface AppSingleton : NSObject
#property (nonatomic, retain) NSString *username;
+ (AppSingleton *)sharedInstance;
#end
Implementation File
#import "AppSingleton.h"
#implementation AppSingleton
#synthesize username;
+ (AppSingleton *)sharedInstance {
static AppSingleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
// Initializing
- (id)init {
if (self = [super init]) {
username = [[NSString alloc] init];
}
return self;
}
#end
Note:
What this does is it defines a static variable (but only global to this translation unit) called sharedInstance which is then initialised once and only once in sharedInstance Method. The way we ensure that it’s only created once is by using the dispatch_once method from Grand Central Dispatch (GCD). This is thread safe and handled entirely by the OS for you so that you don’t have to worry about it at all.
Using Singleton To set value
[[AppSingleton sharedInstance] setUsername:#"codebuster"];
Using Singleton to get value.
NSString *username = [[AppSingleton sharedInstance] username];
Further Reference and Reading

Can not pass value of textfield to other viewcontroller in ios

I want to pass value of textfield in LoginView to uploadview but UserLogin1 always is NULL ( 0x000000)
This is my codes:
loginvuew.h
#property (nonatomic,retain) IBOutlet UITextField *username;
loginview.m
-(IBAction)LoginButton:(id)sender{
uploadview= [[UploadTab alloc] initWithFrame:CGRectMake(0,0,0,0) andUsertring:username.text];
}
uploadview.h
#property (nonatomic, copy) NSString *UserLogin1;
- (id)initWithFrame:(CGRect)frame andUsertring:(NSString *)strUser;
uploadview.m
- (id)initWithFrame:(CGRect)frame andUsertring:(NSString *)strUser
{
if (self) {
UserLogin1=[[NSString alloc] init];
UserLogin1 = strUser;
}
return self;
}
- (void)viewDidLoad
{
NSLog(#"User login: %#",UserLogin1);
self.navigationItem.title = [NSString stringWithFormat: #"Hello, %#",UserLogin1];
}
WHen run in initWithFrame(), string passing correct but in ViewDidLoad is not correct. And UserLogin1 variable always is 0x00000. DO you have sugesstions? Thansk in advance
You are messing up things I think. What class is an UploadTab ? The view does not have a method viewDidload ! It's UIViewController's one. If it is ViewController then you should allocate it properly with initWithNibName:bundle or smth like that.
ADDED:
Your code missing actual alloc-init method
- (id)initWithFrame:(CGRect)frame andUsertring:(NSString *)strUser
{
// self is nil here! It is in almost every cases done like self = [[super alloc] initBlaBla]
if (self) {
UserLogin1=[[NSString alloc] init];
UserLogin1 = strUser;
}
return self;
}

iPhone Application Error Problem

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.

Data going missing when passed between threads using a Singleton

Edit:
Thanks #BlackFrog. I think I'm nearer now, but the values are still not get getting through...
The values are set as shown by logs within [progressController updateProgressSummary:...] but are nil when I log them in progressUpdate initWithProgressUpdate:.... as shown below.
I'm slightly confused over which property is used the one set for progressUpdate or the ones set for each of the 3 components of progressUpdate. I have changed the 3 individual properties from assign to retain as suggested and have also tried doing the same with the overall progressUpdate property too (not shown here).
progressController.h
......
#property (nonatomic, assign) ProgressUpdate *progressUpdate;
progressController.m
// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {
// These report the proper values
DLog(#"Reporting Summary - %s", [summary UTF8String]);
DLog(#"Reporting Detail - %s", [detail UTF8String]);
DLog(#"Reporting Complete - %i", [complete intValue]);
if (summary != nil)
self.progressUpdate.summaryText = summary;
self.progressUpdate.detailText = detail;
self.progressUpdate.percentComplete = complete;
ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWithProgressUpdate:progressUpdate];
[self.delegate performSelectorOnMainThread:#selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO];
[progressUpdateForIssue release];
}
But then a few milliseconds later...., inside the object....they're nil.
progressUpdate.h
.....
#property (nonatomic, retain) NSString *summaryText;
#property (nonatomic, retain) NSString *detailText;
#property (nonatomic, retain) NSNumber *percentComplete;
progressUpdate.m
-(id) initWithProgressUpdate:(ProgressUpdate *)update {
if ((self = [super init])) {
summaryText = [update.summaryText copy];
detailText = [update.detailText copy];
percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue]];
}
// These report nil values
DLog(#"Reporting in progUpdate summaryText - %s", [summaryText UTF8String]);
DLog(#"Reporting in progUpdate detailText - %s", [detailText UTF8String]);
DLog(#"Reporting in progUpdate percentComplete - %i", [percentComplete intValue]);
return self;
}
end of update
I need some help with passing data in a custom class from one thread to another. Its there before the pass but then disappears upon arrival. I've tried everything I know, but to no avail.
My background thread calls ProgressController and passes it details of the current progress. That in turn does performSelectorOnMainThread on ProgressController's delegate (the view controller) to display the details.
It was all working fine when I was passing through a single NSString, but I need to pass two strings and a number and as performSelectorOnMainThread can only pass one object, I have encapsulated these in a custom object - ProgressUpdate.
The data gets through to ProgressController correctly but is null by the time that it appears in the View Controller. I know this as I've put NSLogs in various places.
I wonder if its to do with:
multithreading and custom objects
the fact that ProgressController is a singleton, which is why I have then alloc'd a new ProgressUpdate each time its called, but that has not helped.
Any ideas welcome. For clarity, the code is below.
ProgressUpdate.h
#import <Foundation/Foundation.h>
#interface ProgressUpdate : NSObject {
NSString *summaryText;
NSString *detailText;
NSNumber *percentComplete;
}
#property (nonatomic, assign) NSString *summaryText;
#property (nonatomic, assign) NSString *detailText;
#property (nonatomic, assign) NSNumber *percentComplete;
-(id) initWith:(ProgressUpdate *)update;
#end
ProgressUpdate.m
#import "ProgressUpdate.h"
#implementation ProgressUpdate
#synthesize summaryText, detailText, percentComplete;
-(id) initWith:(ProgressUpdate *)update {
self = [super init];
self.summaryText = update.summaryText;
self.detailText = update.detailText;
self.percentComplete = update.percentComplete;
return self;
}
#end
ProgressController.m
static ProgressController *sharedInstance;
+ (ProgressController *)sharedInstance {
#synchronized(self) {
if (!sharedInstance)
[[ProgressController alloc] init];
}
return sharedInstance;
}
+(id)alloc {
#synchronized(self) {
NSAssert(sharedInstance == nil, NSLocalizedString(#"Attempted to allocate a second instance of a singleton ProgressController.", #"Attempted to allocate a second instance of a singleton ProgressController."));
sharedInstance = [super alloc];
}
return sharedInstance;
}
-(id) init {
if (self = [super init]) {
[self open];
}
return self;
}
.........
// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {
if (summary != nil)
self.progressUpdate.summaryText = summary;
self.progressUpdate.detailText = detail;
self.progressUpdate.percentComplete = complete;
ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWith:progressUpdate];
[self.delegate performSelectorOnMainThread:#selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO];
[progressUpdateForIssue release];
}
RootViewController.m
// Delegate method to display specific text in Progress label
- (void) displayProgress:(ProgressUpdate *)update {
[progressSummaryLabel setText:update.summaryText];
[progressDetailLabel setText:update.detailText];
[progressBar setProgress:[update.percentComplete intValue]];
[progressView setNeedsDisplay];
}
In the init method, you are only assigning the ivars and not retaining them in the new object.
Redo your init method as the following:
-(id) initWithProgressUpdate:(ProgressUpdate *)update {
if ((self = [super init])) {
summaryText = [update.summaryText copy];
detailText = [update.detailText copy];
percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue];
}
return self;
}
Couple of points:
You should not use accessor in the init method
Rename your init method to be a lot clear
In the #property, change the assign to retain
Try removing the statement '[progressUpdateForIssue release];' in the method
'-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete '.
Also change the property attribute from 'assign' to 'retain' in your class ProgressUpdate.
You could release those properties in the dealloc method .
Good luck.

Delegate not working

I have this code in my viewController:
- (GraphModel *)graphModel
{
if (!graphModel) {
graphModel = [[GraphModel alloc] init];
NSLog(#"graphModel = %#", graphModel);
}
return graphModel;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.graphView.delegate = [self graphModel];
NSLog(#"self.graphview.delegate = %#", self.graphView.delegate);
[self updateUI];
}
but the NSLog just says (null) for self.graphview.delegate
even though the NSLog in graphModel says that I successfully created an object. How can this be?
this is the code for the graphViewDelegate
#class GraphView;
#protocol GraphViewDelegate
- (double)yValueForGraphView:(GraphView *)requestor atPosition:(int)i withPrecision:(int)precision;
- (double)scaleForGraphView:(GraphView *)requestor;
#end
#interface GraphView : UIView {
id <GraphViewDelegate> delegate;
}
#property (assign) id <GraphViewDelegate> delegate;
#end
and then I have #synthesize delegate in graphView.m
Most likely guess: graphView is nil. Calling any method on a nil object has no effect and returns nil, and the .delegate is actually a call to the getter or setter as appropriate. I recommend you add:
NSLog(#"self.graphview = %#", self.graphView);
As a quick verification.