NSException with UIImagePickerController - ios

I'm building my first IOS 7 iPad app in Xcode 5 - but I need some help with this issue.
I'm following this tutorial:
I don't quite understand what the writer means with:
"So open up testPickerViewController.h and we want to add in the following to the class reference."
UINavigationControllerDelegate, UIImagePickerControllerDelegate>
I got my view controller.h file here:
#import "ViewController.h"
#interface DetailViewController : ViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIImagePickerController *imgPicker;
IBOutlet UIImageView *customImage;
}
#property(nonatomic, retain)UIImagePickerController *imgPicker;
#end
my view controller.m file:
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize imgPicker, customImage;
- (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.
// Init the image picker
self.imgPicker = [[UIImagePickerController alloc]init];
self.imgPicker.allowsEditing = YES;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)AddImage:(id)sender {
// Let the user add an image for the specific subject
[self presentModalViewController:self.imgPicker animated:YES];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editingInfo {
customImage.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
#end
I ran the app without doing what I wrote at the top, which resulted in an NSException in the main.m file.
What am I doing wrong here?
Edit
main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Edit
2014-05-17 14:56:47.509 myApp[1424:60b] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key image.'

Check the connection for the IBOutlet customImage in Interface Builder (IB) and make sure that the name of the referencing outlet and the UIImageView match. You can check by clicking on the Connection Inspector in IB (it's a little arrow inside of a circle).
In the tutorial that you posted a link to it shows the IBOutlet UIImageView declared as image. I'm assuming you changed the name of the IBOutlet and forgot to reconnect it. You can also check if the IBOutlet customImage is connected by checking if the dot beside the property declaration is filled or empty. Filled = connected and Empty = not connected.
Example of a property declaration for an IBOutlet:
#property (weak, nonatomic) IBOutlet UIImageView * customImage;
Also, <UINavigationControllerDelegate, UIImagePickerControllerDelegate> are protocols. By adding those lines to the #interface declaration you are, very simply, stating that, "I want my UIViewController to conform to the UINavigationControllerDelegate and the UIImagePickerControllerDelegate. I also want to implement my own code when certain events happen."

Related

Passing managedobject from uitableview to textfield to edit in core data model

I have a viewcontroller that has a uitableview being populated by my core data model. I am trying to set this up so I can tap on an item in the uitableview, have that item pass to a uitextfield on a second viewcontroller, where it can be edited and then saved back to my core data model.
prepare for segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"EditItemSegue"])
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
Item *item = [[self fetchedResultsController]objectAtIndexPath:indexPath];
[segue.destinationViewController setItemname:[item valueForKey:#"itemname"]];
}
}
error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[EditItem setItemname:]: unrecognized selector sent to instance
Im pretty sure the error indicates that i am trying to perform an action on an object that isnt allowed.
Some help . push in the right direction would be appreciated.
edititem.h
#import "ViewController.h"
#interface EditItem : ViewController
#property (strong, nonatomic) IBOutlet UITextField *editItemField;
#property (nonatomic, strong) NSString *toDoItemName;
#end
edititem.m
#import "EditItem.h"
#interface EditItem ()
#end
#implementation EditItem
#synthesize editItemField;
#synthesize toDoItemName;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
editItemField.text = toDoItemName;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
edit
This is what I tried in my viewWillLoad
- (void)viewWillAppear:(BOOL)animated
{
[editItemField setText:toDoItemName];
}
You're calling setItemname: when you should be calling setToDoItemName:.

Delegate method not being called, setting delegate to self?

So I'm trying to get a hang of using delegates, and I've watched a few tutorials on how to use them so far. I still find them confusing and after trying to implement one myself, have an issue that I can't seem to solve.
I have two ViewControllers, the first one ViewController contains a UITextField *sampleTextField and a button with the method switchViews. It also contains the protocol declaration with the method sendTextToViewController. SwitchViews is also linked to a segue that switches to the SecondViewController. In SecondViewController the only object is a UILabel *outputLabel When the user taps the button, it calls switchViews and the view changes to SecondViewController, and upon loading outputLabel should be changed to whatever text was entered in sampleTextField in ViewController. However the delegate method sendTextToViewController is never being called. All objects are created in Interface Builder.
Here is the code to make it a bit easier to understand:
ViewController.h
#import <UIKit/UIKit.h>
#protocol TextDelegate <NSObject>
-(void)sendTextToViewController:(NSString *)stringText;
#end
#interface ViewController : UIViewController
- (IBAction)switchViews:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *sampleTextField;
#property (weak, nonatomic) id<TextDelegate>delegate;
#end
Then declared this in ViewController.m
- (IBAction)switchViews:(id)sender {
NSLog(#"%#", self.sampleTextField.text);
[self.delegate sendTextToViewController:self.sampleTextField.text];
}
SecondViewController.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface SecondViewController : UIViewController <TextDelegate>
#property (weak, nonatomic) IBOutlet UILabel *outputLabel;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize outputLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
ViewController *vc = [[ViewController alloc]init];
[vc setDelegate:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)sendTextToViewController:(NSString *)stringText
{
NSLog(#"Sent text to vc");
[outputLabel setText:stringText];
}
I've looked at this and the first answer makes sense, but for some reason it's not working.
I do think that the problem is where I am setting calling [vc setDelegate:self], but not sure how to fix this. Some pointers in the right direction would be greatly appreciated. Keep in mind I'm new to obj-c so if you can explain what you are saying, that would be great. Thank you.
Your are creating a new instance of ViewController but you don't do anything with it.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
ViewController *vc = [[ViewController alloc]init];
[vc setDelegate:self];
}
The SecondViewController needs to have reference to the FirstViewController to be able to set itself as a delegate.
First you don't have to use delegation to do such a program.
A simpler way would be just creating a property in the SecondViewController that you'll pass the content of the textField into it.
Your code doesn't work because you called sendTextToViewController on a delegate that hasn't been set. You have set the delegate to a new instance of ViewController, not the one presented onscreen.

Passing data between ViewControllers is working, but not with Tab Bar Controller

Could anyone please help me in the following problem?
I new in Xcode, I'm still learning it, but I could figure out how to pass data between ViewControllers.
Here is my working code:
FirstViewController.h:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
- (IBAction)displayView:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *lblFirst;
#end
FirstViewController.m:
#import "FirstViewController.h"
#import "SecondViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize lblFirst;
SecondViewController *secondViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.forwarded_lblFirst = lblFirst;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)displayView:(id)sender {
[self.view addSubview:secondViewController.view];
}
#end
SecondViewController.h:
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
#property (nonatomic, retain) UILabel *forwarded_lblFirst;
#property (weak, nonatomic) IBOutlet UITextField *txtSecond;
- (IBAction)btnReturn:(id)sender;
- (IBAction)txtSecond_DidEndOnExit:(id)sender;
- (IBAction)btnSecond:(id)sender;
#end
SecondViewController.m:
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize forwarded_lblFirst;
#synthesize txtSecond;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnReturn:(id)sender {
[self.view removeFromSuperview];
}
- (IBAction)txtSecond_DidEndOnExit:(id)sender {
forwarded_lblFirst.text = txtSecond.text;
[txtSecond resignFirstResponder];
[self.view removeFromSuperview];
}
- (IBAction)btnSecond:(id)sender {
forwarded_lblFirst.text = txtSecond.text;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[txtSecond resignFirstResponder];
}
#end
This code is working perfectly, the text what I enter on the SecondViewController's textbox (after pressing the btnSecond or simply the Return key on the keyboard) appears as the text of the Label on the FirstViewController.
My problem is, that when I do the exact same thing, but with a Tab Bar Application, the Label on the First tab won't change.
I can use the exact same code (except the changing-views part, because I handle on the first app with programmed buttons, but for the Tab-Bar-App there are already the buttons), there are also two ViewControllers for the Tab Bar App, too (one for each tabs).
So the code is the same, line by line, character by character, and the files are the same, too, for both apps (View-Based, Tab-Bar).
Why isn't my code working? How can I solve this problem?
Thank you!
You need to read some articles about transferring data between views:
Passing Data between View Controllers
Storyboard
passing data between views
iPhoneDevSDK
Talking about your problem, try this approach:
Add the property to your Application Delegate.
When assigning the property do something like:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.myProperty = #"My Value";
then, in your different tabs, you can retrieve this property in the same manner:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *valueInTab = delegate.myProperty;
A different approach to this problem is to use an independent data model.
Create an object that provides access and manipulation methods for all the data that your application needs to save, load, share, or use in any non-trivial way. Make the object available either as a Singleton or as a property of the application delegate. When changes happen, have the data model update application state. When something needs to be displayed, have the controller fetch it from the data model and send it to the view (MVC!).
If you don't store things in controllers that actually belong in the model, you never need to worry about passing information from controller to controller.
You need to use tabbardelegate in your secondview controller, assuming that you use this schema
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#property (strong, nonatomic) NSString *content;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tabBarController.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if ([viewController isKindOfClass:[FirstViewController class]]){
FirstViewController *vc =( FirstViewController *) viewController;
vc.content = #"your content";
}
return TRUE;
}

