Terminating app due to uncaught exception 'NSInvalidArgumentException' - iphone

I am not getting an error now but my delegate is not working. I am making a custom keyboard so i have the UIViewController and a UIView. I want the UIView to call the sendKeyboardShortCut method in the UIViewController. The sendKeyboardShortCut method is not being called. Thank You
//ViewController .h
#import "KeyboardExtension.h"
#interface PageViewController : UIViewController <UITextViewDelegate,sendKeyboardShortCutDelegate> {
KeyboardExtension *inputAccView;
}
-(void)sendKeyboardShortCut:(NSString*)shortCut;
#property (nonatomic, assign) IBOutlet UITextView *tv;
#end
//ViewController .m
#implementation PageViewController
#synthesize tv;
- (void)viewWillAppear:(BOOL)animated
{
tv.delegate = self;
}
-(void)createInputAccessoryView{
inputAccView = [[[KeyboardExtension alloc] init]autorelease];
inputAccView.delegate = self;
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"KeyboardExtension" owner:self options:nil];
inputAccView = [nibObjects objectAtIndex:0];
}
-(void)textViewDidBeginEditing:(UITextView *)textView{
[self createInputAccessoryView];
[textView setInputAccessoryView:inputAccView];
}
-(void)sendKeyboardShortCut:(NSString*)shortCut{
if ([shortCut isEqualToString:#"dash"] ) {
NSRange range = tv.selectedRange;
if((range.location+range.length)<=tv.text.length)
{
NSString * before = [tv.text substringToIndex:range.location];
NSString * after = [tv.text substringFromIndex:range.location+range.length];
tv.text = [NSString stringWithFormat:#"%#-%#",before,after];
}
}
}
#end
//keyboard view .h
#import <UIKit/UIKit.h>
#protocol sendKeyboardShortCutDelegate <NSObject>
-(void)sendKeyboardShortCut:(NSString*)shortCut;
#end
#interface KeyboardExtension : UIView
-(IBAction)dash:(id)sender;
#property(nonatomic,assign) id<sendKeyboardShortCutDelegate>delegate;
#end
//keyboard view .m
#import "KeyboardExtension.h"
#implementation KeyboardExtension
#synthesize delegate;
-(IBAction)dash:(id)sender{[delegate sendKeyboardShortCut:#"dash"];}
#end

I suspect that:
1) your button's target is the nib's file owner and not KeyboardExtension
2) your action is setup not to send the sender, so UIKit calls -comma instead of -comma:
Also, the following code is highly suspect:
inputAccView = [[[KeyboardExtension alloc] init]autorelease];
inputAccView.delegate = self;
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"KeyboardExtension" owner:self options:nil];
inputAccView = [nibObjects objectAtIndex:0];
A) you allocate an object that you barely use as you replace it immediately with the nib's object
B) the way to extract the object from the nib ([nibObjects objectAtIndex:0]) is really not robust. You should create an IBOutlet in PageViewController and link it in the nib
I think you should revisit the way you use nibs here.
A final (unrelated) point: why are you using [NSString stringWithFormat:#"..."] instead of just #"..."?

Related

Change UIView (inside nib) background from other viewcontroller

Anyone know how to alter a view inside a nib from another viewcontroller? I have a outlet from the view in nib-file to the view class-file and I have #synthesize the view-class .m file. And then I #import "InfoView.h" (which is the view class) the view to the viewcontroller and at last I:
InfoView *infoView;
if (infoView == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"infoView" owner:self options:nil];
infoView = [nib objectAtIndex:0];
}
infoView.contentView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];"
But I can't get the background to change.
Has anyone tried to do something like this before?
I appreciate any input thank you!
EDIT:
Have addressed the UIColor issue but that was not the problem.
Try this code I have made the demo app for you.
create file CustomView.h
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#property (nonatomic, strong) IBOutlet UILabel *titleLbl;
#end
CustomView.m. If you are using XIB
#import "CustomView.h"
#implementation CustomView
#synthesize titleLbl = _titleLbl;
- (id)initWithCoder:(NSCoder *)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomView" owner:self options:nil];
UIView *theEditView = [nibObjects objectAtIndex:0];
theEditView.frame = self.bounds;
[self addSubview: theEditView];
theEditView = nil;
}
return self;
}
Set fileOwner of CustomView.XIB is CustomView. and connect outlets.
Where ever you want to use CustomView take a UIView object in your XIB, and rename UIView class with CustomView. Create an IBOutlet in your .h file and connect it with CustomView object in XIB.
Now do this:
self.customViewObj.backgroundColor = [UIColor redColor];
self.customViewObj.titleLbl.text = #"Prateek";
In your case your customview object is not created. if you print your object it will show you nil.
You're using the -colorWithRed:green:blue:alpha wrongly. They expect a float value between 0 and 1. You need to do:
infoView.contentView.backgroundColor = [UIColor colorWithRed:50.0/255.0 green:50.0/255.0 blue:50.0/255.0 alpha:1];"
If you are trying to change the background color.. then do this:
infoView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];

