Connecting multiple outlets to single action? - xcode

I'm creating a keyboard extension in XCode Beta 7 (Swift2).
I'm trying to connect multiple buttons to a single action.
However, when I connect all the button outlets to this action, it causes my keyboard to crash which makes me think there's something I'm missing.
#IBOutlet weak var Label: UIButton!
#IBAction func ButtonTapped(sender: AnyObject) {
Label.setTitle("Hello!", forState: .Normal)
Label.hidden = false
Label.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "hideLabel", userInfo: nil, repeats: false)
}
#objc func hideLabel() {
Label.hidden = true
Label.backgroundColor = UIColor.clearColor()
}

Attaching the same action to multiple buttons is not a problem, and is a common technique.
However, you have Label set as force-unwrapped, which will crash if it is nil.
My guess is that your Label outlet is not connected so Label is nil at runtime.
Change the type of Label from UIButton! to UIButton? and then change your code to use "if let" optional binding to only execute the code using Label if label is non-nil.
BTW, Swift has a strong naming convention. Variable names should start with a lower-case letter and use "camel case" for the rest of the variable name. Only class names and type names should start with a capital letter. So "Label" should be "label" instead. Get in the habit of following that style. It serves as a clear visual cue to you and others reading your code as to what type of thing a name refers to.
Finally, "Label" is a horrible name for a button. It's a button, not a UILabel. Call it "myButton" or something instead.
EDIT
The code might look like this:
#IBOutlet weak var myButton: UIButton?
#IBAction func ButtonTapped(sender: AnyObject)
{
println("myButton = \(myButton)") //See if myButton is nil
if let myButton = myButton
{
myButton.setTitle("Hello!", forState: .Normal)
myButton.hidden = false
myButton.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)
NSTimer.scheduledTimerWithTimeInterval(2, target: self,
selector: "hidemyButton",
userInfo: nil, repeats: false)
}
}
#objc func hidemyButton()
{
myButton.hidden = true
myButton.backgroundColor = UIColor.clearColor()
}

Related

Trying to get a UITextView to move content when keyboard is placed over top of itself

I have a UITextView
#IBOutlet weak var note: UITextView!
note.delegate = self
The text view is inside of a UIScrolLView
#IBOutlet weak var scrollView: UIScrollView!
That I am trying to get to respond to this:
// move the scrollView when the keyboard is presented
NotificationCenter.default.addObserver(self, selector: #selector(Keyboard), name: Notification.Name.UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(Keyboard), name: Notification.Name.UIKeyboardWillChangeFrame, object: nil)
that when pressed called this function:
#objc func adjustForKeyboard(_ notification: Notification) {
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
if notification.name == NSNotification.Name.UIKeyboardWillHide {
scrollView.contentInset = UIEdgeInsets.zero
} else {
scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
}
scrollView.scrollIndicatorInsets = scrollView.contentInset
}
What I want to happen is when you tap on the UITextView, if the keyboard is going to hide the text view, the content is scrolled up, so that the TextView is always visible. This method works just fine for my UITextFields, but it's not working for the UITextView.
Followed this tutorial, and still not working for me. I'm not sure if he is using UITextView or UITextFields in the video, I think Fields.
OW TO AUTO ADJUST UISCROLLVIEW WHEN KEYBOARD IS UP (SWIFT-4, XCODE-9)
How to adjust a UIScrollView to fit the keyboard

How can I show the marked text from one textfield as marked text in other textfield in Xcode, swift 2

I have two textfield having two texts in my OS X program. I would like to have the following effect. When I marked part of text in one textfield I would like to have the identical marked part of the text in other textfield. How can I implement this in xcode and using swift 2?
You can create two TextViews (note: class NSTextView not NSTextField) and connect them to a view controller using outlets. Again, connect the innermost TextView, not the clip view or bordered scroll view. In the example below "searchView" is the one that contains the text you select, and "textView" the one which contains the text you want to highlight.
Then, you can do something like this (note that I tested this in Swift 1.2)
class ViewController: NSViewController {
#IBOutlet var textView: NSTextView!
#IBOutlet var searchView: NSTextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "selectedSomeText:", name: NSTextViewDidChangeSelectionNotification, object: searchView)
}
#objc func selectedSomeText(notification: NSNotification) {
let selectedRange = searchView.selectedRange()
if selectedRange.length > 0 {
let nsString = searchView.string! as NSString
let selectedString = nsString.substringWithRange(selectedRange)
let regex = NSRegularExpression(pattern: selectedString, options: nil, error: nil)
let foundRanges = regex?.matchesInString(textView.string!, options: nil, range: NSRange(location: 0, length: count(textView.string!)))
let firstFound = foundRanges![0] as! NSTextCheckingResult
textView.showFindIndicatorForRange(firstFound.range)
}
}
}
This will highlight the first found match. You can then implement buttons or something to iterate though matches (for example, by storing "foundRanges" somewhere and iterate its index using buttons, etc). You might also want to implement some error checking and/or optional chaining because all those nils and forced downcasts in my example might cause crashes.

