I see somewhere this code for highlight selected text in pdf document:
let select = pdfView.currentSelection?.selectionsByLine()
//assuming for single-page pdf.
guard let page = select?.first?.pages.first else { return }
select?.forEach({ selection in
let highlight = PDFAnnotation(bounds: select.bounds(for: page), forType: .highlight, withProperties: nil)
highlight.endLineStyle = .square
highlight.color = UIColor.orange.withAlphaComponent(0.5)
page.addAnnotation(highlight)
})
for me ,
let select = pdfView.currentSelection?.selectionsByLine()
is always giving nil. where to put this code. I putting it in Gesture Recogniser Delegate methods.
Also it seems adding multiple annotation on page. Do we get single highlight annotation per selection on a page?
I need help to set text in searchBar of GMSAutocompleteViewController when open in my App. I am using GMSAutocompleteViewController in Google Place AutocompleteViewController.
I got a working solution by combining #Youngjin and #Exception's answers for Swift 4 and Google Places 2.6.0
To access the GMSAutocompleteViewController searchbar:
let views = gmsAutoCompleteViewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
Then to set the text and also search automatically:
searchBar.text = "Your address"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "Your address") // This performs the automatic searching.
I found that I received a EXC_BAD_ACCESS error when attempting to set the text from within
didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController).
So I instead put this code in the completion block where I present the autoCompleteController, which works without issue.
Combining it all together:
let gmsAutoCompleteViewController = GMSAutocompleteViewController()
gmsAutoCompleteViewController.delegate = self
present(gmsAutoCompleteViewController, animated: true) {
let views = gmsAutoCompleteViewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
searchBar.text = "Your address"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "Your address")
}
EDIT: I found that this solution only seems to work on iOS 11.
let searchBar = subOfContentView[0] as! UISearchBar
will fail on iOS 10, and possibly lower versions.
#Cools
In Swift 3, it seems to have different hierarchy. I've digged into VC and got the place.
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
let views = viewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
searchBar.text = "YOUR_TEXT"
}
However, it has one fault that it does not search automatically. After I'v e got the solution, I will edit again.
Well, I don't necessarily recommend this course of action because if you want more control you should use the UISearchResults Controller. However, here's a swifty-er version:
//Where viewController is the GMSAutocompleteViewController
if let searchBar = (viewController.view.subviews
.flatMap { $0.subviews }
.flatMap { $0.subviews }
.flatMap { $0.subviews }
.filter { $0 == $0 as? UISearchBar}).first as? UISearchBar {
searchBar.text = "YOUR_TEXT_HERE"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "YOUR_TEXT_HERE") // to get the autoComplete Response
}
The benefit of this approach is that you don't have to know exactly where the SearchBar is located. It's basically trying to flatten all the subviews into one array and filter out the SearchBar from the array. If Google decides to change up where the SearchBar is hidden, this approach may still find it. The problem is that you still need to know how many levels of subviews there are. There may be a recursive function that you could set up to deal with this.
I have found out that solutions here are not working for iOS 10. So I have written recursive method for finding concrete view - UISearchBar, in our case:
extension UIView {
func getViewWithConcreteType<T: UIView>()-> T? {
if let concreteSubview = self as? T {
return concreteSubview
}
for subview in subviews {
let concreteView: T? = subview.getViewWithConcreteType()
if concreteView != nil {
return concreteView!
}
}
return nil
}
}
Made some modification to original solution:
let views = autocompleteController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
if let searchBar = subOfContentView[0] as? UISearchBar {
searchBar.text = text
searchBar.delegate?.searchBar?(searchBar, textDidChange: text)
} else {
let searchBar: UISearchBar? = autocompleteController.view.getViewWithConcreteType()
searchBar?.text = text
searchBar.map { $0.delegate?.searchBar?($0, textDidChange: text) }
}
You can inject text in this search bar using something like
func injectTextInSearchView(_ text: String, _ view: UIView) {
if let view = view as? UISearchBar {
view.text = text
view.delegate?.searchBar!(view, textDidChange: text)
return
}
for subview in view.subviews {
injectTextInSearchView(text, subview)
}
}
- (void)viewDidLoad {
[super viewDidLoad];
acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
}
- (IBAction)btnSearch1:(id)sender {
[self presentViewController:acController animated:YES completion:nil];
}
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
UIView *Views = viewController.view;
NSArray *Aar2 = [[Views subviews][0] subviews];
UIView *View2 = Aar2[1];
UIView *View3 = [View2 subviews][2];
UISearchBar *Search = [[View3 subviews] firstObject];
Search.text = #"Your text";
[Search.delegate searchBar:Search textDidChange:txtAddress.text];
}
// Cools enjoy man
I'm not very familiar with swift coding but based from the documentation - Customize text and background colors:
You can set the colors of all text and backgrounds in the autocomplete UI control, to make the widget match the visual appearance of your app more closely. There are two ways to set the UI control colors:
By using the native iOS UIAppearance protocol to globally style UI controls where possible. These settings apply to many, but not all, of the UI control elements.
By using the SDK methods on the widget classes to set properties which are not supported by the UIAppearance protocol.
The documentation states Search Bar text color, Search bar tint color and Search bar placeholder text color (default search text) can be styled using (UIAppearance protocol or SDK method).
Hope this info helps.
typedef void (^TTSearchBarHandler)(UISearchBar * searchbar);
__weak UIViewController *weaks = self;
[self searchSubviews:viewController.view completion:^(UISearchBar *searchbar) {
if(searchbar){
[searchbar.delegate searchBar:searchbar textDidChange:#"Your Text"];
}
}];
-(void)searchSubviews:(UIView*)view completion:(TTSearchBarHandler)completion{
if([view isKindOfClass:[UISearchBar class]]){
UISearchBar *searchBar = (UISearchBar*)view;
if(completion){
completion(searchBar);
}
}
else{
for(UIView * subview in view.subviews){
[self searchSubviews:subview completion:^(UISearchBar *searchbar) {
if(completion){
completion(searchbar);
}
}];
}
}
}
I created a NSStatusBarItem and popUp a (programmatically generated) NSMenu on right click:
let statusBarItem = NSStatusBar.system().statusItem(withLength: -1)
statusBarItem.action = #selector(AppDelegate.statusBarItemAction(sender:))
let menu = NSMenu()
var menuItem = NSMenuItem()
menuItem.action = #selector(AppDelegate.customItemAction)
menu.addItem(menuItem)
func statusBarItemAction(sender: NSStatusItem) {
let mouseEvent = NSEvent.pressedMouseButtons()
if mouseEvent == 2 {
// right click
lxStatusBarItem.popUpMenu(menu)
}
}
func customItemAction() {
// do something
}
Everything works fine, except that the statusBarItem remains highlighted after customItemAction is called:
How can I solve this?
I found that setting statusItem.button?.isHighlighted = false helped with removing the highlight. In your case, this would look like this:
func customItemAction() {
// do something
statusBarItem.button?.isHighlighted = false
...
}
I created a UIBarButtonItem programmatically and the text is underlined. Is there a way to remove the underline?
let editButton = UIButton.init(type: .Custom)
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.title = "General Information"
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
editButton.addTarget(self, action: #selector(editButtonPressed(_:)), forControlEvents: .TouchUpInside)
editButton.frame.size = CGSize(width: 60, height: 30)
editButton.titleLabel?.adjustsFontSizeToFitWidth = true
let barButtonItem = UIBarButtonItem.init(customView: editButton)
self.tabBarController?.navigationItem.setRightBarButtonItem(barButtonItem, animated: true)
updateEditButtonTitle()
self.navigationController!.navigationItem.backBarButtonItem?.tintColor = UIColor.blackColor()
}
here is an image of the result I get, with the underline.
here is the function where I set the button's text. when it is pressed, it becomes a save button.
func updateEditButtonTitle() {
if let button = self.tabBarController?.navigationItem.rightBarButtonItem?.customView as? UIButton {
var title = ""
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
editButton.layer.cornerRadius = 7.0
if isInEditMode {
title = "Save"
editButton.setTitleColor(UIColor.redColor(), forState: .Normal)
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.5)
editButton.layer.cornerRadius = 7.0
editButton.frame.size = CGSize(width: 60, height: 30)
} else {
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
title = "Edit"
}
button.setTitle(title, forState: .Normal)
}
}
Try this code ..
var attrStr: NSMutableAttributedString = yourBtnHere.attributedTitleForState(.Normal).mutableCopy()
//or whatever the state you want
attrStr.enumerateAttributesInRange(NSMakeRange(0, attrStr.characters.count), options: .LongestEffectiveRangeNotRequired, usingBlock: {(attributes: [NSObject : AnyObject], range: NSRange, stop: Bool) -> Void in
var mutableAttributes: [NSObject : AnyObject] = [NSObject : AnyObject](dictionary: attributes)
mutableAttributes.removeObjectForKey(.AttributeName)
attrStr.setAttributes(mutableAttributes, range: range)
})
With the inspector/IB: Select your UIButton.
Show the Attributes Inspector.
The Text settings should be in Attributed. Select the text, click on the fond item remove the Underlining setting it at none.
enter image description here
But..
Let me get this straight. Apple added an accessibility feature that lets users mark buttons with underlines if they want to.
You want a way to defeat this feature, specifically designed to help people with handicaps use their devices, when the feature is something that the user has to ask for.
Why?
It is very likely not possible using standard buttons. If you did figure out a way to do it, Apple would likely reject your app because it defeats a system function meant to help the disabled.
So the answer is: Don't do that.
I'm building a NSStatusBar app and want to call different functions depending on if the user clicked left- or right on the icon.
Here is what I have so far:
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
func applicationDidFinishLaunching(aNotification: NSNotification) {
let icon = NSImage(named: "statusIcon")
icon?.setTemplate(true)
statusItem.image = icon
statusItem.menu = statusMenu
}
With this it shows up the statusMenu by every click. How can I distinguish the mouseEvents?
This snippet
func menuSelected (sender:AnyObject) {
var clickMask: Int = 0
if let clickEvent = NSApp.currentEvent! { // see what caused calling of the menu action
// modifierFlags contains a number with bits set for various modifier keys
// ControlKeyMask is the enum for the Ctrl key
// use logical and with the raw values to find if the bit is set in modifierFlags
clickMask = Int(clickEvent.modifierFlags.rawValue) & Int(NSEventModifierFlags.ControlKeyMask.rawValue)
}
if clickMask != 0 { ... } // click with Ctrl pressed
}
from my code checks for a ctrl-click. It's place in the method that is called from a menu item like this:
let item = NSMenuItem(title: title, action: Selector("menuSelected:"), keyEquivalent: "")