Swift press button function, press again for reverse - xcode

I've got a simple IBAction that performs a method (let's just say shows subview). When I press this button again I want to perform another method (hides subview).
I have done the coding for the show/hide. I have tried using a Boolean but am unsure of the syntax. I also tried using an if/else statement like this:
var doubleTap = false
if (doubleTap) {
//hide view
} else {
//show view
}
If someone could shed some light on this that'd be great!

change to code like below in the Button Press Method:
var doubleTap : Bool! = false
if (doubleTap) {
//Second Tap
doubleTap = false
} else {
//First Tap
doubleTap = true
}

A function which is doing this in one line:
var toggled = true
func toggle() {
toggled == true ? (toggled = false) : (toggled = true)
}
If you wanna let a button appear and disappear again this can be an approach:
import UIKit
class MyViewControllerClass : UIViewController {
var buttonActive : Bool = true {
didSet {
self.mySubView.hidden = !self.mySubView.hidden
}
}
func toggle() {
buttonActive == true ? (buttonActive = false) : (buttonActive = true)
}
}

Take a Global variable and intialize it to 1 and when it First time pressed intialize it to 1 in the function perform the task you want to do. Then if you presses it second time intialize it to 0 and then perform the other task

Related

NSTouchBar - how to combine default text filed items with custom items

I am trying to combine my custom touch bar items together with the automatic text suggestions in the touch bar while editing text field.
Currently i am overriding makeTouchBar in custom NSTextView class, if i wont do that, the default touch bar will be created for the textView.
This is the main makeTouchBar, where i try to add the suggestions with item identifier .candidateList, but no luck:
extension ViewController: NSTouchBarDelegate {
override func makeTouchBar() -> NSTouchBar? {
let touchBar = NSTouchBar()
touchBar.delegate = self
touchBar.customizationIdentifier = .myBar
touchBar.defaultItemIdentifiers = [.itemId1,
.flexibleSpace,
.itemId2,
.itemId3,
.flexibleSpace,
.candidateList]
touchBar.customizationAllowedItemIdentifiers = [.itemId1]
return touchBar
}
}
Can someone provide a simple example of how to add this words suggestions item to a custom touch bar?
Easy. Just call super in your custom NSTextView class:
override func makeTouchBar() -> NSTouchBar {
var touchBar = super.makeTouchBar()
touchBar.delegate = self
var defaultIdentifiers = [Any](arrayLiteral:touchBar.defaultItemIdentifiers)
defaultIdentifiers.insert("CustomLabel", at: 0)
touchBar.defaultItemIdentifiers = defaultIdentifiers
return touchBar
}
override func touchBar(_ touchBar: NSTouchBar, makeItemFor identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem {
if (identifier == "CustomLabel") {
var button = NSButton(title: "Custom", target: self, action: nil)
var item = NSCustomTouchBarItem(identifier: "CustomLabel")
item.view = button
item.customizationLabel = "Custom"
return item
}
else {
return super.touchBar(touchBar, makeItemFor: identifier)
}
return nil
}

NSPressGestureRecognizer called before minimumPressDuration

I need my NSButton to respond to regular clicks, as well as long presses. I am adding NSPressGestureRecognizer like so:
override func viewDidLoad() {
super.viewDidLoad()
let gr = NSPressGestureRecognizer()
gr.minimumPressDuration = 1
gr.action = #selector(handleLongPress)
button.addGestureRecognizer(gr)
}
func handleLongPress(gr: NSPressGestureRecognizer) {
if gr.state == .Began {
Swift.print("long press")
}
}
Unfortunately, the handleLongPress randomly fires even at short single clicks, or double clicks. It happens even if i set the minimumPressDuration to higher values.
I have tried playing with the shouldBeRequiredToFailByGestureRecognizer but it is not solving the problem.
Is there something i am missing with my code?
I have solved this by handling multiple gesture recognizers:
the class must implement NSGestureRecognizerDelegate
var singleClick:NSClickGestureRecognizer?
var longClick:NSPressGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
longClick = NSPressGestureRecognizer()
longClick!.minimumPressDuration = 1
longClick!.action = #selector(handleGestureLong)
longClick!.delegate = self
singleClick = NSClickGestureRecognizer()
singleClick?.numberOfClicksRequired = 1
singleClick!.action = #selector(handleGestureSingle)
singleClick!.delegate = self
btn.addGestureRecognizer(longClick!)
btn.addGestureRecognizer(singleClick!)
}
func gestureRecognizer(gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: NSGestureRecognizer) -> Bool {
if gestureRecognizer == singleClick && otherGestureRecognizer == longClick {
return false
}
return true
}
func handleGestureSingle(gr: NSClickGestureRecognizer) {
switch gr.state {
case .Ended:
print("single click")
break
default:
break
}
}
func handleGestureLong(gr: NSPressGestureRecognizer) {
switch gr.state {
case .Began:
print("long click")
break
default:
break
}
}

