So I am creating an app in the form of a social media app. I am using the tutorial found here as a springboard since I am still trying to wrap my brain around Core Data. I've deviated from the tutorial by adding a sign up button that takes the user to a new View Controller and created a .h and a .m file and set the New Member screen to reference the .h and .m files. They are set up as follows for the .h:
#import <UIKit/UIKit.h>
#interface NewMemberViewController : UIViewController
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (strong, nonatomic) IBOutlet UITextField *nameTF;
#property (strong, nonatomic) IBOutlet UITextField *ageTF;
#property (strong, nonatomic) IBOutlet UITextField *usernameTF;
#property (strong, nonatomic) IBOutlet UITextField *passwordTF;
- (IBAction)alreadyMember:(id)sender;
- (IBAction)checkAndLogin:(id)sender;
#end
and for the .m:
#import "NewMemberViewController.h"
#import "CoreDataHelper.h"
#interface NewMemberViewController ()
#end
#implementation NewMemberViewController
#synthesize usernameTF, ageTF, passwordTF, nameTF, managedObjectContext;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//If the user is already a member simply dismiss the VC
- (IBAction)alreadyMember:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
//When done editing keyboard
- (IBAction)checkAndLogin:(id)sender {
managedObjectContext =self.managedObjectContext;
//Textfield Reference
UITextField *tf = (UITextField *)sender;
//Check tag numbers If its equal to 1 or 2(nameTF or ageTF) then
if (tf.tag==1||tf.tag==2)
{
[sender resignFirstResponder];
NSLog(#"This is working");
}
//If its equal to 3 then this means the username text field is active
else if (tf.tag == 3)
{
[sender resignFirstResponder];
//do a quick search to see if username is availible
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(username == %#)", [usernameTF text]];
//Run the query to check if user exists
if([CoreDataHelper countForEntity:#"Users" withPredicate:pred andContext:managedObjectContext] > 0)
{
//we found a user
NSLog(#"oh no...");
}
}
}
#end
With that being said if I run my app and go to the signup screen and test to see if the user exists, by typing in admin because it already exists, i get the following error in Xcode:
Canvases[779:11603] * WebKit discarded an uncaught exception in the webView:shouldInsertText:replacingDOMRange:givenAction: delegate: +entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Users'
What does this mean and why is it being caused?
Have you pass the context to the view controller? Try with:
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication]delegate];
yourVontext = [appDelegate managedObjectContext];
before fetch.
There is issue with below line.
managedObjectContext = self.managedObjectContext;
self.managedObjectContext is returning nil to managedObjectContext. Instead of self.managedObjectContext you should create Core Data Stack (method implementation)in the Application Delegate and then pass object reference of ManagedObjectContext from AppDelegate to your caller class.
Related
Hey I converted my project to ARC automatically and the only thing I had to fix was that Xcode changed array that had a size of [8] to [4] (still don't know what was going on there)
However, I now realized I got another problem: every time I hit a button in my Popup, the app crashed if it is linked to an IBAction. If I remove the reference to the header and main file, the button is clickable, but as soon as i assign it to a method (even if the method is empty), the whole app jut freezes/crashes.
This is how I initiate my popup:
PopUpViewController *popViewController =
[[PopUpViewController alloc] initWithNibName:#"PopUpViewController" bundle:nil];
[popViewController setTitle:#"This is a popup view"];
[popViewController showInView:self.view
animated:YES];
popViewController.view.center=self.view.center;
Pretty basic stuff, I ripped it off a tutorial I found online. My header is this:
#interface PopUpViewController : UIViewController
- (IBAction)baa:(id)sender;
#property (strong, nonatomic) UIButton *ba; // I was trying to add those buttons as properties here
#property (strong, nonatomic) IBOutlet UIButton *kl; //but no luck whatsoever
#property (strong, nonatomic) IBOutlet UIView *popUpView;
#property (strong, nonatomic) IBOutlet UIView *ppp;
- (IBAction)openSomething:(id)sender;
- (IBAction)openYoutube:(id)sender;
- (IBAction)openFacebook:(id)sender;
- (void)showInView:(UIView *)aView animated:(BOOL)animated;
#end
And my main
#import "PopUpViewController.h"
#interface PopUpViewController ()
#end
#implementation PopUpViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)showAnimate
{
// not important for this question
}
- (void)removeAnimate
{
// shortened
}
- (IBAction)baa:(id)sender{
// NSLog(#"asd"); I commented it out, but even an empty method kills the app
// only if I leave a button unassigned to any method, the app "survives" a button click
}
- (IBAction)openSomething:(id)sender
{
// [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.test.de"]];
}
- (IBAction)openYoutube:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.youtube.com/"]];
}
- (IBAction)openFacebook:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.facebook.com/"]];
}
- (void) doSomething{
// also tried an empty method with a "new" name over here to eliminate any caching errors, no luck
}
- (IBAction)closePopup:(id)sender {
[self removeAnimate];
}
- (void)showInView:(UIView *)aView animated:(BOOL)animated
{
[aView addSubview:self.view];
if (animated) {
[self showAnimate];
}
}
- (void)viewDidLoad
{
self.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:.0];
self.popUpView.layer.cornerRadius = 5;
self.popUpView.layer.shadowOpacity = 1.0;
self.popUpView.layer.shadowOffset = CGSizeMake(0.2f, 0.2f);
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
Any ideas what I could do different? I referenced everything to everything else possible now and I don't even know how it looked before anymore, but I somehow think it has something to do with the referencing.
Thanks a lot in advance, Alex
I was able to figure out on my own:
In the header of my main ViewController I added
#property (strong, nonatomic) PopUpViewController *popViewController;
Which still fired the crash. But then I adjusted the popup "opening" block to
_popViewController =
[[PopUpViewController alloc] initWithNibName:#"PopUpViewController" bundle:nil];
[_popViewController setTitle:#"This is a popup view"];
[_popViewController showInView:self.view
animated:YES];
_popViewController.view.center=self.view.center;
(added the underscores) and now it's working perfectly again.
Actually I am curious why it worked before but I am not going to investigate this any further.
I'm developing an iOS application and I have a strange problem.
The application sends local notifications to the user and when he taps on it, my app programmatically chooses a ViewController, sets its labels and images and then displays it to the user. But it simply doesn't work! Labels and images are not set. Here's my code in AppDelegate.m
- (void) manageLocalNotification:(UILocalNotification *) notification {
[[UIApplication sharedApplication] cancelLocalNotification:notification];
if ([self.theme intValue] == 1) {
ADATheme1ViewController *notifyViewController = [[ADATheme1ViewController alloc] init];
[notifyViewController.titleLabel setText:self.title];
[notifyViewController.bodyLabel setText:self.text];
[notifyViewController.bgImage setImage: [self getImageFromURL:self.background]];
self.window.rootViewController = notifyViewController;
} else {
ADATheme2ViewController *notifyViewController = [[ADATheme2ViewController alloc] init];
[notifyViewController.titleLabel setText:self.title];
[notifyViewController.bodyLabel setText:self.text];
[notifyViewController.offerLabel setText:self.offer];
[notifyViewController.bgImage setImage: [self getImageFromURL:self.background]];
self.window.rootViewController = notifyViewController;
}
}
I made some debugging and my properties (text, title, offer and so on) are properly set. The method getImageFromUrl: returns an UIImage* and it works.
My ViewControllers are very simple, here's the code (but nothing special)
.h file
#import
#interface ADATheme1ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *bgImage;
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
#property (strong, nonatomic) IBOutlet UILabel *bodyLabel;
#end
.m file
#import "ADATheme1ViewController.h"
#interface ADATheme1ViewController ()
#end
#implementation ADATheme1ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
#end
and there's a .xib file attached.
Can you help me?
Solved: the view weren't loaded so the properties were set to nil.
I added just a line of code to "force" the loading of my view before setting labels:
[notifyViewController view];
I'm having problems passing data between two view controllers.
I've seen two ways to do this.
One involves implementing prepareForSeque: in the segue's source view controller and another involves setting properties in the viewDidLoad: method of the segue's destination view controller.
e.g.-
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toEmailReservationViewController"]) {
FLSendEmailViewController *controller = (FLSendEmailViewController *)segue.destinationViewController;
if (!controller.startDateField.text) {
controller.startDateField.text = #"today";
}
}
}
and
- (void)viewDidLoad
{
[super viewDidLoad];
self.startDateField.text = ((FLViewController *)self.presentingViewController).startDate;
}
I've got these to work on simple apps using two UIViewController. However, I can't get them to work on an app that has a UITabViewController connected to some UINavigationViewController connected to custom subclasses of UIViewController. When I click the button to perform the push seque, I get to the view I want, but the startDateField.text doesn't have the text from the segue's source view controller.
Why are these methods of sharing data not working with the tab controller and navigation controller setup?
I noticed that in prepareForSegue: I can't set controller.startDateField.text; as shown when I try to set it and use NSLog to display it. Could this be the problem? Is it possible that the property controller.startDateField.text doesn't exist yet?
I'm trying to grab the date from a datePicker in an instance of FLViewController, store this date in the property NSString *startDate, and in an instance of FLSendEmailViewController set NSString *startDateField.text to the `NSString *startDate'.
Here are the UIViewController subclasses I created:
FLViewController.h
#import <UIKit/UIKit.h>
#import "FLSendEmailViewController.h"
// import frameworks to use ad
#import AddressBook;
#import AddressBookUI;
#interface FLViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *theScroller;
#property (weak, nonatomic) NSString *startDate;
#property (weak, nonatomic) NSString *stopDate;
- (IBAction)exitToReservations:(UIStoryboardSegue *)sender;
#end
FLViewController.m
#import "FLViewController.h"
#interface FLViewController ()
#property (weak, nonatomic) IBOutlet UIDatePicker *startReservationDatePicker;
#property (weak, nonatomic) IBOutlet UIDatePicker *stopReservationDatePicker;
#end
#implementation FLViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.theScroller setScrollEnabled:YES];
[self.theScroller setContentSize:CGSizeMake(280, 1000)];
//setup reservationDatePicker
[self.startReservationDatePicker addTarget:self
action:#selector(startDatePickerChanged:)
forControlEvents:UIControlEventValueChanged];
[self.stopReservationDatePicker addTarget:self
action:#selector(stopDatePickerChanged:)
forControlEvents:UIControlEventValueChanged];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// add method called when user changes start date
- (void)startDatePickerChanged:(UIDatePicker *)datePicker
{
NSDateFormatter *dateFortmatter = [[NSDateFormatter alloc] init];
[dateFortmatter setDateFormat:#"dd--MM-yyyy HH:mm"];
// get date using stringFromData: method and getter datePicker.date
self.startDate = [dateFortmatter stringFromDate:datePicker.date];
NSLog(#"The start date is %#", self.startDate);
}
// add method called when user changes stop date
- (void)stopDatePickerChanged:(UIDatePicker *)datePicker
{
NSDateFormatter *dateFortmatter = [[NSDateFormatter alloc] init];
[dateFortmatter setDateFormat:#"dd--MM-yyyy HH:mm"];
// get date using stringFromData: method and getter datePicker.date
self.stopDate= [dateFortmatter stringFromDate:datePicker.date];
NSLog(#"The stop date is %#", self.stopDate);
}
- (IBAction)exitToReservations:(UIStoryboardSegue *)sender {
// execute this code upon unwinding
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toEmailReservationViewController"]) {
FLSendEmailViewController *controller = (FLSendEmailViewController *)segue.destinationViewController;
if (!controller.startDateField.text) {
controller.startDateField.text = #"today";
NSLog(#"in vc startDate is null but set to %#",controller.startDateField.text );
}
}
}
#end
FLSendEmailViewController.h
#import <UIKit/UIKit.h>
#class FLViewController;
#interface FLSendEmailViewController : UIViewController
#property (retain, nonatomic) IBOutlet UITextField *startDateField;
#property (retain, nonatomic) IBOutlet UITextField *stopDateField;
#end
FLSendEmailViewController.m
#import "FLSendEmailViewController.h"
#import "FLViewController.h"
#interface FLSendEmailViewController ()
- (IBAction)sendEmail:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *numberOfDoggies;
#property (weak, nonatomic) IBOutlet UITextField *emailAddressField;
- (IBAction)hideKeyboard:(id)sender;
#end
#implementation FLSendEmailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.startDateField.text = ((FLViewController *)self.presentingViewController).startDate;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)sendEmail:(id)sender {
NSString *emailString = [NSString stringWithFormat:#"I would like you to watch my %# doggies from %# to %#. Thank you.", self.numberOfDoggies.text, self.startDateField.text, self.stopDateField.text];
NSLog(#"%#",emailString);
}
- (IBAction)hideKeyboard:(id)sender {
[self.startDateField resignFirstResponder];
}
#end
Import the FLSendEmailViewController.h to the "InitialViewController.h"
Add this property to the FLSendEmailViewController.h
#property (nonatomic, strong) NSString *exportedData;
Add this to the FLSendEmailViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.startDateField.text = self.exportedData
}
4.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toEmailReservationViewController"]) {
FLSendEmailViewController *controller = (FLSendEmailViewController *)segue.destinationViewController;
if (!controller.startDateField.text) {
controller.exportedData = #"today";
}
}
}
This "sharing method" works in any case when from a controller go to another controller.
So, in case of a navigation controller, if you want push another viewController passing the data, you have just to set the trigger in the Storyboard (if you are using storyboard) from the button, and the new viewController.
So, you will not met troubles. Otherwise, you are committing other type of errors, and in this case, update your question.
I have a big noob problem. I new in iOS and I'm trying to do this:
I have two ViewControllers. The first one has an button that if it is pushed, control goes to a second view controller.
That works but the problem is when I try to get data in my second view controller. The UITextfield doesn't work.
I'm trying to display which I insert into textfield in the label. But THE TEXTFIELD DOESN'T WORK :(
I putted the IBOutlets succesfully in the xibs and connect the buttons with their IBActions...
This is my code:
ViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#class SecondViewController;
#interface ViewController : UIViewController
#property (strong, nonatomic) SecondViewController *secondViewController;
-(IBAction)buttonClicked:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize secondViewController;
-(IBAction)buttonClicked:(id)sender {
self.secondViewController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
[self presentViewController:self.secondViewController animated:YES completion:nil];
}
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController {
IBOutlet UITextField *textField;
UIButton *obtener;
IBOutlet UILabel *label;
}
#property (nonatomic, retain) IBOutlet UITextField *textField;
#property (nonatomic, retain) IBOutlet UIButton *obtener;
#property (nonatomic, retain) IBOutlet UILabel *label;
-(IBAction)obtenerClicked:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
#synthesize obtener, textField, label;
-(IBAction)obtenerClicked:(id)sender {
label.text = textField.text;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
In your SecondViewController.h, add this property:
#property(nonatomic, readwrite) NSString* myString;
now in firstViewController's onClick method, add this line
-(IBAction)buttonClicked:(id)sender {
//....... Previous code....
self.secondViewController.myString= #"String to be sent";
}
This will pass the string for you..
if you want to pass the string in text field, use this:
-(IBAction)buttonClicked:(id)sender {
//....... Previous code....
self.secondViewController.textField.text= #"String to be sent";
}
hope it will work fine for your requirement.
UPDATE:
Do the following to get expected results:
1. make your secondViewController a textView delegate.
in your secondViewController.h
replace #interface SecondViewController : UIViewController with #interface SecondViewController : UIViewController<UITextFieldDelegate>
put a button in your secondViewController & create an IBAction for it.
on Click event of button, write this:
self.label.text= self.textfield.text;
tell me if it does not work.
I'm trying to separate the UITextViewDelegate methods from the main class of my project, I created a class to manage the delegate methods, but I can not change the values of the IBOulets from the main class.
I made a test project with a ViewController and a TextFieldController, in the Storyboard I add a text field and a label. What I want to do is change the text of the label when I start to write in the text field. Here is the code:
ViewController.h:
#import <UIKit/UIKit.h>
#import "TextFieldController.h"
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UILabel *charactersLabel;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
TextFieldController.h:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : UIViewController <UITextFieldDelegate>
#end
Text Field Controller.m:
#import "TextFieldController.h"
#interface TextFieldController ()
#property ViewController *viewController;
#end
#implementation TextFieldController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
_viewController.charactersLabel.text = #"hello";
return YES;
}
#end
When I start writing in the text field the message "Hello" is printed in the log, but the text of the label does not change. I want to know how to change the label text value from the other class.
First change the TextFieldController.h like this:
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface TextFieldController : NSObject <UITextFieldDelegate>
{
}
#property (nonatomic, assign) ViewController *viewController;
#end
Then change your TextFieldController.m file like this:
#import "TextFieldController.h"
#interface TextFieldController ()
#end
#implementation TextFieldController
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"hello");
self.viewController.charactersLabel.text = #"hello";
return YES;
}
#end
In the ViewController.m do like that:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) TextFieldController *textFieldController;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_textFieldController = [[TextFieldController alloc] init];
_textFieldController.viewController = self;
_textField.delegate = _textFieldController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
This will work but I personally dont like that way you took.
Good luck :)
It's failing because _viewController is nil. You need to assign the viewController property in your delegate in order to support the two way communication.
Also, I'd strongly recommend you make your delegate object a subclass of NSObject, and not UIViewController. It does nothing with controlling views. You can just manually instantiate it in your ViewController objects viewDidLoad.
In TextViewController I don't see where the viewController property (_viewController ivar) is being set so it is probably nil. You should set it when you create the TextViewController instance.
When you are navigating to other controllers using storyboad's segue then you need to implement prepareForSegue method to initialised its properties as follows
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"segue for textFieldController"])
{
TextFieldController *_textFieldController = [segue destinationViewController];
_textField.delegate = _textFieldController;
}
}
But I was wondering, why are you setting textFieldDelegate here, why can't you set in TextFieldController's viewDidLoad method as then you didn't you to implement above prepareForSegue method call?
Besides you are keeping strong reference of each other and you are creating strong retain cycle.
One more thing, following code
_textField.delegate = _textFieldController;
will not work, until textFieldController is loaded and its viewDidLoad method is being called as you are only initialising it but its outlets will not be connected until view is loaded into navigation stack.