IOS app not recognizing accelerometer data or text input - ios

This code is not giving me any output or even setting up the accelerometer it seems. I am first and foremost trying to get the device to recognize the accelerometer and the thresh input. It is a simple accelerometer app where I can set up a thresh hold variable where I can then compare some values from previous and current accelerometer output. The thresh input is a simple text box for input. Any help would be appreciated.
#import "ViewController.h"
#interface ViewController (){
//set up variables for switch and BOOL variables
BOOL isStarted;
BOOL switchX;
BOOL switchY;
BOOL switchZ;
}
#end
#implementation ViewController
-(IBAction)startSensor:(id)sender{
//start with displaying the values...then move onto the just flash method
//set up the accelerometer function within the button press
[self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[self showAccelerationdata:accelerometerData.acceleration];
//print statements for future debugging. only in the log files though
if (error){
NSLog(#"%#", error);
}
}];
}
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
currentAccelx = 0;
currentAccely = 0;
currentAccelz = 0;
previousAccelx = 0;
previousAccely = 0;
previousAccelz = 0;
//set up class for movement controls
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = .1;
}
-(IBAction)checkSwitchx:(UISwitch *)sender{
if (sender.on){
switchX = TRUE;
}
else{
switchX = FALSE;
}
}
-(IBAction)checkSwitchy:(UISwitch *)sender{
if (sender.on){
switchY = TRUE;
}
else{
switchY = FALSE;
}
}
-(IBAction)checkSwitchz:(UISwitch *)sender{
if (sender.on){
switchZ = TRUE;
}
else{
switchZ = FALSE;
}
}
-(void)showAccelerationdata:(CMAcceleration)acceleration
{
self.view.backgroundColor = [UIColor whiteColor];
if ([thresh.text length] == 0){
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"numbers are blank!" message:#"Please enter numbers!"
delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles: nil];
[alert show];
[alert resignFirstResponder];
}
else{
threshold = [thresh.text floatValue];
NSLog(#"%#", thresh);
}
}
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

Show the code where you set self.motionManager.
If you don't actually create a CMMotionManager, you are sending messages to nil in the startSensor: method, and you will observe that no accelerometer callbacks are executed.

I did not set up my CMMotionManager correctly it seems. After I looked at my setup it was pretty straight-forward on how to get everything to display correctly.

Related

Red recording bar distorting view