I cannot save retrieve NSurl from another class?

I have a function that returns a NSUrl, and i want to use it in another class. But when i tried to retrieve it in my other class, it gives me null.
This is my First Class
#interface UOEventDetailController : UIViewController {
NSURL *imgData;
}
#property(nonatomic, retain)NSURL *imgData;
-(NSURL *)imgData;
#implementation UOEventDetailController
#synthesize imgData;
The .m File
-(NSURL *)imgData{
UOEventPost *post = (UOEventPost *)self.event;
NSURL *url = [NSURL URLWithString:post.postImageURL];
return url;
}
I want to retrieve the URL in this class
#class UOEventDetailController;
#interface UOEnlargeImageViewController : UIViewController {
IBOutlet UIImageView *enlargedImage;
}
#property (nonatomic, retain) UOEventDetailController *controller;
#property (nonatomic, retain) IBOutlet UIImageView *enlargedImage;
the .m file
#implementation UOEnlargeImageViewController
#synthesize controller;
#synthesize enlargedImage;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Enlarged Image";
controller = [[UOEventDetailController alloc]init];
NSURL *url = [controller imgData];
NSLog(#"%#",url);
}
#end
I can retrieve objects other than post.postImageUrl.
For Example
instead of post.postImageUrl, i put in string like #"omg", #"god"
it gets retrieved in my other class...
EDIT
-(IBAction)enlargeImg{
UOEventPost *post = (UOEventPost *)self.event;
UOEnlargeImageViewController *enlarge = [[UOEnlargeImageViewController alloc]initWithNibName:nil bundle:nil];
enlarge.temp = post.postImageURL;
[self.navigationController pushViewController:enlarge animated:YES];
[suggestPopupView removeFromSuperview];
[enlarge release];
}
this is because you are making a new object. and that of new object, relevent attributes are empty and hence url is also null.
The Object will be null as a new object is being created and it's not in same state as you want it , you must use protocol & delegate to pass the object to another class if flow is backward else ensure that you work on the same object.

Passing Values Between Master and Detail in UISplitViewController Using Storyboards

