Does scrollViewWillScrollToTop: exist? - ios

Apple documentation says that scrollViewWillScrollToTop: will be called as part of the UIScrollViewDelegate protoco. However, this method doesn't seem to exist even when I recursively grep through the /Developer folder. I don't see where this method is being called nor its prototype. Any hints?

Are you referring to this?
This gesture works on a single visible scroll view; if there are
multiple scroll views (for example, a date picker) with this property
set, or if the delegate returns NO in scrollViewWillScrollToTop:,
UIScrollView ignores the request. After the scroll view scrolls to the
top of the content view, it sends the delegate a
scrollViewDidScrollToTop: message.
It's a typo in the docs. They meant to say scrollViewShouldScrollToTop:. You can see they are mentioning returning a BOOL value, and will... delegate methods usually don't return anything. The ones starting with should... on the other hand do.
I suggest you report this by clicking the "It's good, but..." link in the footer of the doc. I will do the same.

Related

setting view.accessibilityElements with embedded view controllers

I am trying to add iOS accessibility support/Voice Over to my app. My main screen has three main controls, but the third control is hosted within an embedded view controller.
I am setting accessibility elements in prepareForSegue and have confirmed that the embedded view controller controls are all loaded. Problem is I can still only select the first two controls which are in the enclosing view controller.
self.view.accessibilityElements =
#[
self.cmdMenu, // works
self.collectionView, // works
self.childViewController.peerMenu // doesn't work
];
All three views have isAccessibilityElement = YES.
Am I missing something? I can't imagine that there is a restriction on the accessibility elements being in the same view controller.
I found my bug and now have Voice Over working. In the process I figured out a number of things that I would like to share.
To my original question, you can reference controls in your child view controllers from your main view controller. You can add the controls directly (as I did in my question) or you can add all accessibility elements in the child view controller using self.view.accessibilityElements = #[ _control1, childViewController.view, childViewController2.view].
If you add all of the controls in your child view controller as in (1.) then ensure that childViewController.view.isAccessibilityElement = NO.
You can add any kind of object to accessibilityElements, even elements that have no accessibility information. The API will not assert or warn you. This ended up being my bug.
If your UI changes and you need to change the number or order of items in your accessibilityElements array tell UIKit about it using UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self). The notification argument (where I'm sending self) tells Voice Over where it should position its cursor when the notification completes.
If you want to read aloud some text for a transient notification (imagine when Clash Of Clans tells you how many Gems you found in that Tree Stump) call UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, messageText). One caveat, this won't read aloud the messageText unless there is no other Voice Over in progress. You need to manage the timing yourself. Submitted a bug on this. Apple could make this a lot better.
If you are using UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, messageText) you can listen for UIAccessibilityAnnouncementDidFinishNotification, but unfortunately this notification has almost no value. You only will get notified if your messageText was fully spoken. It doesn't tell you that it was spoken, but interrupted, and it will also not get triggered for any text spoken through the UIKit framework.
The Accessibility Inspector in the iOS Simulator kind of sucks. If your accessibility settings are correct, it can tell you what is there. If you have a problem the Inspector does not provide you any information about what is wrong. This is true of the entire UIAccessibility API. It is so easy to use that it almost always works. But when it doesn't work you need to resort to hunt and peck to figure it out. The API needs some assertions or console messages similar to how Apple handles Constraint warnings. Spoiler alert: the Accessibility Inspector in Xcode 8 is wayyyyy better, but still would not have helped with my issue.
There is a ton of good information in the UIAccessibility.h header. If you are embarking on UIAccessibility support, it is a good read.

When to use didMoveToWindow method?

I have been searching around for this particular method:didMoveToWindow() however I haven't found any concrete information.
Could someone explain why and when should someone use this method and when is it called?
This method is called by iOS when a UIView is added to the Window object.
You are supposed to override it to make your app do something at the same that.
The default implementation of this method does nothing. Subclasses can
override it to perform additional actions whenever the window changes.
The window property may be nil by the time that this method is called,
indicating that the receiver does not currently reside in any window.
This occurs when the receiver has just been removed from its superview
or when the receiver has just been added to a superview that is not
attached to a window. Overrides of this method may choose to ignore
such cases if they are not of interest.
https://developer.apple.com/reference/uikit/uiview/1622527-didmovetowindow

Determining a visible part (frame) of UIView subclass, that is added as a subview to cell in table view

