iOS: Detect backspace in empty UITextField with UITextField subclass - ios

The clear answer to detecting a backspace is by creating a subclass of UITextField and overriding the deleteBackward property.
I've created a subclass a UITextField subclass, but am getting this error:
'NSInvalidArgumentException', reason: '-[UITextField setMyDelegate:]: unrecognized selector sent to instance
This is my subclass code:
My TextField.h:
#protocol MyTextFieldDelegate <NSObject>
#optional
- (void)textFieldDidDelete;
#end
#interface MyTextField : UITextField<UIKeyInput>
//create "myDelegate"
#property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
#end
My TextField.m:
- (void)deleteBackward {
[super deleteBackward];
if ([_myDelegate respondsToSelector:#selector(textFieldDidDelete)]){
[_myDelegate textFieldDidDelete];
}
}
In my ViewController that I would like to access the UITextField subclass I do the following:
#import "MyTextField.h"
<MyTextFieldDelegate>
#property (nonatomic, strong) IBOutlet MyTextField *passcode1;
self.passcode1.myDelegate = self;
Any ideas as to why I am getting the unrecognized selector error? It looks to me like I have done everything correctly in subclassing UITextField.

The problem is with your outlet. The property is defined with your custom class but in a Interface Builder you added a plain old UITextField. Hence the error at runtime. In Interface Buldier, update the text field's class to be your custom class.

Related

Unable to set property of a UIViewController ios

I have a view controller which extends UIViewController.
#interface MyViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextView *phoneTxt;
#property (nonatomic, strong) NSDictionary *data;
#end
However when I try to set the property of the view controller by:
MyViewController *vvc = (MyViewController *)[sb instantiateViewControllerWithIdentifier:#"MyVC"];
vvc.data = data;
I get following error:
'NSInvalidArgumentException', reason: '-[UIViewController setData:]: unrecognized selector sent to instance
I have checked, the view controller is not nil and I have synthesized the property data in MyViewController.m
#synthesize data = _data;
Why am I getting this error?
I think you probably forgot to set the proper class for your view controller (File's Owner) in your storyboard/xib, so it probably gets instantiated as a raw UIWievController.

subclass override method not being called

I created a subclass of UITextField to override the method rightViewRectForBounds.
Here is my custom class CustomTextField
#interface CustomTextField : UITextField
#end
#implementation CustomTextField
// override rightViewRectForBounds method:
- (CGRect)rightViewRectForBounds:(CGRect)bounds{
NSLog(#"rightViewRectForBounds");
CGRect rightBounds = CGRectMake(bounds.origin.x + 10, 0, 30, 44);
return rightBounds ;
}
#end
Now I set up my ViewController to call the custom class instead of UITextField.
#import "OutputViewController.h"
#import "CustomTextField.h"
#interface OutputViewController () <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet CustomTextField *field1;
#property (strong, nonatomic) IBOutlet UILabel *label1;
- (void)methodName
{
self.field1.rightView = self.label1;
}
The property rightView should call my method override according to Apple's Documentation: "The right overlay view is placed in the rectangle returned by the rightViewRectForBounds: method of the receiver". Why isn't my override working?
Sorry if this is a bad question. I've only been programming for a month.
The problem is most likely that field1 is not in fact a CustomTextField. It is easy to confirm this with a breakpoint or some logging.
Remember, it is not enough to declare the class of something. That thing must actually be that class (polymorphism). An instance has a class, quite without regard for how you may cast or declare a variable that refers to it.

FBLogin assign delegate from UIView

I have a FBLogin (Facebook SDK) button I am using in a view being replicated throughout many of my view controllers. It seems I cannot set a UIView as a delegate to the Facebook SDK, so I am trying to create a seperate ViewController to handle the delegate functions of the Facebook SDK.
Header file:
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#class AppDelegate, FBDelegateViewController;
#interface UserView : UIView {
AppDelegate *appDelegate;
IBOutlet UIView *contentView;
IBOutlet UIImageView *userImage;
IBOutlet UILabel *firstName;
FBDelegateViewController *fbDelegate;
IBOutlet FBLoginView *FacebookLogin;
}
#property (nonatomic, strong) IBOutlet UIView *contentView;
#property (nonatomic, strong) IBOutlet UILabel *firstName;
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) FBDelegateViewController *fbDelegate;
Currently in my implementation I am doing the following:
#import "UserView.h"
#import "AppDelegate.h"
#import "FBDelegateViewController.h"
#import <FacebookSDK/FacebookSDK.h>
#implementation UserView
#synthesize contentView, firstName, appDelegate, fbDelegate;
- (void)awakeFromNib {
fbDelegate = [[FBDelegateViewController alloc] init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[[NSBundle mainBundle] loadNibNamed:#"UserView" owner:self options:nil];
[self addSubview:self.contentView];
[userImage.layer setCornerRadius:21.5];
[FacebookLogin setDelegate:fbDelegate];
}
#end
The application crashes with the following:
** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setDelegate:]: unrecognized selector sent to instance 0xa5e4f80'*
In interface builder the UIView that contains the FBLogin item is set.
I also tried delegation with the UIView as well, but it looks like a UIView cannot be a delegate for a FBLogin?
Sorry, new territory here. Typically have used the associated view controller as a delegate - but want to understand external delegation.
It seems I cannot set a UIView as a delegate to the Facebook SDK, so I
am trying to create a seperate ViewController to handle the delegate
functions of the Facebook SDK.
This assumption is false, any NSObject can be set as the delegate as long as it implements the FBLoginViewDelegate protocol
This can be done like this:
#interface UserView : UIView <FBLoginViewDelegate> {
After you do this, you can set this view as the delegate!

Having an ivar 'delegate' in a subclass whose superclass also has same named ivar

I have a subclass defined like this
#protocol UMTextViewDelegate;
#interface UMTexView : UITextView <UITextViewDelegate> {
}
#property (nonatomic, assign) id<UMTextViewDelegate> delegate;
#end
#protocol UMTextViewDelegate <NSObject>
#optional
- (void)textViewDidSelectWordToDefine:(UMTexView*)textView;
#end
But I get a warning Property type 'id<UMTextViewDelegate>' is incompatible with type 'id<UITextViewDelegate>' inherited from 'UITextView'.
How do I suppress this warning ? I tried adding this :
#protocol UMTextViewDelegate <NSObject, UITextViewDelegate>
but no luck. !!
EDIT:
I am not using ARC
The problem you are having is about forward declarations. In the place where you are declaring the delegate, the compiler doesn't know that UMTextViewDelegate descends from UITextViewDelegate. The only thing it knows is that UMTextViewDelegate is a protocol.
You have to create a forward declaration for the class #class UMTexView;, then put the protocol declaration and then the class declaration.
On a separate note, it's obvious UMTexView is supposed to be the text delegate for itself. Maybe it would be easier to have UMTexView descending directly from UIView and put an UITextView inside it. Then you wouldn't have any problem with delegate collisions and the UITextViewDelegate would be unaccessible externally.
Using #Sulthan's answer, this is what I came up with and it squished the warning.
#class UMTextView;
#protocol UMTextViewDelegate <NSObject, UITextViewDelegate>
#optional
- (void)textViewDidSelectWordToDefine:(UMTextView*)textView;
#end
#interface UMTextView : UITextView <UITextViewDelegate>
#property (nonatomic, assign) id<UMTextViewDelegate> delegate;
#end
The forward declaration of UMTextView followed by protocol declaration tells UMTextView that UMTextViewDelegate is indeed descends from UITextViewDelegate. That way I don't have to the route of adding a uiview and then adding a uitextview inside that view.

iOS Instantiate Custom View from Nib File across multiple UIViewController

I need an example of how to instantiate a custom view from a nib file. i wrapped my head around several stackoverflow posts but i didn't get it. Maybe i only need a hint how to do it.
what I want to do is - creating a custom view with interface builder. it should be a template so that i can instantiate it multiple times to add it to multiple view controllers.
So far I have created my custom view xib file called MyIssueView.xib. Which consists in fact just of the main view and some labels.
And I created a Subclass of UIView which is called IssueView with the Outlets for my labels in the MyIssueView.xib.
How do I now hook up the outlets with the IB? And how can I instantiate the IssueView from any ViewController?
Would be glad for an example!
Cheers.
UPDATE:
I now have
IssueView.xib
IssueView.h (UIView Subclass)
IssueView.m
My IssueView.h:
#import <UIKit/UIKit.h>
#interface IssueView : UIView
#property (weak, nonatomic) IBOutlet UILabel *label1;
#property (weak, nonatomic) IBOutlet UILabel *label2;
#property (weak, nonatomic) IBOutlet UILabel *label3;
#property (weak, nonatomic) IBOutlet UILabel *label4;
#end
My IssueView.m:
#import "IssueView.h"
#implementation IssueView
#end
My ViewController.m:
#import "AllIssuesViewController1.h"
#import "IssueView.h"
#import "UIView+NibLoading.h"
#interface AllIssuesViewController1 ()
#end
#implementation AllIssuesViewController1
- (void) loadView
{
}
- (void)viewDidLoad
{
[super viewDidLoad];
_issueView = [IssueView loadInstanceFromNib];
}
It gives me an error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x8292580> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label1.'
I have a category that extends UIView called UIView+NibLoading.
In it is this code...
#import "UIView+NibLoading.h"
#implementation UIView (NibLoading)
+ (id)loadInstanceFromNib
{
UIView *result;
NSArray* elements = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id anObject in elements) {
if ([anObject isKindOfClass:[self class]]) {
result = anObject;
break;
}
}
return result;
}
#end
Then when I want to instantiate a UIView subclass from a nib I just import the category and I can run...
self.issueView = [IssueView loadInstanceFromNib];\
You need to connect the labels like this...
If you connecting the labels to "File's Owner" then you'll need to remove those connections.

Resources