Insert string at location Objective-C - iphone

I'm making an app the has 'hotkeys' in it and when you tap the hotkey it should insert a character at the location you are typing at.
I'm using a UITextView with editing on.
What I want do do is insert the text right after the blue cursor.
Is this possible?

You want to use the insertText: method of UITextView, which is declared in its implementation of the UIKeyInput protocol (which is a super-protocol of UITextInput, which UITextView implements.)

You can get the location of the cursor by using
int position = txtView.selectedRange.location;
Then you will need to get the string from the text view and insert your own string
NSMutableString *str = [txtView.text mutableCopy];
[str insertString:#"YourString" atIndex:position];
txtView.text = str;
This may scroll the text view and lose your current cursor, if you dont want to lose it, you will need to subclass UITextView and do some work inside the drawRect

Related

Each button click adds text to current label objective-c

I'm new to the Objective-c language. I'm trying to create an app that has a button and a label. The button should display some text which I did already. The only problem is that when I click the button, it only adds the specified text once. I want it to keep adding the same text to the label each I time I press the button.
Here is my .h file
{
IBOutlet UILabel *label;
}
-(IBAction)btnClcik:(id)sender;
Here is the .m file
-(IBAction)btnClcik:(id)sender
{
label.text=#"test";
}
To append to the existing text, use the string's concatenation method...
label.text = [label.text stringByAppendingString:#"test"];
You need to append to the string?
Then do
label.text = [label.text stringByAppendingFormat:#"%#", textToAdd];
where textToAdd is a NSString or some other valid object where %# is the correct format specifier.

UITextView inputView

I'm making a custom input method for the iPad, I want to be able to replace the system keyboard with my input method and enter text via that input method.
According to the documentation all I need to do is to set the inputView property with my view and it will be used instead of the system keyboard. I did that and it works, as far as showing the keyboard but how do I actually enter text into the text view?
Supposedly the text view needs to adopt the UIKeyInput and I can use the protocol's methods to enter the text but in reality UITextView doesn't adopt this protocol. conformsToProtocol:#protocol(UIKeyInput) returns NO and "deleteBackwards" is not implemented (insertText and hasText are implemented. In addition to that, "insertText" doesn't cause the textViewDidChange: delegate method to be invoked. Obviously I need to send the UIKeyInput method to some other object (a field editor?) but how do I get it?
Any ideas?
Assuming your keyboard has some buttons, why cant you just set a selector for your keys, and append to the textViews text when each button is clicked, I have done this an it works fine...Here is the method that actually does the "writing" to the UITextView, this method is part of a custom protocol defined by the inputView and is called on the delegate whenever a button is pressed, hope it helps, note: i submit ret when the return key is pushed and <- when backspace is pushed.
-(void)userDidInputString:(NSString*)s
{
NSRange r=padView.textView.selectedRange;
if([s isEqualToString:#"ret"])
s=#"\n";
if([s isEqualToString:#"<-"])
{
NSString *text=padView.textView.text;
if(r.location>0)
{
r.location=r.location-1;
r.length+=1;
}
[padView.textView setScrollEnabled:YES];
padView.textView.text=[text stringByReplacingCharactersInRange:r withString:#""];
[padView.textView setScrollEnabled:NO];
r.length=0;
[padView.textView setSelectedRange:r];
[note setNoteText:padView.textView.text];
}
else {
NSString *text=padView.textView.text;
[padView.textView setScrollEnabled:YES];
padView.textView.text=[text stringByReplacingCharactersInRange:r withString:s];
[padView.textView setScrollEnabled:NO];
r.location=r.location+[s length];
//whenever you modify the text by setting the UITextViews text property it resets the cursor to the end of the text view, we have this line below to go back to where the user left off
[padView.textView setSelectedRange:r];
}
}

UITextView.text property doesn't update first time, and then clips or doesn't display when it does

I'm trying to get the contents from a dictionary into a UITextView. The dictionary contains molecular masses paired with percentages, for example:
24 -> 98
25 -> 1.9
26 -> 0.1
I have an NSArray containing the keys from the dictionary, sorted in ascending order. So, here is my code to generate the string to set as the textField.text property:
-(void)detailIsotopes:(NSMutableDictionary *)isotopes withOrder:(NSMutableArray *)order{
NSMutableString *detailString = [[NSMutableString alloc] init];
for (NSNumber *mass in order){
[detailString appendString:[NSString stringWithFormat:#"%d: %f\n", [mass integerValue], [[isotopes valueForKey:[NSString stringWithFormat:#"%#", mass]] floatValue]]];
}
NSLog(#"%#", detailString);
textField.text = detailString;
[detailString release];
}
This should create a string looking like this:
24: 89
25: 1.9
26: 0.1
For some reason, this method never does anything the first time it runs. I see the NSLog output, which outputs the correct string. However, the contents of the UITextView don't change: they stay as 'Lorem ipsum dolor sit amet...' from Interface Builder. If I run the method again, it works, sort of.
The UITextView displays some of the text, and then just cuts off half way through a line, leaving only the tops of the characters. If I delete the contents above the half line, the other lines pull up from under the divide: the contents are there, they just stop being shown, if you understand what I mean. This appears to go away if I enable paging in the view. If I do that, then the line isn't truncated, but the UITextView just stops showing any content after some point, although the scroll bar indicates that there is more to go (which there is).
The view containing the UITextView is not visible when the contents is set, if that makes a difference. A separate view controller generates the NSMutableDictionary and NSMutableArray and sends them to its delegate, which then sends them to the view which should display the UITextField and has the detailIsotopes: withOrder: method. The two can be swapped between with an info button.
Does anyone understand why these things are happening?
Thanks for any advice you can give!
First of all, I don't think you need to allocate and release your NSMutableString here. Simply initialize one using [NSMutableString string] which creates an empty string you can modify and don't need to explicitly release.
Second thing, you seem to store masses in NSStrings in your NSDictionnary, why do you use their integerValue method for stringWithFormat (with %d modifier), instead of using them as is? (the stringWithFormat modifier for NSStrings is %#)
Also, you talk about a UITextView at start, then about a UITextField, are you sure you did not make a mistake somewhere? I guess the receiving object for your formatted NSString should rather be the UITextView (if you have both a textField and textView).
If it's not about this, maybe you are calling detailIsotopes too early and the textView it's created yet. Try to NSLog its address and see if it's nil the first time. It could be the case if you use Interface Builder and your UITextField is an ib outlet. If you do, then you could store your dictionary and array in the viewController, and set the textField in the viewController's viewDidLoad method. Or call detailIsotopes after you've displayed the view, I guess that's up to you.
About the truncated text, I think that's because UITextView doesn't resize itself automatically, so it keeps the height you originally set. What I usually do is this:
CGRect frame = textView.frame;
frame.size.height = textView.contentSize; // you can adjust this to leave some space at the end
textView.frame = frame;
This will set the textView height to the content (the text) height.
Also note that if your textView is supposed to display the whole text, you can set its scrollingEnabled property to FALSE so it never allows scrolling.
Hope that helps.

Contents of UITextField and UITextView to NSString

I have a UITextView and 2 UITextField set up. UITextView resigns first responder status when empty part of the screen is tapped, the same for the 2 UITextField, plus for these 2, the return key also resigns first responder status. All 3 are declared in interface.
I would like to get the contents of all of these to individual NSString and/or learn how to enter them directly into something like:
NSString *urlstr = [[NSString alloc] initWithFormat:#"http://server.com/file.php?var1=%#&var2=%#&var3=%#", *content of UITextView*, *content of UITextField*, *content of UITextField*];
This is a very basic question, i know, but i'm pretty much a novice. If i learn how to do this i'll probably be able to pick up from there.
cheers
(edited)
UITextField and UITextView both have a text property that you can use to retrieve the string values. For example,
NSString *string = [NSString stringWithFormat:#"%#, %#", textField.text, textView.text];
Keep in mind you'll probably want to examine the strings to make sure they're not empty or contain invalid characters before putting them into a URL.
The accepted answer is good, I just wanted to add the following for an expanded look at grabbing text in iOS.
See the textInRange: aspect of the below code that I devised to use one function to determine the text whether it's a UITextField, UITextView or any other class that complies with the UITextInput protocol.
//handle text container object length whether it's a UITextField, UITextView et al
NSUInteger LengthOfStringInTextInput(NSObject<UITextInput> *textContainer)
{
UITextPosition *beginningOfDocument = [textContainer beginningOfDocument];
UITextPosition *endOfDocument = [textContainer endOfDocument];
UITextRange *fullTextRange = [textContainer textRangeFromPosition:beginningOfDocument
toPosition:endOfDocument];
return [textContainer textInRange:fullTextRange].length;
}
By changing the return type to NSString and removing .length you could have the functionality of the text property on any class.

Getting cursor position in a UITextView on the iPhone?

We have a UITextView in our iPhone app which is editable. We need to insert some text at the cursor location when the users presses some toolbar buttons but can't seem to find a documented (or undocumented) method of finding the current location of the cursor.
Does anybody have any ideas or has anybody else achieved anything similar?
Like drewh said, you can use UITextView's selectedRange to return the insertion point. The length of this range is always zero. The example below shows how to it.
NSString *contentsToAdd = #"some string";
NSRange cursorPosition = [tf selectedRange];
NSMutableString *tfContent = [[NSMutableString alloc] initWithString:[tf text]];
[tfContent insertString:contentsToAdd atIndex:cursorPosition.location];
[theTextField setText:tfContent];
[tfContent release];
Swift 4:
// lets be safe, thus if-let
if let cursorPosition = textView.selectedTextRange?.start {
// cursorPosition is a UITextPosition object describing position in the text
// if you want to know its position in textView in points:
let caretPositionRect = textView.caretRect(for: cursorPosition)
}
We simply use textView.selectedTextRange to get selected text range and cursor position is at its start position.
Use UITextView selectedRange property to find the insertion point when the text view is first responder. Otherwise, when the view is not in focus, this property returns NSNotFound. If you need to know the cursor position in that case, consider subclassing UITextView and overriding canResignFirstResponder method, where you can store cursor position to a member variable.
Have you tried UITextView.selectedRange? It returns an NSRange, whose location element should tell you, where the cursor is.