I'm having a heck of a time figuring this out.
I have a modal view that appears when tapping on one of the tabs of a tab bar. In the new view that takes over the whole screen, there is a button a user taps to start recording audio, and when they're finished recording audio, or if they cancel recording, the modal view is dismissed.
The problem is that, once they start recording, that red recording bar should appear on this new view. But it's not. And as soon as that view is dismissed, in the next view that is presented (a table view, which is found in one of the tabs), you can see the red recording bar at the top for a split second and it disappears BUT it shoves the tab bar down the screen and obscures part of the tab bar, which you can see in the third screenshot below.
Modal view pops up - recording is currently in progress, but red recording indicator is not showing at the top
Right when the recording is done and the view is about to disappear, the red bar appears
And once the view disappears and we're left with the table view that lives in one of the tabs, the tab bar is shoved down past the bottom of the screen :( It SHOULD look like this (with the fourth tab selected):
My questions:
1) What am I doing wrong that's causing the red recording bar to NOT show up in the modal view?
2) Is there a way to maybe refresh this view from the screenshot so that when it appears, it resizes properly?
Here's the code. I removed some of the non-important stuff that doesn't deal with the views.
#interface AudioViewController ()
#end
#implementation AudioViewController
#synthesize fileData;
UILabel *countdownLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
self.recipients = [[NSMutableArray alloc] init];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.audioPicker = [[UIViewController alloc] init];
self.audioPicker.view.backgroundColor = [UIColor yellowColor];
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
PFQuery *query = [self.friendsRelation query];
[query orderByAscending:#"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error %# %#", error, [error userInfo]);
}
else {
self.friends = objects;
[self.tableView reloadData];
}
}];
UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
cancelBtn.frame = CGRectMake(50.0, 200.0, 200.0, 200.0);
cancelBtn.titleLabel.font = [UIFont systemFontOfSize:20];
[cancelBtn setTitle:#"Cancel" forState:UIControlStateNormal];
[self.audioPicker.view addSubview:cancelBtn];
cancelBtn.center = CGPointMake(self.view.center.x, 400);
[cancelBtn addTarget:self action:#selector(exitRecordingScreen) forControlEvents:UIControlEventTouchUpInside];
UIButton *recordBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
recordBtn.frame = CGRectMake(50.0, 50.0, 200.0, 200.0);
recordBtn.titleLabel.font = [UIFont systemFontOfSize:50];
[recordBtn setTitle:#"Record" forState:UIControlStateNormal];
recordBtn.center = CGPointMake(self.view.center.x, 100);
[self.audioPicker.view addSubview:recordBtn];
if ([self respondsToSelector:#selector(timeout)]) {
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeout) userInfo:nil repeats:NO];
} else {
NSLog(#"Error: missing selector");
}
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDuckOthers
error:nil];
if (!fileData) {
[self presentViewController:self.audioPicker animated:NO completion:nil];
NSLog(#"File data: %#", fileData);
[recordBtn addTarget:self action:#selector(startRecordingAudio) forControlEvents:UIControlEventTouchUpInside];
} else {
NSLog(#"Existing File data: %#", fileData);
}
}
- (void) timeout {
[self.navigationController popViewControllerAnimated:YES];
}
# pragma mark - Audio Recording Methods
////////
// Removed some stuff here that is not manipulating views
////////
- (void) stopRecordingOnAudioRecorder:(AVAudioRecorder *)paramRecorder{
/* Just stop the audio recorder here */
[paramRecorder stop];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
successfully:(BOOL)flag{
if (flag) {
NSLog(#"Stopped recording process");
NSError *playbackError = nil;
NSError *readingError = nil;
fileData = [NSData dataWithContentsOfURL:[self audioRecordingPath]
options:NSDataReadingMapped
error:&readingError];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData
error:&playbackError];
if (self.audioPlayer != nil) {
self.audioPlayer.delegate = self;
//Prepare and start playing
if ([self.audioPlayer prepareToPlay] && [self.audioPlayer play]) {
NSLog(#"Started playing recorded audio");
} else {
NSLog(#"Couldn't play recorded audio");
}
} else {
NSLog(#"Failed to create audio player");
}
} else {
NSLog(#"Stopping audio recording failed");
}
self.audioRecorder = nil;
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
successfully:(BOOL)flag{
if (flag){
NSLog(#"Audio player stopped correctly.");
} else {
NSLog(#"Audio player did not stop correctly.");
}
if ([player isEqual:self.audioPlayer]){
self.audioPlayer = nil;
} else {
/* This is not the player */
}
}
# pragma mark - TableView methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.friends count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
cell.textLabel.text = user.username;
// makes sure checkmark isn't reused if user didn't explicitly select name
if ([self.recipients containsObject:user.objectId]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)reset {
self.audioFile = nil;
}
// User hits "Cancel" button
-(void)exitRecordingScreen {
[self reset];
[self.presentedViewController dismissViewControllerAnimated:NO completion:nil];
[self.tabBarController setSelectedIndex:0];
NSLog(#"exit recording screen button pressed");
}
- (IBAction)send:(id)sender {
if (self.audioFile == nil) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Please try again." message:#"Please record audio again to share." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[self presentViewController:self.audioPicker animated:NO completion:nil];
} else {
[self uploadMessage];
[self.tabBarController setSelectedIndex:0];
}
}
// Cancel sending recorded file
- (void)cancel:(id)sender {
fileData = nil;
[self reset];
[self.tabBarController setSelectedIndex:0];
}
#end
Sorry for the wall of text and the length. I'm really stumped.
Solution : You have to reset frame for UITabBarController.
1. Initially frame for UITabBarController will be (0,0,screenWidth,screenHeight).
2. But when this recording red bar appear it becomes (0,20,screenWidth,screenHeight)
3. Here you are supposed to change height for UITabBarController
CGRect changedFrame = objMainTabBarController.view.frame;
changedFrame.size.height = [UIScreen mainScreen].bounds.size.height - CGRectGetMinY(changedFrame);
objMainTabBarController.view.frame = changedFrame;
That's it..

How do I add an Event Title (from a UI Text View) to a Calendar Event created by my APP?

I've developed an App and my App needs to create an event at device's calendar. I've been trough EventKitProgGuide and studied the SimpleEKDemo.
By simplifying the code from SimpleEKDemo I generated the code shown below that opens an 'calendar's event screen' straight from my app and generates the event properly. I'm OK with that.
Now I need to use the text content of an UITextView as the Event Title!
Could somebody help my with that code?
Thanks,
Marcos
Here's my code:
#.h
#import <EventKitUI/EventKitUI.h>
#import <EventKit/EventKit.h>
#property (nonatomic, strong) EKEventStore *eventStore;
#property (nonatomic, strong) EKEvent *event;
#property (nonatomic, strong) EKCalendar *defaultCalendar;
#property (nonatomic, strong)
IBOutlet UITextView *textView1;
- (IBAction)agendar:(UIButton *)sender;
#.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.eventStore = [[EKEventStore alloc]init];
self.textView1.text = #"hello world!";
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self checkEventStoreAccessForCalendar];
}
- (IBAction)agendar:(UIButton *)sender {
EKEventEditViewController *addController = [[EKEventEditViewController alloc] init];
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self presentViewController:addController animated:YES completion:nil];
self.event = [EKEvent eventWithEventStore:self.eventStore];
// Jeff's suggested code:
self.event.title = self.textView1.text;
// Jeff's SaveEvent Sugestion
NSError *err;
[self.eventStore saveEvent:self.event span:EKSpanThisEvent error:&err];
}
-(void)checkEventStoreAccessForCalendar
{
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
switch (status)
{
case EKAuthorizationStatusAuthorized: [self accessGrantedForCalendar];
break;
case EKAuthorizationStatusNotDetermined: [self requestCalendarAccess];
break;
case EKAuthorizationStatusDenied:
case EKAuthorizationStatusRestricted:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alerta de Privacidade" message:#"Permissão de acesso ao calendário não concedida."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
break;
default:
break;
}
}
-(void)requestCalendarAccess
{
[self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
if (granted)
{
Tela8ViewController * weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf accessGrantedForCalendar];
});
}
}];
}
-(void)accessGrantedForCalendar
{
self.defaultCalendar = self.eventStore.defaultCalendarForNewEvents;
}
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
{
[self dismissViewControllerAnimated:YES completion:^
{
if (action != EKEventEditViewActionCanceled)
{
dispatch_async(dispatch_get_main_queue(), ^{
});
}
}];
}
There are two ways to create an event with EventKit. Your sample code currently has a mix of both, so you should pick just one!
A: Create an event with certain fields pre-set (in your case, the title), and allow the user to review and save it (or choose to cancel and discard it) with EKEventEditViewController. In this case, your code doesn't need to commit the event - just watch for the delegate response to confirm that it happened.
- (void)createEventWithTitle:(NSString *)title
{
EKEvent *newEvent = [EKEvent eventWithEventStore:self.eventStore];
newEvent.title = title;
EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];
controller.eventStore = self.eventStore;
controller.event = newEvent;
controller.editViewDelegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
// EKEventEditViewController delegate method
- (void)eventEditViewController:(EKEventEditViewController *)controller didCompleteWithAction:(EKEventEditViewAction)action
{
if (action == EKEventEditViewActionSaved) {
// event has been committed
}
// alternatives are EKEventEditViewActionCanceled, EKEventEditViewActionDeleted
[self dismissViewControllerAnimated:YES completion:Nil];
}
B. You can create an event and commit it entirely in your code, if you don't need user involvement. In this case you can use EKEventStore saveEvent: span: error: instead of relying on EKEventEditViewController.
Have you tried something like
self.event.title = self.textView1.text;
?

validation method doesn't gets called and segue doesn't gets triggered

I am trying to implement a sign up process with a parse backend. I have a validation method called processFieldEntries and once the done button gets enabled, I try to trigger the segue that I setup modally from my view controller(not from the done button) from view did appear method but neither the validation method gets called nor the segue gets triggered. I setup some debug and logging breakpoints for debugging but, I couldn't go any further apart from the fact that it does not see the view did load. I also tried setting up the segue from the done button. When I did that, the segue gets triggered, not from the code but from storyboard my storyboard here. If someone can help me to figure out how to call processfieldentriees along with the segue, I would really appreciate. Thank you.
NewUserSignUpViewController.h
#import <UIKit/UIKit.h>
#import "ProfileViewController.h"
#interface NewUserSignUpViewController : UIViewController<UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UIBarButtonItem *barButtonItem;
#property (strong, nonatomic) IBOutlet UITextField *usernameField;
#property (strong, nonatomic) IBOutlet UITextField *passwordField;
#property (strong, nonatomic) IBOutlet UITextField *repeatPasswordField;
- (IBAction)doneEvent:(id)sender;
- (IBAction)cancelEvent:(id)sender;
#end
NewUserSignUpViewController.m
#import "NewUserSignUpViewController.h"
#import "ProfileViewController.h"
#import <Parse/Parse.h>
#import "ActivityView.h"
#interface NewUserSignUpViewController ()
-(void)processFieldEntries;
- (void)textInputChanged:(NSNotification *)note;
- (BOOL)shouldEnableDoneButton;
#end
#implementation NewUserSignUpViewController
#synthesize barButtonItem = _doneButtonInTheBar;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_usernameField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_passwordField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_repeatPasswordField];
}
-(void)viewDidAppear:(BOOL)animated
{
[_usernameField becomeFirstResponder];
[super viewDidAppear:animated];
//perform the segue
if (_doneButtonInTheBar.enabled == YES) {
[self performSegueWithIdentifier:#"segueToProfileView" sender:self];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
}
#pragma mark - UITextFieldDelegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{ textField.delegate = self;
if (textField == _usernameField) {[_usernameField becomeFirstResponder];}
if (textField == _passwordField){[_passwordField becomeFirstResponder];}
if (textField == _repeatPasswordField)
{
[_repeatPasswordField becomeFirstResponder];
[self processFieldEntries];
}
return YES;
}
-(BOOL)shouldEnableDoneButton
{
BOOL enableDoneButton = NO;
if (_usernameField.text != nil && _usernameField.text.length != 0 &&_passwordField.text != nil &&
_passwordField.text.length !=0 && _repeatPasswordField.text != nil &&
_repeatPasswordField.text.length != 0) {
enableDoneButton = YES;
[self processFieldEntries];
}
return enableDoneButton;
}
-(void)textInputChanged:(NSNotification *)note
{
_doneButtonInTheBar.enabled = [ self shouldEnableDoneButton];
}
- (IBAction)doneEvent:(id)sender {
[_usernameField resignFirstResponder];
[_passwordField resignFirstResponder];
[_repeatPasswordField resignFirstResponder];
NSLog(#"processfieldentries");
[self processFieldEntries];
}
- (IBAction)cancelEvent:(id)sender {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)processFieldEntries
{
// Check that we have a non-zero username and passwords.
// Compare password and passwordAgain for equality
// Throw up a dialog that tells them what they did wrong if they did it wrong.
NSString *username = _usernameField.text;
NSString *password = _passwordField.text;
NSString *passwordAgain = _repeatPasswordField.text;
NSString *errorText = #"Please ";
NSString *usernameBlankText = #"enter a username";
NSString *passwordBlankText = #"enter a password";
NSString *joinText = #", and ";
NSString *passwordMismatchText = #"enter the same password twice";
BOOL textError = NO;
// Messaging nil will return 0, so these checks implicitly check for nil text.
if (username.length == 0 || password.length == 0 || passwordAgain.length == 0) {
textError = YES;
//setting the keyboard for th first missing output
if (passwordAgain.length == 0) {
[_repeatPasswordField becomeFirstResponder];
}
if (password.length == 0) {
[_passwordField becomeFirstResponder];
}
if (username.length == 0) {
[_usernameField becomeFirstResponder];
}
if (username.length == 0) {
errorText = [errorText stringByAppendingString:usernameBlankText];
}
if (password.length == 0 || passwordAgain.length == 0) {
if (username.length == 0) { // We need some joining text in the error:
errorText = [errorText stringByAppendingString:joinText];
}
errorText = [errorText stringByAppendingString:passwordBlankText];
}
}else if ([password compare:passwordAgain] != NSOrderedSame)
{errorText = [errorText stringByAppendingString:passwordMismatchText];
[_passwordField becomeFirstResponder];}
if (textError) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:errorText message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
return;
// Everything looks good; try to log in.
// Disable the done button for now.
_doneButtonInTheBar.enabled = NO;
ActivityView *activityView = [[ActivityView alloc]initWithFrame:CGRectMake(0.f, 0.f, self.view.frame.size.width, self.view.frame.size.height)];
UILabel *label = activityView.label;
label.text = #"signing up";
label.font = [UIFont boldSystemFontOfSize:20.0f];
[activityView.activityIndicator startAnimating];
[activityView layoutSubviews];
[self.view addSubview:activityView];
// Call into an object somewhere that has code for setting up a user.
// The app delegate cares about this, but so do a lot of other objects.
// For now, do this inline.
NSLog(#"does it reach here");
PFUser *user = [PFUser user];
user.username = username;
user.password = password;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
_doneButtonInTheBar.enabled = [self shouldEnableDoneButton];
[activityView.activityIndicator stopAnimating];
[activityView removeFromSuperview];
// Bring the keyboard back up, because they'll probably need to change something.
[_usernameField becomeFirstResponder];
return;
}
// Success!
[activityView.activityIndicator stopAnimating];
[activityView removeFromSuperview];
}];
}
}
#end
You could try not to use performSegueWithIdentifier inside viewDidAppear (performSegue actually take you to the other ViewController). Instead you could call it from an IBAction method connected to the done button, after calling in the same method processFieldEntries. I hope this can help you :)

Code does not wait for user to finish typing in the repeat password section

I am trying to setup a signup view with using parse.com as backend but for some reason whenever i start typing in the reenter password field, as soon as i type something, it starts going through this
else if ([password compare:passwordAgain] != NSOrderedSame) {
// We have non-zero strings.
// Check for equal password strings.
textError = YES;
errorText = [errorText stringByAppendingString:passwordMismatchText];
[_reEnterPasswordField becomeFirstResponder];
NSLog(#"stops here");
}
method and sends me the error message passwordMismatchText. It goes through this message everytime i change a word whether i added or deleted it. When I use the same methods with xib the files i had no problem. But after I try to do the same thing with storyboards I am having this issue. I tried creating a user default for _doneButton.enabled == YES and put an another if around the errorText =[...] message, but did not solve the problem. I appreciate for the help.
SignUpViewController.h
#import <UIKit/UIKit.h>
#interface SignUpViewController : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *doneButton;
#property (weak, nonatomic) IBOutlet UITextField *userNameField;
#property (weak, nonatomic) IBOutlet UITextField *passwordField;
#property (weak, nonatomic) IBOutlet UITextField *reEnterPasswordField;
- (IBAction)done:(id)sender;
- (IBAction)cancel:(id)sender;
#end
SignUpViewController.m
#import "SignUpViewController.h"
#import <Parse/Parse.h>
#import "ActivityView.h"
#import "ProfileViewController.h"
#interface SignUpViewController ()
- (void)textInputChanged:(NSNotification *)note;
-(void)processFieldEntries;
- (BOOL)shouldEnableDoneButton;
#end
#implementation SignUpViewController
#synthesize doneButton = _doneButton;
#synthesize userNameField = _userNameField;
#synthesize passwordField = _passwordField;
#synthesize reEnterPasswordField = _reEnterPasswordField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter ]addObserver:self selector:#selector(textInputChanged:) name: UITextFieldTextDidChangeNotification object:_userNameField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_passwordField];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(textInputChanged:) name:UITextFieldTextDidChangeNotification object:_reEnterPasswordField];
_doneButton.enabled = NO;
NSLog(#"nsnotification is working fine");
}
-(void)viewWillAppear:(BOOL)animated
{
[_userNameField becomeFirstResponder];
[super viewWillAppear:animated];
NSLog(#"indeed usernamefield became a first responder");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == _userNameField ) {
[_userNameField becomeFirstResponder];
}
if (textField == _passwordField) {
[_passwordField becomeFirstResponder];
}
if (textField == _reEnterPasswordField)
{
[_reEnterPasswordField becomeFirstResponder];
}
NSLog(#"keyboard action works fine ");
return YES;
}
-(BOOL)shouldEnableDoneButton
{
BOOL enableDoneButton = NO;
if (_userNameField.text != nil &&
_userNameField.text.length > 0 &&
_passwordField.text != nil &&
_passwordField.text.length > 0 &&
_reEnterPasswordField.text != nil &&
_reEnterPasswordField.text.length > 0)
{
[self processFieldEntries];
enableDoneButton = YES;
NSLog(#"done button enabled");
}
return enableDoneButton;
}
-(void)textInputChanged:(NSNotification *)note
{
_doneButton.enabled = [self shouldEnableDoneButton];
}
- (IBAction)done:(id)sender {
[_userNameField resignFirstResponder];
[_passwordField resignFirstResponder];
[_reEnterPasswordField resignFirstResponder];
[self processFieldEntries];
NSLog(#"do you see this");
}
- (IBAction)cancel:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
-(void)processFieldEntries
{
// Check that we have a non-zero username and passwords.
// Compare password and passwordAgain for equality
// Throw up a dialog that tells them what they did wrong if they did it wrong.
NSString *username = _userNameField.text;
NSString *password = _passwordField.text;
NSString *passwordAgain = _reEnterPasswordField.text;
NSString *errorText = #"Please ";
NSString *usernameBlankText = #"enter a username";
NSString *passwordBlankText = #"enter a password";
NSString *joinText = #", and ";
NSString *passwordMismatchText = #"enter the same password twice";
BOOL textError = NO;
NSLog(#"validation begins here");
// Messaging nil will return 0, so these checks implicitly check for nil text.
if (username.length == 0 || password.length == 0 || passwordAgain.length == 0) {
textError = YES;
// Set up the keyboard for the first field missing input:
if (passwordAgain.length == 0) {
[_reEnterPasswordField becomeFirstResponder];
}
if (password.length == 0) {
[_passwordField becomeFirstResponder];
}
if (username.length == 0) {
[_userNameField becomeFirstResponder];
}
if (username.length == 0) {
errorText = [errorText stringByAppendingString:usernameBlankText];
}
if (password.length == 0 || passwordAgain.length == 0) {
if (username.length == 0) { // We need some joining text in the error:
errorText = [errorText stringByAppendingString:joinText];
}
errorText = [errorText stringByAppendingString:passwordBlankText];
}
} else if ([password compare:passwordAgain] != NSOrderedSame) {
// We have non-zero strings.
// Check for equal password strings.
textError = YES;
errorText = [errorText stringByAppendingString:passwordMismatchText];
[_reEnterPasswordField becomeFirstResponder];
NSLog(#"stops here");
}
if (textError) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:errorText message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
return;
}
NSLog(#"validation works just fine");
// Everything looks good; try to log in.
// Disable the done button for now.
_doneButton.enabled = NO;
ActivityView *activityCircle = [[ActivityView alloc] initWithFrame:CGRectMake(0.f, 0.f, self.view.frame.size.width, self.view.frame.size.height)];
UILabel *label = activityCircle.label;
label.text = #"Signing You Up";
label.font = [UIFont boldSystemFontOfSize:20.f];
[activityCircle.activityIndicator startAnimating];
[activityCircle layoutSubviews];
[self.view addSubview:activityCircle];
NSLog(#"activity view works just fine");
//parse registeration
// Call into an object somewhere that has code for setting up a user.
// The app delegate cares about this, but so do a lot of other objects.
// For now, do this inline.
PFUser *user = [PFUser user];
user.username = username;
user.password = password;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
_doneButton.enabled = [self shouldEnableDoneButton];
[activityCircle.activityIndicator stopAnimating];
[activityCircle removeFromSuperview];
// Bring the keyboard back up, because they'll probably need to change something.
[_userNameField becomeFirstResponder];
return;
}
// Success!
[activityCircle.activityIndicator stopAnimating];
[activityCircle removeFromSuperview];
//add the next screen here
}];
NSLog(#"user signedup just fine");
//now pass the view from sign up to profile view
}
/*
//this one didnt work
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ProfileViewController *myProfileView = [segue destinationViewController];
if (_doneButton.enabled == YES) {
[myProfileView performSegueWithIdentifier:#"SignUpSegue" sender:_doneButton];
}
}
*/
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
NSLog(#"is this method visible");
if (_doneButton.enabled == YES) {
[self performSegueWithIdentifier:#"SignUpSegue" sender:_doneButton];
}
return NO;
}
#end
this is the log files that I am getting
2013-09-06 02:49:19.938 nsnotification is working fine
2013-09-06 02:49:19.942 indeed usernamefield became a first responder
2013-09-06 02:49:47.446 validation begins here
2013-09-06 02:49:47.448 stops here
2013-09-06 02:49:47.485 done button enabled
2013-09-06 02:49:49.271 validation begins here
2013-09-06 02:49:49.273 stops here
2013-09-06 02:49:49.296 done button enabled
2013-09-06 02:49:51.257 validation begins here
2013-09-06 02:49:51.259 validation works just fine
2013-09-06 02:49:51.265 activity view works just fine
2013-09-06 02:49:51.270 user signedup just fine
2013-09-06 02:49:51.271 done button enabled
You are triggering the code to run by your observation of UITextFieldTextDidChangeNotification. As this moves through your methods you eventually call processFieldEntries. Probably you shouldn't be calling processFieldEntries from shouldEnableDoneButton.

How to add a textfield to an NSMutableArray

I'm trying to present what was entered into a textfield into a nsmutable array that will later be displayed.
I think that the problem is in the -(void)viewDidLoad method but I included all of the code just in case. The catch is that I will be leaving this page and then returning to it after another piece of information is selected. As this happens, I need to keep track of EACH thing that was entered into the textfield. Thanks for any help!
#import "EnteringCoursesViewController.h"
#import "SelectRotationController.h"
#implementation EnteringCoursesViewController
#synthesize classField;
#synthesize indicatedClass;
#synthesize labelClassTitle;
#synthesize selectRotationController;
#synthesize classesEnteredTable;
- (IBAction)chooseType {
UIActionSheet *typeSheet = [[UIActionSheet alloc]
initWithTitle:#"Class types"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:#"Core Class", #"Elective", nil];
[typeSheet showInView:self.view];
[typeSheet release];
}
- (void)actionSheet:(UIActionSheet *)typeSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
self.indicatedClass = classField.text;
NSString *indicatedString = indicatedClass;
NSString *greeting = [[NSString alloc]
initWithFormat:#"%# meets 6 times per rotation", indicatedString];
labelClassTitle.text = greeting;
labelClassTitle.hidden = NO;
[greeting release];
[indicatedClass release];
}
else if (buttonIndex == 1) {
self.indicatedClass = classField.text;
NSString *indicatedString = indicatedClass;
NSString *greeting = [[NSString alloc]
initWithFormat:#"%# meets 3 times per rotation", indicatedString];
labelClassTitle.text = greeting;
labelClassTitle.hidden = NO;
[greeting release];
[indicatedClass release];
}
}
- (IBAction)chooseFirstMeeting:(id)sender {
SelectRotationController *selectView = [[SelectRotationController alloc]
initWithNibName:#"SelectRotationController"
bundle:[NSBundle mainBundle]];
[selectView.navigationItem setTitle:#"First Period Day Choose"];
[self.navigationController pushViewController:self.selectRotationController animated:YES];
self.selectRotationController = selectView;
[selectView release];
}
- (IBAction)enteredClassText:(id)sender {
NSMutableArray *classesEntered = [[NSMutableArray alloc] init];
[classesEntered addObject:indicatedClass];
[classesEntered release];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
self.navigationItem.hidesBackButton = YES;
[super viewDidLoad];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[classField release];
[labelClassTitle release];
[indicatedClass release];
[selectRotationController release];
[classesEnteredTable release];
[super dealloc];
}
#end
If viewDidLoad is called "indicatedClass" is not yet initialised and therefore nil.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
Important Raises an NSInvalidArgumentException if anObject is nil.
If you want to save that by leaving the view, add the addObject-Call in the viewDidUnload-method. Definitely you should check if the value is nil ;)
I dont see any alloc for your variable indicatedClass but an release!? It might be that the variable doesnt exists if viewDidUnload is calling.
EDIT
You init an NSMutableArray, add the object to this array and after that you released that object. Therefore the Data is away. You must save your array therewith you can use the content later. Keyword: NSUserDefaults ;)
Check also of nil values:
- (IBAction)enteredClassText:(id)sender {
if (indicatedClass != nil) {
NSMutableArray *classesEntered = [[NSMutableArray alloc] init];
[classesEntered addObject:indicatedClass];
[classesEntered release];
}
}
If the sender is an UILabel you can also use this snippet:
- (IBAction)enteredClassText:(id)sender {
if (sender.text != nil) {
NSMutableArray *classesEntered = [NSMutableArray arrayWithObject:sender.text];
// TODO: Save your array to NSUserDefaults...
}
}

Resources