this class is not key value coding-compliant for the key image view

Debugger is showing this information:
2013-07-16 15:23:15.731 app2[2501:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x71a4140> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key imageview.'
My app currently consist of two view controllers.
'ViewController' has just a button to start the app and pressing the button launches the new view.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)startBtn:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (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)startBtn:(id)sender {
UIViewController *flipViewController = [[UIViewController alloc] initWithNibName:#"AppViewController" bundle:[NSBundle mainBundle]];
[self presentViewController:flipViewController animated:YES completion:NULL];
}
#end
My second view controller 'AppViewController' has a UIImageView and a UIButton. It's code is:
AppViewController.h
#import <UIKit/UIKit.h>
#interface AppViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *imageview;
#end
and
AppViewController.m
#import "AppViewController.h"
#interface AppViewController ()
#end
#implementation AppViewController
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The problem I am facing is that the moment I connect the property between the 'xib' file and 'h' file by Ctrl-dragging the image view into the 'h' file, my app crashes in the simulator and gives me the error.
I reckon this might be too simple of an error for many of you, however, I am unable to rectify it. I have read numerous posts on this forum and have tried most, including the #synthesize fix and the like.
Your flipViewController should be a AppViewController.
The issue is that AppViewController is a subclass of UIViewController so you are allowed to instantiate it as a UIViewController, but you lose access to all the additional properties that your AppViewController adds on top of UIViewController's.
Your button handler should look like:
- (IBAction)startBtn:(id)sender {
AppViewController *flipViewController = [[AppViewController alloc] initWithNibName:#"AppViewController" bundle:[NSBundle mainBundle]];
[self presentViewController:flipViewController animated:YES completion:NULL];
}

Unable to display popover in iOS from UITextField

I am working on a very basic app that displays a popover when the user is entering text into a UITextField. Unfortunately, the popover is not showing up and the default keyboard is appearing (which shouldn't). Here is my relevant code below:
NumberPadViewController.h
#import <UIKit/UIKit.h>
#import "NumberViewController.h"
#interface NumberPadViewController : UIViewController <UITextFieldDelegate> {
IBOutlet UITextField *numTest;
}
#property (nonatomic, strong) NumberViewController *numberPicker;
#property (nonatomic, strong) UIPopoverController *numberPickerPopover;
#end
NumberPadViewController.m
- (BOOL)textFieldShouldBeginEditing:(UITextField *) textField
{
// Create popover controller if nil
if(_numberPickerPopover == nil){ //make sure popover isn't displayed more than once in the view
_numberPickerPopover = [[UIPopoverController alloc]initWithContentViewController:_numberPicker];
}
[_numberPickerPopover presentPopoverFromRect:numTest.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
return NO;
}
My popover class is called NumberViewController.h
#interface NumberViewController : UIViewController {
}
#property (strong, nonatomic) IBOutlet UIButton *oneButton;
NumberViewController.m
#import "NumberViewController.h"
#interface NumberViewController ()
#end
#implementation NumberViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
NSInteger buttonHeight = _oneButton.frame.size.height * 4;
NSInteger buttonWidth = _oneButton.frame.size.width * 3;
self.contentSizeForViewInPopover = CGSizeMake(buttonWidth, buttonHeight);
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I have created the UITextField in Storyboard, and set the delegate there. Can anyone see what I am doing wrong?
Thanks in advance to all who reply.
Ensure the textFieldShouldBeginEditing delegate method is being called. The rest of the code looks correct.
This is just a thought, but when a popover does a popover thing i think it becomes first responder, but your text view is first responder... so it might not be able to over do it.... if this is the error then before you tell the popover to appear you can say [textView resignFirstResponder]; and see if that helps.... it's just a thought though not 100% sure i will have to do some testing ~
also check to see if _numberPicker is not nil aswell i don't know what happens if you try to display a popover with no controller but you can see if that's the problem
Seeing as your popover isn't represented in the storyboard (if I read your post right) I think you need to add the popover view as a subview in code. Something like:
[self addSubview:_numberPickerPopover];
There are potentially a few places to do this. Probably makes the most sense in your textFieldShouldBeginEditing: method, after you've inited it.

Resources