Tappable Dynamic Links With UILabel - ios

I am looking for a way, that does not involve a UITextView or 3rd party framework, to make multiple tappable links, on a label. A side note, with the string, for the label is, it’s fetched from a server, so we don’t know the links ahead of time.
As an example, lets say there’s a post, and it has two links, each to a random site dynamically fetched from the server. After detecting that they are links, which I can do, how would I make those tappable?
I have scoured StackOverflow, there have been no duplicates or this question, that I can find. If you find something exactly like this question, feel free to mark it as a duplicate. All I’ve seen were people recommending to use a UITextView, a 3rd party framework, or to use attributed strings, but the links are known at that point, they aren’t dynamically fetched.

As #DonMag pointed out, in the comments of the question - I could in fact use a UITextView, and disabling scrolling, which fixed the original reason I was having, that made me turn to do it with a UILabel.

If you would like to do it with a UILabel class then:
set 'isUserInteractionEnabled' property to true
create a Tap Gesture Recogniser and assign it to the gesture recognisers collection outlet of the label
write 'IBAction func didTapLink(_ sender: Any)' which opens a selected link and connect is with the tap gesture recogniser 'sent action selector' outlet
set 'text' property with a link
if you must to display a link as in a browser then:
set 'attributedText' property with a link
add 'NSAttributedString.Key.link' attribute to the link range

Related

Does setting a button's UIAccessibilityTrait remove the word "button" from it's accessibilityLabel?