Where I should put code to customize Cancel button in UISearchBar?

I trying to change Cancel button color in UISearchBar implemented with UISearchController (iOS 8 and greater). This is a code I use:
if self.resultSearchController.active {
for subView in self.resultSearchController.searchBar.subviews {
for subsubView in subView.subviews {
if subsubView.isKindOfClass(UIButton) {
subsubView.tintColor = UIColor.whiteColor()
}
}
}
}
If I paste it in viewDidLoad, it doesn't work, cause I think Cancel button initialize only when SearchController becomes Active.
If I paste code in viewDidLayoutSubviews everything work great, but I'm not sure its a correct way.
So, where I should put this code in TableViewController?
Also, I don't understand, how I can receive notification in my TableViewController that SearchController becomes inactive. In other words where I should put code like this:
if self.resultSearchController.active == false {
//Do something
}
First you should insert delegate methods :-
class HomeViewController: UIViewController,UISearchResultsUpdating, UISearchBarDelegate {
var searchController: UISearchController!
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search here..."
searchController.searchBar.delegate = self
searchController.searchBar.sizeToFit()
searchController.hidesNavigationBarDuringPresentation = true
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.tintColor = UIColor.whiteColor()
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
}
}
then used delegate methods and change cancel button colors and thing what you want
You can try this in AppDelegate's didFinishLaunchWithOptions:.
UIBarButtonItem.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).tintColor = UIColor.whiteColor()
PS: This is a generic method and would affect UIBarButtonItem in UISearchBar across app.
Swift 4.2, 4.0+ An answer is added here for a custom search bar that can be customized as below,
You can check the usage of SearchBar class.

How to use NSWindowOcclusionState.Visible in Swift

I am trying to implement window toggling (something I've done many times in Objective-C), but now in Swift. It seams that I am getting the use of NSWindowOcclusionState.Visible incorrectly, but I really cannot see my problem. Only the line w.makeKeyAndOrderFront(self) is called after the initial window creation.
Any suggestions?
var fileArchiveListWindow: NSWindow? = nil
#IBAction func tougleFileArchiveList(sender: NSMenuItem) {
if let w = fileArchiveListWindow {
if w.occlusionState == NSWindowOcclusionState.Visible {
w.orderOut(self)
}
else {
w.makeKeyAndOrderFront(self)
}
}
else {
let sb = NSStoryboard(name: "FileArchiveOverview",bundle: nil)
let controller: FileArchiveOverviewWindowController = sb?.instantiateControllerWithIdentifier("FileArchiveOverviewController") as FileArchiveOverviewWindowController
fileArchiveListWindow = controller.window
fileArchiveListWindow?.makeKeyAndOrderFront(self)
}
}
Old question, but I just run into the same problem. Checking the occlusionState is done a bit differently in Swift using the AND binary operator:
if (window.occlusionState & NSWindowOcclusionState.Visible != nil) {
// visible
}
else {
// not visible
}
In recent SDKs, the NSWindowOcclusionState bitmask is imported into Swift as an OptionSet. You can use window.occlusionState.contains(.visible) to check if a window is visible or not (fully occluded).
Example:
observerToken = NotificationCenter.default.addObserver(forName: NSWindow.didChangeOcclusionStateNotification, object: window, queue: nil) { note in
let window = note.object as! NSWindow
if window.occlusionState.contains(.visible) {
// window at least partially visible, resume power-hungry calculations
} else {
// window completely occluded, throttle down timers, CPU, etc.
}
}

how to prevent user response during delay before the AI response

I am having trouble with being able to keep activating buttons before my AI response in a Tic Tac Toe game. As you can see I added a delay response, but I am still able to do another turn even before my AI responds. Anyone knows how to disable the first player turn until the AI has made its turn?
#IBOutlet var userMessage: UILabel!
struct Sender{
var tag = 1
}
var plays = Dictionary<Int,Int>()
var done = false
var aiDeciding = false
var sender: Sender = Sender()
#IBAction func UIButtonClicked(sender:UIButton) {
userMessage.hidden = true
if plays[sender.tag] == nil && !aiDeciding && !done {
setImageForSpot(sender.tag, player: 1)
}
checkForWin()
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
delay(0.4) {
self.aiTurn()
}
}
You can set enabled on any buttons to false or set userInteractionEnabeled on the entire view to false during AI "playback" to prevent the user from interacting with your interface.
Take your entire UIButtonClicked method and wrap it in an if clause to see if the AI is deciding:
#IBAction func UIButtonClicked(sender:UIButton) {
if (!aiDeciding) {
//all of your code
}
}

Resources