I have an iPad app that uses thousands of UITextFields and UITextViews throughout it. When text is being entered into these elements, the iOS default keyboard is used. However, because my app does not provide dictation support, it crashes whenever the user attempts to dictate. Some research into the subject has shown that it isn't possible to disable the dictation feature on the default keyboard.
Instead, I found that it is recommended to use a change the type of keyboard to one that doesn't offer a dictation option. The problem is that I have thousands of UITextFields and UITextViews throughout my app, so manually going in and changing the keyboard type of each of these is unfeasible. My question is this: is there a way to change the default keyboard used within an app?
One way to go about doing this is to use a category and set the value during init. This requires swizzling, but should be safe.
Keep in mind that this will do what you are requesting, so ALL UITextFields will now present using the defined keyboard type (even if you didn't instantiate the text field yourself).
This category will default all UITextFields to display the number pad.
#import "UITextField+KeyboardType.h"
#import <objc/runtime.h>
#implementation UITextField (KeyboardType)
+(void)initialize {
Method originalMethod = class_getInstanceMethod([self class], #selector(init));
Method swizzledMethod = class_getInstanceMethod([self class], #selector(init_swizzled));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (instancetype)init_swizzled {
self = [self init_swizzled];
if (self) {
self.keyboardType = UIKeyboardTypeNumberPad;
}
return self;
}
#end
I would recommend that you instead create subclasses of UITextField/UITextView and replace all existing instances of UITextField/UITextView with their new subclasses.
Related
I need to have a text part in my iOS application (in Objective C), with different names written. Each name must be linked to a view with the person's informations.
I don't know how to do that, what to use to be able to generate multiple links in one text, and link each name do the right action. So when I click on the link it should send the name I clicked on to required action.
Anyone knows how to do that with UIViews ? Or UILabels ? or anything..
Also, whenever I put a UIView in my View, it takes longer to load, do you know why ?
Thanks.. Hope that was clear enough !
HermyKa
You can use RTLabel for that,
Add this library in your code and than follow this step,
In .h file add this code
//Import RTLabel
#import "RTLabel.h"
// Add delegate
#interface ViewController : UIViewController<RTLabelDelegate>
#end
And in .m file
- (void)viewDidLoad {
RTLabel *label = [[RTLabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width-262)/2, (self.view.frame.size.height-203)/2, 262, 203)];
label.delegate = self;
// You have to create link for each name
NSString *searchString = #"Dilip Dev Ram";
}
//RTLabel Delegate Method
- (void)rtLabel:(id)rtLabel didSelectLinkWithURL:(NSURL*)url
{
//When user click on one of the name this method will called and url will return the name which user has tapped. You can add condition on name that which view will display.
NSLog(#"did tap on name %#", url);
}
You can use the set of the UILabels with gesture recognizer connected to each. Or the set of UIButtons.
http://www.raywenderlich.com/104744/uigesturerecognizer-tutorial-creating-custom-recognizers
I started creating all elements programmatically and I repeat most of the code for styling the fields (e.g. borderStyle, keyboardType, keyboardAppearance, spellCheckingType, etc.).
What is the most acceptable way of doing this from one place?
Analogue would be CSS - I would define the general styles in one place, and all generated elements would use them automatically.
Thanks!
If I kept wanting UITextFields with a certain setup, my preferred approach would be to add a factory method to UITextField:
#implementation UITextField (DHFactory)
+ (instancetype)dh_textField {
UITextField *textField = [[self alloc] init];
[textField setKeyboardAppearance:UIKeyboardAppearanceAlert];
[textField setSpellCheckingType:UITextSpellCheckingTypeNo];
return textField;
}
#end
I prefixed the category method name, following the advice in Appleās Programming with Objective-C.
I am trying to implement a feature in iOS project that when you select a piece of text and highlight it you can then choose from the menu options to use another app like the default dictionary. Is it possible to do this? If so where can I find such documentation or tutorials?
You are describing the iOS menu. Look at the documentation on classes such as UIMenu, UIMenuItem, and UIMenuController.
I've found a solution to my problem.
Thanks to the author of this article:
http://blog.studiovillegas.com/2014/02/06/ios-uipasteboard-uimenucontroller-and-uimenuitem/
To add a custom menu item on to the default menu controller.
ViewController.h
- (void)longPressGestureRecognizer:(UIGestureRecognizer *)recognizer
{
UIMenuItem *mi = [self.label menuItemOpenPleco];
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = #[mi];
}
PasteboardLabel {h,m}
#interface PasteboardLabel : UILabel
- (UIMenuItem *)menuItemOpenPleco;
#end
#implementation PasteboardLabel
- (UIMenuItem *)menuItemOpenPleco
{
return [[UIMenuItem alloc] initWithTitle:#"Open Pleco" action:#selector(openPleco:)];
}
- (void)openPleco:(id)sender
{
NSString *selectedText = [self textInRange:[self selectedTextRange]];
UIPasteboard *pb = [UIPasteboard generalPasteboard];
pb.string = selectedText;
NSString *urlString = [NSString stringWithFormat:#"plecoapi://x-callback-url/q?s=%#", pb.string];
NSURL *url = [[NSURL alloc] initWithString:urlString];
[[UIApplication sharedApplication] openURL:url];
}
#end
I've found that there's a dearth of examples of adding custom menu items, or explanations of how they work. So I wanted to resolve that by sharing a few important tidbits then showing an example.
The UIMenuController "talks" with UIViews, not with UIViewControllers. This means that your UIMenuController related code needs to go into subclasses of UIView rather than a UIViewController.
Notice the word The at the start of my prior example. There's only one UIMenuController, a singleton which is shared from when your application first starts until it ends. This means that you should only add your item once, and that you shouldn't be writing over the existing array of items.
The appearance of the button in the UIMenu is based on whether or not the UIView that was tapped responds to the selector. This means you need to implement the method if you want the button to appear, and that you don't need to worry about it appearing when unrelated views are tapped unless you pick a selector name for which other UIViews also have methods.
So, having said all that, I made a subclass of a UITextView (which means its a subclass of UIView per my first bullet) and then I gave it this initialize method, along with an implementation for my selector.
+ (void)initialize {
static dispatch_once_t addInsert;
dispatch_once(&addInsert, ^{
UIMenuController *mController = [UIMenuController sharedMenuController];
UIMenuItem *insert = [[UIMenuItem alloc] initWithTitle:#"Insert..."
action:#selector(insert:)];
mController.menuItems = [mController.menuItems arrayByAddingObject:insert];
});
}
- (void)insert:(id)sender {
NSLog(#"Insert... pressed!");
}
The important points above here:
It's in the class initialize method, which is called by the runtime before the first time any other method in your class is invoked. In practice means the code is handled just before the first time an instance of your custom view will be appearing on screen.
I added a dispatch_once guard around it. If my class is subclassed, it's possible that those subclasses will call this initialize method. Maybe those subclasses show up before this one does, so I don't want to prevent the initialize method from running then. I just want to prevent it from running multiple times. Thus why I wrapped the code in a dispatch_once.
I didn't just set the menuItems to a new array of items - I assigned it to a new array of items that extended the existing array of items with my new item.
Hope you find all of that helpful. It's not very complicated, and you can certainly go about implementing my second point in other ways - I tried to pick a way that seemed safest to me, but there are certainly simpler ways of doing it.
I don't know if I have chosen right title for my question.
I have developed an app and now I want to process text before assigning text to UILabel or UIView text property.
instead of
myLabel.text = story.text
do this:
myLabel.text = [story.text substituteCharactersOfText];
substituteCharactersOfText is a method of Category I have added to NSString class
so if I have a lot of label or another views, it will be difficult or errorProne to manually call this category method. (maybe I forgot one for anotherLabel.text)
so is there anyway to call this method automatically before assigning text to UILabel.text?
I think maybe there is way in objective-c I don't aware of (maybe an special use of delegate)!!
Subclass UILabel and override setText:
#implementation HALabel
- (void)setText:(NSString *)text {
[super setText:[text substituteCharactersOfText]];
}
#end
I have made an application in which user may generate as many UITextField as he/she wants and those will be automatically placed over a UIView. Functionality is that user may drag the any of the UITextField at any point of screen.Till this part every thing is quite working. Now if he wants to edit the UITextField he taps(2 times) on UITextField and edits.This part of mine is only working for the recent generated UITextField not for all. How can i do this? I fnay one wants my previous code i can post. Plese respond it sonn. Thanks in advance.
add textFieldArray to .h file then specify <UITextFieldDelegate> and
sythesize that array.
while creating the each textfield
specify delegate like this
mytextF1.delegate=self;
mytextF2.delegate=self;
.....
after that add all text field object to an textFieldArray which should be declared .h file and synthesize them .(dont forget to alloc and init this array in ur viewdidload).
self.textFieldArray=[[NSMutableArray alloc]init];
then add each text field to this array
[self.textFieldArray addObject:mytextF1];
[self.textFieldArray addObject:mytextF2];
.......
then use this delegate methode to update
- (void)textFieldDidBeginEditing:(UITextField *)textField{
for (UITextField *textF in self.textFieldArray) {
[textF setText:[textField text]];
}
}