I ran into a weird situation just now. I have a container view in our app which needs to read out all of the views when tapped, but only one view should be able to be accessed individually. Because some of the views are complex views with their own subviews, I setup my ADA logic to read the accessibilityLabel of a view if it has one, and if not, to build one from the subviews.
Well, today we had to add the word "button" to the help button when it's being read because the container view was tapped. So I simply added the word "button" to the label's accessibilityLabel and everything worked fine. Then I realized, this may change it to read "more information button button" when tapped individually, since I had set the accessibilityTraits property of the button to be UIAccessibilityTraitButton.
However, to my surprise, it read it correctly as "more information button." Does Apple detect extraneous "button's" in an accessibilityLabel and remove them when the trait is set to be a button? Would they also remove extraneous "label's" from a button when it's trait is set to be a label? I find this extremely cool, and incredible forethought on Apple's engineer's parts, if this is the way it works.
Edit: If this is the way it's done, could someone point me to where this is documented? I wasn't able to find it, although I'm currently still working on this fix so I didn't do the most in depth search I could have done.
I've had some time now to do some proper testing. VoiceOver will remove the extra labels if you set the traits properly. This allows for you to have the type read in a container view, and still set an accessibilityTraits.
So, for example, if you set the accessibilityTraits to UIAccessibilityTraitButton and the last word in your accessibilityLabel is button, it will remove the last word and only read button once. If, however, you set the accessibilityTraits to `UIAccessibilityTraitImage', it will not remove the button, and will end its reading with "button image". Changing the last word to "image", however, has it only read image once.
Pretty nice forethought on Apple's part with that implementation.

Prevent UISegmentedControl segment selection on focus on tvOS

I'm working on a simple UI on a tvOS app and I'm facing a strange problem.
When a UISegmentedControl get focused you can move your focus around and it automatically changes the selected segment. But what I'm looking for is a way to limit the segment selection only when the user taps the segment, not when he focused it.
Any idea?
Thanks in advance.
You need to have your own internal variable for the selected segment and only change its value when the select button is pressed (which you can get using a gesture recognizer). When the segment loses focus (detectable in didUpdateFocus function) you assign the value of your internal variable to the selected index of the segment control.
You need to subclass UISegmentedControl then override didUpdateFocusInContext. In the "Custom Class" field in IB use the name of your custom class.
You can subclass UISegmentedControl and disable the behavior by defining:
#objc func _selectFocusedSegment(){
print ("select focused segment")
}
Beware that this solution is a hack. As far as I know there is no good, clean way to accomplish what you want short of steering clear of UISegmentedControl.
Also know that when a UISegmentedControl 'changes focus' between segments, it does not actually change focus. So hooking into focus updates like Nostradamus is suggesting will not work. To the focus engine UISegmentedControl behaves like a single large focusable element, not like a group of focusable segments. You can see this for yourself by debug inspecting a UIFocusUpdateContext on focusing towards or away from a UISegmentedControl.
I stumbled onto _selectFocusedSegment by defining a UISegmentedControl subclass and debug logging the various NSObject.perform methods, among others. My intent was to reverse engineer how UISegmentedControl retains a sticky last focused item, which is quite difficult to do on Apple TV. I was not able to find out exactly how UISegmentedControl manages focus, but I was able to find the answer to your question along the way.

What makes an element accessible? And why are tap gestures less accessible than UIButtons? How do I fix it?

Brent Simmons wrote in a blog post that tap gesture recognizers, presumably on a UIView, are less accessible than UIButtons. I'm trying to learn my way around making my app accessible, and I was curious if anyone could clarify what makes that less accessible than a UIButton, and what makes an element "accessible" to begin with?
For more customizability I was planning to build a button comprised of a UIView and tap gesture recognizers with some subviews, but now I'm not so sure. Is it possible to make a UIView as accessible as a UIButton?
Accessible in this context most likely refers to UI elements that can be used using Apple's accessibility features, such as VoiceOver (see example below).
For example, a visually impaired person will not be able to see your view or subviews, or buttons for that matter; but the accessibility software "VoiceOver" built into every iOS device will read to her/him the kind of object and its title, something like "Button: Continue" (if the button title is "Continue").
You can see that most likely the tap gesture recognizer will not be read by VoiceOver and thus be less "accessible".

How to get Range value of text in a UITextView from tapped location?

I have a UITextView with some content of text. I need to get the exact range value of character/string from tapped location. I set TapGestureRecognizer for UITextView. In its action method i need to get the Range of tapped location. How its possible? I tested with some answers from Stackoverflow but they were not perfect. Thanks in advance.
Have you looked at the UITextView documentation?
https://developer.apple.com/library/ios/documentation/uikit/reference/uitextview_class/Reference/UITextView.html#//apple_ref/occ/instp/UITextView/selectedRange
You can use this selectedRange method to determine the range of text that is selected by the user.
Late edit: this was just recently downvoted, and gave me a chance to re-read my answer and I'd downvote my answer from 3 years ago too.
Updated answer:
If there is a single tap, the tap action itself should have the info you need. At the core here, you'll need the UITouch events themselves, such as to calculate where the touch occurred in relation to where your text should be. This will let you know what part of text was covered by the user's finger.
I'm honestly not sure if any 3rd party solutions exist for this, but I'd bet cocoapods.org would be a good place to start with keyword UITextView tap, if not Github itself with keywords: cocoapod uitextview.
If I were implementing such a solution, with UITouch events in hand, using the properties described in the docs I'd use The location of the touch within the view or window
given by the class.
By manipulating on one hand CGPoints from: https://developer.apple.com/documentation/uikit/uitouch/1618116-location, you can then use String mechanisms for determining size of text in your given font.
While this solution is for a UILabel, it can either:
(a) be used in a different way but hopefully quite similarly in a UITextView
OR
(b) I have seen a dummy UILabel get used simply to calculate text sizes in features requiring this kind of precision. This is usually quite effective, since changing the string of a UILabel isn't expensive and a UILabel has built in properties for size calculation based on text and font without needing to do a layout pass.
Again, apologies if the first original answer seemed sassy, it does come off that way I see now. I will confirm, though, that my original answer still stands (the selectedRange mechanism) SHOULD the desired solution be in terms of a long press. For a custom solution based on a single touch down event, though, collecting UITouch events through a delegate callback and then processing those with knowledge of what String is present is the best approach from what I can tell.

detect urls in UILabel

I have a Tableview and tableview cell is customized to have a UILabel. The text in UILabel is having URLs. Is there a way to detect urls like how UITextView will enable detect URLs so that user interaction should be able to load the urls.
If you just want to identify the URLs, you can use NSDataDetector with the NSTextCheckingTypeLink checking type.
If you want to draw the URLs differently, and you are targeting iOS 6, you can use an NSAttributedString to turn the URLs blue or underline them or whatever. If you're targeting an older version of iOS, you will probably want to look for some free code on the Internet to draw styled text, like OHAttributedLabel.
If you want to actually make the URLs touch-sensitive, you can add a tap gesture recognizer to the label and try to figure out which part of the string was tapped (somewhat complicated), or look for some free code on the Internet that already does it for you (like OHAttributedLabel), or just put a UITextView in the table view cell instead of a label.
as Rob point out how can we achieved the same is awesome.
But, we can use a tact so can save with issue of ios version (possibly), just by using a UILabel and UIButton.
What we need to do is that, either from IB or story-board,just place a UILabel with string as URL(use this as title), say;
"www.myURL.com"
Now, just above it, place a UIButton(button with custom type), and just use "______"(underline) and set this button as overlap your UILabel and also the 'underline' must be beneath your label.
Now, just do in action of button whatever you required as you need on the click of URL and here also you can change the textColor, etc, properties; also load URL and navigate to UIWebView.

Resources