Swift: Display images linked to a timer and slider

I'm new to programming and very new to Swift so am in need of help please.
I want to create a view where images will appear and then disappear from the screen at a specific time. The time will be indicated by a label and also a slider. For example, When 5 seconds is indicated on the the label the image will appear, After 10 seconds on the label, the image will disappear. After 15 seconds another image will appear and so on. This would continue for 60 seconds. This time label would also be connected to the slider. I would like to do this completely in code if possible
Any suggestions as to an efficient way to achieve this would be very much appreciated.
You can use an UIImageView, UILabel, UISlider and NSTimer to achieve this. Make sure you keep the NSTimer instance as a member variable in your ViewController
For example, your viewDidAppear would start the NSTimer with the default interval (lets say 5 seconds):
Your ViewController would look something like this:
import UIKit
class MyViewController : UIViewController
{
// Connect these outlets via InterfaceBuilder
#IBOutlet weak var imageView : UIImageView!
#IBOutlet weak var label : UILabel!
#IBOutlet weak var slider : UISlider!
var timer : NSTimer!
override func viewDidLoad()
{
super.viewDidLoad()
slider.addTarget(self, action: Selector("sliderValueChanged"), forControlEvents: .ValueChanged)
}
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
self.startTimerWithInterval(5)
}
func sliderValueChanged()
{
let newValue = slider.value
self.startTimerWithInterval(NSTimeInterval(newValue))
}
func timerDidFire()
{
// Do something with the imageView
}
private func startTimerWithInterval(seconds: NSTimeInterval)
{
if self.timer != nil { self.timer.invalidate() }
self.timer = NSTimer(timeInterval: seconds, target: self, selector: Selector("timerDidFire"), userInfo: nil, repeats: true)
}
}

Trigger Segue Artificially

I am trying to pass data between two viewContollers in an OS X storyboard application using Swift. When I press a button on VC1, it opens VC2, and prepareForSegue is run. However, I can't pass data back to VC1 because a. prepareForSegue isn't being run (because a window isn't being opened) and b. because even if it were, VC1 doesn't know data is being sent and I can't figure out a function (something like viewDidBecomeFocus, if such a function existed) to let it know to look. I feel like there must be a way to do this.
If you know of a way to do this in IOS but not OSX, it could still be useful.
Thanks!
Let assume that in your first ViewController you have one label and one button. When pressed, that button open popover (SecondViewController) with one textfield (and one button what says ready or close etc.), where you want take its value and assign it to your label. That is where delegates and protocols come handy.
SecondViewController:
#objc protocol TextDelegate {
func passedString(textValue: String)
}
class SecondViewController: NSViewController {
#IBOutlet weak var textField: NSTextField!
weak var delegate: TextDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
#IBAction func closePopOver(sender: AnyObject) {
if delegate != nil {
delegate!.passedString(textField.stringValue)
}
self.dismissViewController(self)
}
}
This is ViewController:
#IBOutlet weak var myLabel: NSTextField!
override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mySegue" {
let vc = segue.destinationController as! SecondViewController
vc.delegate = self
}
}
func passedString(textValue: String) {
myLabel.stringValue = textValue
}

Extra argument 'selector' in call

I'm trying to create a simple stopwatch app where the timer label increments when the startButton button is pressed. This is what I have:
#IBOutlet weak var timer: UILabel!
#IBAction func startButton(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(0.0025, target: self, selector: Selector("result"), userInfo: nil, repeats: true)
}
var count = 0
func result() {
count++
timer.text=String(count)
}
I get the error "Extra argument 'selector' in call" but can't workout the syntax to do it properly.
Swift error messages are a little lacking at times. It should have said something like "NSTimer is not convertible to UILabel". You are assigning the timer you create to your IBOutlet timer which is a UILabel. The timer is an NSTimer. Just assign it to a different variable when you create it and all will be fine.
#IBAction func startButton(sender: AnyObject) {
let myTimer = NSTimer.scheduledTimerWithTimeInterval(0.0025, target: self, selector: "result", userInfo: nil, repeats: true)
}
As a shortcut, you can just use a string as a selector, so Selector("result") can be replaced by just "result".

Resources