UITextView beginningOfDocument returns nil - objective-c

I have to get the position on the screen of a string contained in a UITextView. To do that, I tried to get the corresponding UITextPosition(s). The problem is that the UITextView method beginningOfDocument returns nil (same for endOfDocuement). Could someone explain me why? And which solution I could use.
My code looks like this:
- (UITextRange *)getRangeOfString:(NSString *)string inTextView:(UITextView *)tv
{
UITextPosition *beginning = [tv positionFromPosition:tv.beginningOfDocument offset:[tv.text rangeOfString:string].location];
UITextPosition *end = [tv positionFromPosition:beginning offset:[tv.text rangeOfString:string].length];
return ([tv textRangeFromPosition:beginning toPosition:end]);
}

This is about a month late, but make sure you have the "selectable" property enabled in Interface Builder.
Credit: http://jon-nolen.blogspot.com/2013/10/uitextview-returns-nil-for-uitextinput.html

Make sure the UITextField is added as a subview of another view. If it exists just in memory, the beginningOfDocument and endOfDocument properties will return nil for some reason.

Related

get indexPath for customCell in TableView

I have a UITextField in a customCell. I want to be able to get the text that user inputs in it. In my customCell.m file I can get the text that is inputed with
[self.aTextField addTarget:self action:#selector(aTextFieldEditing:) forControlEvents:UIControlEventEditingChanged];
but I cannot get the indexPath so I can save it to the NSMutableArray that holds all the UITextFields.
In my TableView I cannot get the didSelectRowAtIndexPath to run. I also cannot get the textFieldDidBeginEditing method to output anything. If it helps I have a TableView with sections.
My idea at the moment is to get the indexpath.row and indexpath.section from the tableView and save them as an extern so I can access it in the customCell.m
I would be grateful for any ideas or specific examples of how I could do this. Or a different cleaner way to accomplish what I want.
You should be able to get the index path using the -indexPathForRowAtPoint: method on UITableView.
You can do something like this (not tested):
- (void)aTextFieldEditing:(UITextField *)textField {
CGPoint convertedPoint = [textField.superview convertPoint:textField.center toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:convertedPoint];
// Use your index path...
}
Edit:
In the case your cell is receiving the edit events, you can always define a protocol and make your view controller a delegate of the cell. You could then call this delegate method from your aTextFieldEditing method and pass the cell. Now that you have the cell you can call -indexPathForCell on your table view. If none of this makes sense, look into the delegate pattern. It's very common in Cocoa/Cocoa Touch and is very well documented online.

UITable on a scrollView, UITable not acting on reloadData call

I've got a scroll view, with 2 UITables on it.
Everything about the table work well. Neither of the tables need to scroll themselves.
If I call
[self.tableOne reloadData]; when a button is pressed it works. But when I call it in a delegate method of UITextView it does not action. Is this some threading issue? Or what is causing this bizarre behavior.
I want to increase the size of a TableCell when the user presses on UITextView thats in each cell.
I added a NSLog here to confirm that this method is getting called.
- (void)textViewDidBeginEditing:(UITextView *)textView
{
theTableCellCurrentlyBeingEdited = textView.tag;
[self.tableOne reloadData];
}
Gets touched I note which cell is active, and call reload table so I can adjust the height of this cell in
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath
{
if (theTableCellCurrentlyBeingEdited == indexPath.row)
{
return 120;
}
else
{
return TABLE_CELL_HEIGHT;
}
}
But heightForRowAtIndex never gets called.
I have tableOnes datasource and delegate set to self.
In my .h I have added
<UITextViewDelegate, UITableViewDelegate, UITableViewDataSource>
So the calls are getting here.
Anybody able to give me some advice as to what is going wrong?
Many Thanks,
-Code
First of all. Where do you call the text of the textView?
You are using theTableCellCurrentlyBeingEdited = textView.tag;
And the tag will not give you the text you entered. You are just changing the tag of your cell which won't change a thing to the visuals of the cell.
Second. Why not call:
- (void)textViewDidChange:(UITextView *)textView
or
- (void)textViewDidEndEditing:(UITextView *)textView
So that in the first delegate method your cell gets updated every char you write and in the second you are sure the user is done writing in the textview?

How Do I validate UITextfield with Correct Answer String?

I have a UITexfield in Xcode that the user inputs their answer to a question. If the answer is correct they are taken to another screen. All the help I have found only shows how to verify the amount of characters or numbers in a string.
I have declared
NSString *answer = #"The Correct Answer";
and
if ([UITextField1.text isEqualToString:#"The Correct Answer"])
then ...
This is where I get lost (sorry total newbie) I have been able to compare these in NSlog in foundation.h file but get really lost when trying to deal with .h and .m files in xcode.
Can anyone please check if with the above I am on the right track and please explain how I get to display the new screen when the string/answer is correct.
Thanks in Advance
The check you are making is correct. It checks the precise text of the TextField1 with the precise text of #"The Correct Answer". If it matches you can make your navigationController push a new view.
ea. Like this:
MyViewController *myVC = [[MyViewController alloc] init];
//do something with your new ViewController.view
[self.navigationController pushViewController:myVC animated:YES];
Of course you will have to adjust the new View to your own needs. Also make sure you have access to that navigationController.
But yeah, this is all very basic and you should be able to figure it out for yourself with some proper tutorials.
Well I'm not clear on your question.
If you are asking how to show a screen once a user typed the right answer in textbox then use:
Set textfield's delegate to your view controller then handle this method in your view controller:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Just do the needful there, something like:
if ([textField.text isEqualToString:#"The Correct Answer"])
{
[self presentModalViewController:correctVC animated:NO];
return NO;
}
return YES;

Cocoa NSView subview blocking drag/drop

I have an NSView subclass which registers for drag files in init method like this:
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
The drag drop works perfectly fine, but if I add a subview to this view with the exact same frame, it doesn't work any more. My guess is that the subview is block the drag event to go to super view. Can can I avoid that? Thanks
Also, I know I am asking two questions, but I don't want to create a new topic just for this: When I am dragging, my cursor doesn't change to the "+" sign like with other drags, how can I do that?
Thanks again.
UPDATE:
Here's the how I have it set up in my IB:
The DrawView is the custom class I was talking about that registered for draggedtypes. And the Image view simply is a subview, I dragged an image from the media section...
If it helps, here's my relevant code for DragView:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
return NSDragOperationCopy;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pboard;
pboard = [sender draggingPasteboard];
NSArray *list = [pboard propertyListForType:NSFilenamesPboardType];
if ([list count] == 1) {
BOOL isDirectory = NO;
NSString *fileName = [list objectAtIndex:0];
[[NSFileManager defaultManager] fileExistsAtPath:fileName
isDirectory: &isDirectory];
if (isDirectory) {
NSLog(#"AHH YEA");
} else {
NSLog(#"NOO");
}
}
return YES;
}
The answer to the second part of your question is this:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender{
return NSDragOperationCopy;
}
if you return NSDragOperationCopy, you get the mouse badge for a copy operation. (You can and should, of course, not just return NSDragOperationCopy unconditionally; check the objects on the pasteboard to see if you can accept them.)
I'm not sure what the answer to the first part of your question is, because I'm unable to recreate the subview blocking effect.
Okay, the answer is unfortunately that you can't. The image you dragged is contained in an NSImageView, and NSImageViews accept drag events themselves, so it's grabbing the drag event and not doing anything with it. If your subview was a custom class, you could either a) not implement drag and drop, in which case the drags would be passed through; b) implement drag and drop to accept drags for the subview. In this case, you're using a class over which you don't have any control. If all you want it to do is display an image, you should be able to make another NSView subclass that does nothing but draw the image in drawRect:
As mentioned in the comments, NSImageViews have their own drag and drop enabled by default (used for accepting images that are dragged onto the NSImageView). If you don't want to use this behavior and instead want to use the super view's drag and drop behavior, you'll want to unregister the dragging behavior in the NSImageView.
Objc:
[imageView unregisterDraggedTypes];
Swift:
imageView.unregisterDraggedTypes()
(in case anyone else stumbled across this question first and not the linked one in the comments)

Fetching reference to superview from UITextField?

I have created three UIImageViews. I then added a UITextField to each image as a subview.
When the user clicks on the text field I want to capture which UIImageView ths text field belongs to. I am trying the following code :
-(void)textFieldDidBeginEditing : (UITextField *)textField {
textField = retainedObject;
MyPicture *capture = nil;
for (UIImageView *oneView in retainedObject.superview) {
if ([oneView isMemberOfClass:[myPicture class]])
capture = (UIImageView *)oneView;
}
However I get an error that UIView may not respond to count by enumeration. It looks like the superview of the textfield is UIView rather than UIImageView perhaps ? Can anybody help solve this ?
Thanks,
Martin
A UIView's superView is assumed to be a UIView. However, you can still cast it as a UIImageView, and call UIImageView methods on it, but just make sure it will always be a UIImageView without exception, as otherwise it will crash.
Source: My own applications ;)