Let's call this UIView subclass - SomeClass. This SomeClass is a part of a static library. Some customer will use this library and will add instances of this SomeClass to the cells of his (customer's) table view.
I (SomeClass) need to determine when the SomeClass "enters" screen (will become visible), and when will "exit" screen (will become non-visible).
I can use didMoveToWindow: method and then check self.window for nil. BUT, there is a problem, SomeClass gets this event, before it is actually visible, because of cells "preparation" by table view concept. And I need to know for sure, it is 100% visible by some user.
One way to determine is by using scrollViewDidScroll:. Suppose SomeClass will get scroll view by using iteration on super views and will subscribe as a delegate to found scroll view. But he will be removed by some cell that will subscribe itself as a delegate to scroll view. So I need to invent here some solution for this. For example, in Android, there is possibility to add observer, in that case SomeClass is always a listener and is not overriding any other listener. There is many to one relation in Android, not like in iOS, one to one.
The other way, I can enable some timer in didMoveToWindow: when SomeClass becomes visible, that will check each X time, its frame. The timer will be disabled, when SomeClass will go from screen.
Probably there is a way to check at low level, without using scroll view and timer on some low-level redraw method. Is it possible?
So what is the best (will use less resources / good design) method?
You can use CGRectIntersectsRect to check if the cell's frame intersects with the frame of your custom view. Aside from that, didMoveToWindow is the method you are looking for.
If as you say the table view cell will always have SomeClass as a subview, then it would make more sense to use UITableViewDelegate tableView:willDisplayCell:forRowAtIndexPath:.

Not all UITextFields are calling all delegate methods

I've got a view controller xib file with several views in it. I'm building a wizard-type interface. I'm just doing a simple fade between the views, and I'm already using a navigation controller for the main interface. I'd prefer not to use one for this wizard. Anyway, in the views, each panel has at least a button, some sort of input field (usually a UITextField) and some helper text hard coded in a UILabel.
The problem is that not all the UITextField objects are calling the textFieldDidChange method in the delegate (File's Owner - .m file associated with the xib), but all the UITextField objects ARE calling the textFieldDidBeginEditing method.
Makes no sense to me. I feel like I must be missing something simple in how I set up the screens, but I'll be darned if I can figure it out. Each of the screens all look identical in the property sheets (on the right hand side of Xcode), and everything is wired up correctly in the File's Owner property sheet, both in IBOutlet and IBActions.
Here are some shots of what's going on...
Ideas? Thanks.
Here are links to the screen caps of the vital parts.
(being a new member is making it hard to add all the info I need with screen caps!)
As far as I now, there is no delegate method with the header textFieldDidChange. You have created a method of your own, which is depending on a NSNotification. Make sure all the UITextFields are send the right notification.
There is no such method on a UITextFieldDelegate
You may have confused textViewDidChange, which is a delegate method for a UITextView, but itis passed the UITextView that generated the event, not an NSNotification.
Seems like you want textField:shouldChangeCharactersInRange:replacementString: instead.
This is resolved. I'm a knucklehead. :-)
I was attaching my own notifier/observer and hadn't done so for the last few UITextField objects. Sorry to bother y'all.

Access first responder of MFMessageComposeViewController

I'm interested in doing something similar to this, however the component subviews of MFMessageComposeViewController are a much different than MFMailComposeViewController.
I figured out how to set focus to the input that let's you to type your message text by simply calling setRecipients: with an array containing a blank NSString. However, I'd like to paste non-text from the pasteBoard into the input, so I can't simply use setBody:.
Problem:
What I need to do is get a reference to the actual text field that is the current first responder for my MFMessageComposeViewController. This way, I have a "sender" I can pass to UIPasteboard's paste: method. The problem is, I can't seem to walk the subview hierarchy the same way as MFMailComposeViewController, so I can't find out which view is first responder.
I've even tried this, but the view is always returned as nil if I do a [myMessageVC.view findFirstResponder]
Word of caution, you're not supposed to have your hands inside that view. Apple will refuse your app for doing so. You are only allowed to set the body and recipients.
Important The message composition interface itself is not customizable
and must not be modified by your application. In addition, after
presenting the interface, your application is unable to make further
changes to the SMS content. The user can edit the content using the
interface, but programmatic changes are ignored. Thus, you must set
the values of content fields, if desired, before presenting the
interface
http://developer.apple.com/library/ios/#documentation/MessageUI/Reference/MFMessageComposeViewController_class/Reference/Reference.html

Resources