I have defined the protocol in Customer.h file which is shown below:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#end
The MasterViewController (left side) invokes the didSelectCustomer method as shown below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Customer *selectedCustomer = [customers objectAtIndex:[indexPath row]];
[self.delegate didSelectCustomer:selectedCustomer];
}
Now, I need to tell the DetailViewController (right side) to do something. The DetailViewController complies with the CustomerDelegate protocol.
#interface DetailViewController : UIViewController<UISplitViewControllerDelegate,CustomerDelegate>
{
}
-(void) didSelectCustomer:(Customer *)customer
{
NSLog(#"sssdasdasdasd");
}
The didSelectCustomer method is never invoked. I think I need to set the masterViewController.delegate = self but I am not sure where to set this thing up.
UPDATE 1:
I added the instance of MasterViewController inside the DetailViewController but it did not work:
- (void)viewDidLoad
{
[super viewDidLoad];
MasterViewController *master = [[MasterViewController alloc] init];
master.delegate = self;
}
SOLUTION:
In AppDelegate:
else
{
UISplitViewController *splitViewController = (UISplitViewController *) self.window.rootViewController;
splitViewController.delegate = [splitViewController.viewControllers lastObject];
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
// splitViewController.delegate = (id)navigationController.topViewController;
DetailViewController *detail =(DetailViewController *) [splitViewController.viewControllers lastObject];
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
MasterViewController *master = (MasterViewController *)masterNavigationController.topViewController;
master.delegate = detail;
}
You never explicitly declare yourself as the delegate to the Consumer class. Merely conforming to it won't cut it. Declare it in -viewDidLoad by creating an instance of Consumer, possibly like this:
-(void)viewDidLoad {
Consumer *consumer = [[Consumer alloc]init];
[consumer setDelegate:self];
}
You also don't declare a property for your delegate object in Consumer, so it can never actually be accessed. Do this first:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#property (weak) id <CustomerDelegate> delegate; //use assign or __unsafe_unretained if targeting <5.0.
#end
You can check if your class conforms to your protocol like so:
if (![delegate conformsToProtocol:#protocol(CustomerDelegate)]) {
[NSException raise:#"Delegate Exception"
format:#"Parameter does not conform to CustomerDelegate protocol at line %d", (int)__LINE__];
}
the split view controller's last object.
this object is return a UI navigation controller.
you know, then you can do yourself.

iPhone - SubClassing UIToolbar the right way?

I created a new Class named
CustomToolbar
Then i created an empty nib, added a
toolbar to it, and set the toolbar
class to "CustomToolbar".
What is the proper way of initializing CustomToolbar In code so that my class uses the nib file?
I already have written the code to do that but i know it's not the correct way and it has a leak.
#interface CustomToolbar : UIToolbar {
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem *button;
#end
#implementation CustomToolbar
- (id)initWithDelegate
{
NSArray *objects = [[NSBundle mainBundle]
loadNibNamed:#"CustomToolbar"
owner:nil
options:nil];
if (self = (CustomToolbar*) [objects objectAtIndex:0])
{
//do some work here
}
return self;
}
#end
The NIB will call initWithCoder: on your custom class, like this:
- (id)initWithCoder:(NSDecoder*)aDecoder {
self = [super initWithCoder:aDecoder];
if( self ) {
// Do something
}
return self;
}
If you really want to load it the way you do now, you need to retain the object returned from loadNibNamed.

iOS using External Object in Nib

I am writing an application that needs to interfaces with different backend systems. I decided to use a Protocol in order to abstract my backend Classes. I created a nib called LoginViewController that contains an "External Object" reference of type "NSObject", and wired it to the systemDelegate outlet in my LoginViewController.
#interface LoginViewController : UIViewController {
}
#property (nonatomic, retain) IBOutlet UITextField *usernameTextView;
#property (nonatomic, retain) IBOutlet UIImageView *captchaImageView;
#property (nonatomic, retain) IBOutlet UITextField *captchaTextView;
#property (nonatomic, retain) IBOutlet NSObject <BackEndSystemDelegate> *systemDelegate;
- (IBAction) submitCaptcha:(id) sender;
- (IBAction)dismissKeyboard: (id)sender;
- (IBAction) animateViewUp: (id) sender;
- (IBAction) animateViewDown: (id) sender;
- (void) animateViewOnYAxis: (int) offset;
- (void) loadCaptchaImage;
#end
I instanciate the LoginViewController in my application delegate, then try to load the nib with the external object reference. My code calls the loadNibNamed and crashes without a stack trace. I do not reach the NSLog statements after the invocation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSObject <BackEndSystemDelegate> *systemDelegate = [[ACMEBackEndSystemDelegate alloc] init];
// Init LoginView, and load nib with systemDelegate
self.viewController = [[LoginViewController alloc] init];
NSDictionary *proxies = [NSDictionary dictionaryWithObject:systemDelegate forKey:#"systemDelegate"];
NSDictionary *options = [NSDictionary dictionaryWithObject:proxies forKey:UINibExternalObjects];
NSArray *toplevelobjects = [[NSBundle mainBundle] loadNibNamed:#"LoginViewController"
owner:self.viewController
options:options];
if (toplevelobjects) {
NSLog(#"toplevelobjects is nil");
} else {
NSLog(#"toplevelobjects count %d", [toplevelobjects count]);
}
NSLog(#"Controller: %#, View: %#", viewController, viewController.view);
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
I am at a loss trying to figure this out. Any help would be appreciated.
Thanks,
J Garcia
A few comments:
Generally you refer to a delegate object using the pattern id<SomeProtocolName> and not NSObject<SomeProtocolName>
You alloc your systemDelegate variable but never release it. This is a memory leak.
If the ACMEBackEndSystemDelegate class implements the BackEndSystemDelegate protocol, it is sufficient to allocate it like ACMEBackEndSystemDelegate* systemDelegate = [[ACMEBackEndSystemDelegate alloc] init];
Now, as for your crash, you said there's a crash on this line:
NSArray *toplevelobjects = [[NSBundle mainBundle] loadNibNamed:#"LoginViewController"
owner:self.viewController
options:options];
I assume you have a .xib called LoginViewController.xib. Open it up. That is the class type set for "File's Owner"? Is it LoginViewController? If not, set it. Now check the view outlet property. Is it set to a UIView in the .xib (perhaps a top-level UIView object)? If not, set it.