I added a toolbar on top of the keyboard, it appears every-time the user clicks on a TextView, it also has a number of buttons that change and interact with the TextView, like for example, changing the text font.
What I'm trying to do now is to create a subclass of the Toolbar so that it can be used on other TextViews, but my problem is:
How to use the TextView delegate methods from inside the Toolbar subclass?
Here is my current code(not all code, for not making the post too big):
.h
#import <UIKit/UIKit.h>
#interface CustomUIToolbar : UIToolbar{
UIButton *btn1;
UIButton *btn2;
UIButton *btn3;
}
.m
#implementation CustomUIToolbar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIBarButtonItem *one = ...
UIBarButtonItem *two = ...
UIBarButtonItem *three = ...
self.barStyle = UIBarStyleDefault;
self.layer.borderWidth = 1;
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self.items = [NSArray arrayWithObjects:one,placeholder,two,three,four,five,nil];
[self sizeToFit];
}
return self;
}
-(void)actionBtn3:(UIButton *) barBtnItem{
...
}
-(void)actionBtn2:(UIButton *) barBtnItem{
...
}
-(void)actionBtn1:(UIButton *) barBtnItem{
...
}
// And the UITextView Delegate Methods
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
...
return YES;
}
- (void)textViewDidChangeSelection:(UITextView *)textView {
...
}
Your CustomUIToolbar class should conform to UITextViewDelegate protocol:
#interface CustomUIToolbar : UIToolbar <UITextViewDelegate> {
Then you need to assign your CustomUIToolbar subclass as a delegate to textView:
self.textView.delegate = self.customTabbar;
Update:
I think the problem because your toolbar instance is released before the delegate method is called on it. Try to make a property to make sure that variable stays in memory. So instead of:
UIToolbar *tool = [[CustomUIToolbar alloc] init];
Create a property:
#property(nonatomic, strong) CustomUIToolbar *tool;
And initialize it:
self.tool = [[CustomUIToolbar alloc] init];
You can make another class for UIextView and import toolbar class in it and call bar button click method from this class. and use textview of this class where it need.
Related
I have the problem like this: Hide UISearchBar Cancel Button
I have subclassed UISearchController and UISearchBar, and override methods layoutSubviews in UISearchBar.
How to override searchBar property with custom UISearchBar in my custom UISearchController?
Update 1
To implement property with custom UISearchBar i do in MyUISearchController:
#property(nonatomic, strong, readonly) UISearchBar *searchBar;
And
#synthesize searchBar=_searchBar;
- (UISearchBar *)searchBar {
return [MySearchBar new];
}
But UISearchController uses default searchBar anyway..
Update
In h file:
#interface MySearchController : UISearchController <UITableViewDelegate, UITableViewDataSource>
In m file:
#interface MySearchController () <UISearchDisplayDelegate, UISearchControllerDelegate,
UISearchBarDelegate, UISearchResultsUpdating, SearchAutocompleteLoader>
#property UISearchController *searchController;
#property (strong, nonatomic) UITableView *searchResultTable;
#property UIView *viewForSearchBar;
#property (nonatomic) NSInteger filterSettings;
#property (strong, nonatomic) UILabel *matchesLabel;
#property (strong, nonatomic) UIView *loading;
#property (strong, nonatomic) UIView *foggView;
#end
- (instancetype)initWith:(UIView *)viewForSearch foggView:(UIView *)view delegate:(id)delegate andResultTableView:(UITableView *)tableView
{
self.viewForSearchBar = viewForSearch;
self.searchResultTable = tableView;
self.foggView = view;
self.searchDelegate = delegate;
[self configureSearchController];
return self;
}
- (void)configureSearchController {
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.dimsBackgroundDuringPresentation = NO;
[self loadFilterSettings];
self.searchController.searchBar.delegate = self;
[self.searchController.searchBar setShowsCancelButton:NO];
//self.searchController.searchBar.searchBarStyle = UISearchBarStyleDefault;
[self.searchController.searchBar setBackgroundImage:[UIImage imageWithCGImage:(__bridge CGImageRef)([UIColor clearColor])]];
[self.searchController.searchBar setImage:[UIImage imageNamed:#"iconSearchSettings"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal];
self.searchController.searchBar.frame = CGRectMake(0, 0, self.view.frame.size.width, self.viewForSearchBar.frame.size.height);
self.viewForSearchBar.tintColor = [UIColor yellowColor];
// [self.viewForSearchBar addSubview:self.searchController.searchBar];
self.searchController.searchBar.barTintColor = [UIColor whiteColor];
self.searchController.searchBar.tintColor = [UIColor blackColor];
//self.searchController.searchBar.backgroundColor = [UIColor whiteColor];
[self.viewForSearchBar addSubview:self.searchController.searchBar];
for (UIView *subView in self.searchController.searchBar.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
[subView setTintColor:[UIColor blueColor]];
[[(UITextField *) subView valueForKey:#"textInputTraits"] setValue:[UIColor blueColor] forKey:#"insertionPointColor"];
}
}
[self.searchController setActive:YES];
[self.searchController setActive:NO];
}
UISearchController's searchBar is a computed property, you have to store your custom searchBar and return it when call searchBar.
Here is some code in Swift:
var mySearchBar = MySearchBar()
override var searchBar: UISearchBar {
get{
return mySearchBar;
}
}
In order to customize the searchBar property begin the customization process by subclassing first the search bar (UISearchBar). Then, use this custom search bar in the subclass of the search controller, and at the end use both of them in the your ViewController class.
Refer this tutorial:
UISearchController Customization
import UIKit
class MySearchController: UISearchController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
searchBar.showsCancelButton = false
}
}
See this one tutorial for customise the UISearchBar in Swift:
Customise UISearchBar
Objective - C : Add the code in ViewDidLoad. You have already declare object of UISearchBar
[searchBar setShowsCancelButton:NO];
Swift : in ViewDidLoad
searchBar.showsCancelButton = false
I have a custom class based on UIButton, and I have difficulties calling the custom setter method in this custom class. I will list the codes in these files:
CallMyMethod.h (subclass of UIButton)
CallMyMethod.m
CallOtherClassMethod.h (to call setter method in CallMyMethod)
CallOtherClassMethod.m
CallMyMethod.h
#interface CallMyMethod : UIButton
#property (nonatomic, setter=setIsSelected:) BOOL isSelected;
#property (nonatomic, retain) UIImageView *checkmarkImageView;
- (void)setIsSelected:(BOOL)aIsSelected; //this is unnecessary, I guess
#end
CallMyMethod.m
#implementation CallMyMethod
#synthesize isSelected = _isSelected;
#synthesize checkmarkImageView = _checkmarkImageView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self loadView];
}
return self;
}
- (void) loadView
{
[self.checkmarkImageView setHidden:YES];
}
- (UIImageView *)checkmarkImageView
{
if (_checkmarkImageView == nil) {
UIImage *checkmarkImage = [UIImage imageNamed:#"checkmark.png"];
_checkmarkImageView = [[UIImageView alloc]initWithImage:checkmarkImage];
[_checkmarkImageView setFrame:CGRectMake(10, 10, 32, 32)];
[self addSubview:_checkmarkImageView];
}
return _checkmarkImageView;
}
- (void)setIsSelected:(BOOL)aIsSelected
{
_isSelected = aIsSelected;
[self.checkmarkImageView setHidden:!_isSelected];
[self addSubview:_checkmarkImageView];
}
#end
CallOtherClassMethod.h
#class CallMyMethod;
#interface CallOtherClassMethod : UIViewController
#property (nonatomic,retain) CallMyMethod *btnCMM;
#end
CallOtherClassMethod.m
#import "CallMyMethod.h"
#implementation CallOtherClassMethod
#synthesize btnCMM;
- (void)viewDidLoad
{
[super viewDidLoad];
self.btnCMM = [[CallMyMethod alloc]initWithFrame:CGRectMake(0, 30, 50, 70)];
//somewhere in my code I will add btnCMM to the view
[someView bringSubviewToFront: btnCMM];
[someView addSubview: btnCMM];
}
//somewhere where I pressed a button to trigger this method
- (IBAction) pressMe:(id)sender
{
NSLog(#"self.btnCMM %#", self.btnCMM); //returned as btnCMM is nil ?!
[self.btnCMM setIsSelected:YES];
}
#end
The issue lies in the program not able to run the codes in setIsSelected method, I have traced btnCMM to be nil in NSLog. I wonder why is this so, because when I call CallOtherClassMethod as a UIViewController, the viewDidLoad would have initialised my custom button. Am I doing something wrong here?
Why not override setSelected, which is a method on UIButton and then use button.selected = YES?
If you want to debug why your button becomes nil, implement dealloc in your UIButton subclass, put a breakpoint there, and see the stack trace to find the reason.
How to start entering the text in UITextFiled at specific position ?
make a class using subclass of UITextField and in .m file
#import "CustomTextField.h"
#import <QuartzCore/QuartzCore.h>
#implementation CustomTextField
- (id)initWithCoder:(NSCoder*)coder
{
self = [super initWithCoder:coder];
if (self) {
//self.clipsToBounds = YES;
//[self setRightViewMode:UITextFieldViewModeUnlessEditing];
self.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,15,46)];
self.leftViewMode=UITextFieldViewModeAlways;
}
return self;
}
Go to your storyboard or xib and click on identity inspector and replace UITextfield with your own "CustomTextField" in class option.
I am trying to change self.navigationController.toolbar position to top instead of a bottom.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIToolbarDelegate, UIBarPositioningDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
// View did load
- (void)viewDidLoad
{
// Superclass view did load method call
[super viewDidLoad];
// UIToolbarDelegate
self.navigationController.toolbar.delegate = self;
}
- (void)viewDidLayoutSubviews
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.frame = CGRectMake(self.navigationController.toolbar.frame.origin.x, 64.0f, self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height);
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(50.0f, 10.0f, 220.0f, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
}
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
The position changes at first, but later gets back to the bottom. Please, help me!
First make sure that toolbar delegate method positionForBar: is get called. If not, then your toolbar delegate is not properly set and you've have to define the UIToolbarDelegate protocol inside your header class.
#interface ExampleViewController : UIViewController <UIToolbarDelegate>
...
#end
Then set the delegate and also change the frames for toolbar. However, for the orientation you might have to reconsider the frames of toolbar.
#implementation ExampleViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set the toolbar delegate
self.navigationController.toolbar.delegate = self;
self.navigationController.toolbarHidden = NO;
// create a toolbar child items
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.with, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
// set the frames
CGRect toolbarFrame = self.navigationController.toolbar.frame;
toolbarFrame.origin.y = self.navigationController.frame.size.height;
self.navigationController.toolbar.frame = toolbarFrame;
}
// pragma mark - UIToolbarDelegate
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
In your viewDidLoad method, add:
self.navigationController.toolbar.delegate = self;
I have a view controller (UserLogin) that calls a method in NSObject class (custompop). The method returns a UIView object to viewController. In method i add one button and call action popupAction on button click. The popupAction calls method in view controller. I set all the delegate property.
Here is the code:
//**in viewcontroller.h**
#import "custompopup.h"
#interface UserLogin : UIViewController<customPopUpDelegate>
{
custompopup *obj_custompopup;//NSObject Class
}
-(void)handlePopUpAction;
//**in viewcontroller.m**
- (void)viewDidLoad
{
[super viewDidLoad];
obj_custompopup = [[custompopup alloc] init];
[obj_custompopup setDelegate:self];
popupview = [[UIView alloc] init];
popupview = [obj_custompopup initwithTitleText:#"Title" withdelegate:self];
[self.view addSubview:popupview];
}
-(void)handlePopUpAction
{
NSLog(#"Inside handlePopUpAction");
}
//**in NSObject.h**
#protocol customPopUpDelegate <NSObject>
-(void)handlePopUpAction;
#end
#interface custompopup : NSObject
{
id<customPopUpDelegate>delegate;
UIButton *First_Btn;
}
#property(retain)id delegate;
//**in NSObject.m**
#synthesize delegate;
-(UIView *)initwithTitleText:(NSString *)titleText withdelegate:(id)del
//returns uiview to viewcontroller
{
self.delegate =del;
UIView *customView = [[UIView alloc] init];
customView.frame = CGRectMake(200, 100, 617,367);
First_Btn =[UIButton buttonWithType:UIButtonTypeRoundedRect];
First_Btn.frame=CGRectMake(20, 330,125,45);
[First_Btn #"title" forState:UIControlStateNormal];
[First_Btn addTarget:self action:#selector(popUpAction) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:First_Btn];
return customView;
}
-(void)popUpAction
{
[[self delegate] handlePopUpAction];
}
Problem is compiler goes in each method successfully and print everything in console till last step. After complete last step in view controller, EXC_BAD_ACCESS comes and the application crashes.
your init is wrong .. dont get what you try to do but you return customView , leaving self unretained but you are using self.