Swift - call #IBAction method in viewDidLoad without parameter - swift

#IBAction func getNewPhotoAction(sender: AnyObject) {
println("getNewPhotoAction")
}
override func viewDidLoad() {
super.viewDidLoad()
self.getNewPhotoAction(sender: AnyObject) // Error
}
I just want to call the getNewPhotoAction IBAction method in viewDidLoad.
Which parameter to enter in this line -> self.getNewPhotoAction(?????) ?
I don't have any parameter. I just need to call.
I used in Objective-C style:
[self getNewPhotoAction:nil]
but I don't know Swift style.

The parameter sender indicates who are calling the action method.
When calling from viewDidLoad, just pass self to it.
override func viewDidLoad() {
super.viewDidLoad()
getNewPhotoAction(self)
}
By the way, if the sender parameter of the getNewPhotoAction method wasn’t used, the parameter name can be omitted.
#IBAction func getNewPhotoAction(AnyObject) {
println("getNewPhotoAction")
}

You could always create a separate func that you call on in your viewDidLoad or in your IBAction
override func viewDidLoad() {
super.viewDidLoad()
self.getNewPhoto()
}
func getNewPhoto(){
//do whatever you want here.
println("getnewphotoaction")
println("whatever you want")
}
#IBAction func getNewPhotoAction(sender: AnyObject) {
self.getNewPhoto()
}

Swift 4.2
#IBAction func getNewPhotoAction(sender: Any) {
println("getNewPhotoAction")
}
override func viewDidLoad() {
super.viewDidLoad()
self.getNewPhotoAction(AnyObject.self)
}

If you still need to reference the UIButton or whatever is sending the action and want to call it from code at the same time - you can do this too:
onNext(UIButton())
Wasteful, but less code.

#IBAction func getNewPhotoAction(sender: AnyObject?){
......
}
**AnyObject** means that you have to pass kind of Object which you are using, nil is not a AnyObject.
But **AnyObject?**, that is to say AnyObject is Optional, nil is a valid value.
meaning the absence of a object.
self .getNewPhotoAction(nil)

You actually don't need to pass any object at all. If you have no need to use the sender, then declare the function without it like this:
#IBAction func getNewPhotoAction() { ... }
And use it like this:
self.getNewPhotoAction()
You may need to re-connect the outlet in interface builder when you make this change (remove it and then add it back) if this method is connected to an event in interface builder.

#IBAction func getNewPhotoAction(sender: AnyObject? = nil) {
print("getNewPhotoAction")
}
override func viewDidLoad() {
super.viewDidLoad()
self.getNewPhotoAction(nil)
}

Since you don't have any sender, hand over nil.
self.getNewPhotoAction(nil)

Related

window.windowController is nil inside windowWillClose() but it isn't inside viewDidAppear()

I've tried, without success, respond to events such as windowWillClose() and windowShouldClose() inside NSWindowController (yes conforming to NSWindowDelegate).
Later, to my surprise, I was able to receive those events if I make my contentViewController (NSViewController) conform to NSWindowDelegate.
Unfortunately, later on, found out that view.window?.windowController is nil inside windowWillClose() or windowShouldClose(), code:
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
self.view.window?.windowController // not nil!
}
func windowWillClose(_ notification: Notification) {
self.view.window?.windowController // nil!!
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
self.view.window?.windowController // nil!!
return true
}
After realizing that view.window?.windowController is not nil inside viewDidAppear() the next thing I thought was that Swift garbage collected the controller, so I changed viewDidAppear() in a way that creates another reference of windowController thus preventing garbage collection on said object, code:
var windowController: NSWindowController?
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
windowController = view.window?.windowController
}
func windowWillClose(_ notification: Notification) {
self.view.window?.windowController // NOT nil
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
self.view.window?.windowController // NOT nil
return true
}
My hypothesis turned out to be correct (I think).
Is this the same issue that is preventing me from receiving those events inside NSWindowController?
Is there another way I can achieve the same thing without creating more object references?
In order to post code, I use the Answer option even though it is more of a comment.
I added in NSViewController:
override func viewDidAppear() {
super.viewDidAppear()
parentWindowController = self.view.window!.windowController
self.view.window!.delegate = self.view.window!.windowController as! S1W2WC. // The NSWC class, which conforms to NSWindowDelegate
print(#function, "windowController", self.view.window!, self.view.window!.windowController)
}
I get print log:
viewDidAppear() windowController Optional()
and notification is passed.
But if I change to
override func viewDidAppear() {
super.viewDidAppear()
// parentWindowController = self.view.window!.windowController
self.view.window!.delegate = self.view.window!.windowController as! S1W2WC
print(#function, "windowController", self.view.window!, self.view.window!.windowController)
}
by commenting out parentWindowController, notification don't go anymore to the WindowController…
Edited: I declared in ViewController:
var parentWindowController: NSWindowController? // Helps keep a reference to the controller
The proposed solutions are, in my opinion, hacks that can cause serious problems with memory management by creating circular references. You definitely can make instances of NSWindowController work as the window’s delegate. The proper way is to wire it up correctly in either code or in Interface Builder in Xcode. An example of how to do it properly is offered here.
If the delegate methods are not called is because the wiring up is not done correctly.
Another thing that must be done in Swift is when you add the name of the NSWindowController subclass in Interface Builder in Xcode is to check the checkbox of Inherits from Module. If you fail to do this, none of your subclass methods will be called.

How To Use UserDefaults with Bool (Swift) [duplicate]

I'm trying to save a bool value to UserDefaults from a UISwitch, and retrieve it in another view. However, I've tried following multiple tutorials and stack answers and none seem to work.
This is how I'm saving it:
class SettingsViewController: UITableViewController {
#IBOutlet weak var soundSwitchOutlet: UISwitch!
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
and this is how I'm trying to retrieve it in another view:
if let savedValue = UserDefaults.standard.bool(forKey: "sound") {
boolValue = savedValue
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
For a reason this code is giving me errors and none of the things I've tried have worked. How can I save a bool to UserDefaults and retrieve it in another view?
Edit: I think I fixed the first part. However, the way I'm retrieving the boolean seems to be totally wrong. Also: No other stackExchange answer responds to what I'm asking, at least not in swift.
As Leo mentioned in the comments bool(forKey returns a non-optional Bool. If the key does not exist false is returned.
So it's simply
boolValue = UserDefaults.standard.bool(forKey: "sound")
Calling synchronize() as suggested in other answers is not needed. The framework updates the user defaults database periodically.
Do it like this.
In your first view controller.
create an IBoutlet connection to your UISwitch
And then the action for your UISwitch. so in the end, your first view controller should look like this.
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var myswitch: UISwitch! // Outlet connection to your UISwitch (just control+ drag it to your controller)
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func myswitchAction(_ sender: Any) { // Action for your UISwitch
var myswitctBool : Bool = false // create a local variable that holds your bool value. assume that in the beginning your switch is offed and the boolean value is `false`
if myswitch.isOn == true { // when user turn it on then set the value to `true`
myswitctBool = true
}
else { // else set the value to false
myswitctBool = false
}
// finally set the value to user default like this
UserDefaults.standard.set(myswitctBool, forKey: "mySwitch")
//UserDefaults.standard.synchronize() - this is not necessary with iOS 8 and later.
}
}
End of the first view controller
Now in your second view controller
you can get the value of userdefault, which you set in first view controller. I put it in the viewdidload method to show you how it works.
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myswitchBoolValuefromFirstVc : Bool = UserDefaults.standard.bool(forKey: "mySwitch")// this is how you retrieve the bool value
// to see the value, just print those with conditions. you can use those for your things.
if myswitchBoolValuefromFirstVc == true {
print("true")
}
else {
print("false")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Hope this will help to you. good luck
Use this line of code:
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
insteadof :
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet, forKey: "sound")
}
Try this:
#IBAction func soundSwitchs(_ sender: Any)
{
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
UserDefaults.standard.synchronize()
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
boolValue = UserDefaults.standard.bool(forKey: "sound")

How to call extension methods in overrideViewDidLoad in swift

I have the following code:
extension ViewController {
func AddLeftGesture(){
let SwipeLeft:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyDismissOnSwipeLeft))
self.view.addGestureRecognizer(SwipeLeft)
}
func MyDismissOnSwipeLeft(){
self.dismiss(animated: true, completion: nil)
}
and What I would like to accomplish is that override the viewDidLoad and
call AddLeftGesture method so that it'll be part of each VC I make
and I don't have to type it again and again in each viewDidLoad,
is this possible? or do you guys have any other suggestions?
well I don't think it's a good idea, because typically viewDidLoad is used for setting most properties and if you would like to override it in a view controller you should write it again.What I can suggest is that to make a base ViewController and add this code in the viewDidLoad of that and then subclass every viewController from the base view controller , This way whenever you want to change anything you just call super.viewDidLoad
class BaseViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
addLeftGesture()
}
}
class CustomViewController: BaseViewController{
}
Make this class which inherits UITapGestureRecognizer
open class BlockTap: UITapGestureRecognizer {
fileprivate var tapAction: ((UITapGestureRecognizer) -> Void)?
public override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
}
public convenience init (
tapCount: Int = 1,
fingerCount: Int = 1,
action: ((UITapGestureRecognizer) -> Void)?) {
self.init()
self.numberOfTapsRequired = tapCount
#if os(iOS)
self.numberOfTouchesRequired = fingerCount
#endif
self.tapAction = action
self.addTarget(self, action: #selector(BlockTap.didTap(_:)))
}
open func didTap (_ tap: UITapGestureRecognizer) {
tapAction? (tap)
}
}
then make an extension of UIView
extension UIView {
public func addTapGesture(tapNumber: Int = 1, action: ((UITapGestureRecognizer) -> ())?) {
let tap = BlockTap(tapCount: tapNumber, fingerCount: 1, action: action)
addGestureRecognizer(tap)
isUserInteractionEnabled = true
}
}
Then You can use this as
override func viewDidLoad() {
super.viewDidLoad()
self.view.addTapGesture(action: {[unowned self] (_) in
//Do whatever on click of View
})
}
Hope it helps!
There's two options AFAIK. Either you can subclass UIViewController and then make all of your controllers inherit from the subclassed one, or you can swizzle UIViewController's viewDidLoad().
I personally would choose swizzling, although it has one disadvantage - it hides the implementation and might be confusing for a new developer coming onto a project. So make sure you document this properly, somewhere in your project README and in the code as well.
Now for some code examples:
Subclassing UIViewController
MyViewController.swift
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
addGesture()
}
func addGesture() {
// Do what you need
}
}
class OtherViewController: MyViewController {
// Automatically will add gesture because it's a subclass of MyViewController
}
Swizzling viewDidLoad
What method swizzling does is, that it exchanges implementations of your methods. That simply means that the name of your function points at code from a different function. For more information on this topic read this article.
UIViewController+Swizzle.swift
static func swizzle(selector originalSelector: Selector,
with newSelector: Selector,
on targetClass: AnyClass) {
let originalMethod = class_getInstanceMethod(targetClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(targetClass, newSelector)
// If we were able to add the swizzled function, replace methods.
// Otherwise exchange implementations if method already exists.
if class_addMethod(targetClass, originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)) {
class_replaceMethod(targetClass, newSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
extension UIViewController {
// This function is getting called automatically by the runtime,
// when this class is loaded to perform some additional intiialization.
// However, this has now been deprecated in Swift, so only option is to
// declare a static function which you need to remember to call from
// somewhere, preferably early in your app initialization, like your
// didFinishLaunching function in AppDelegate or even AppDelegate's init
// function. I kept the initialize function in the code as a reference,
// however you would probably want to write it like in the comment
// below, to silence the warning.
//
// class func swizzle()
//
open override class func initialize() {
if self != UIViewController.self { return }
let swizzlingClosure: () = {
swizzle(selector: #selector(UIViewController.viewDidLoad),
with: #selector(UIViewController.swizzled_viewDidLoad),
on: UIViewController.self)
}()
swizzlingClosure
}
#objc private func swizzled_viewDidLoad() {
// Calls the original implementation,
// because implementations are switched.
swizzled_viewWillAppear(animated)
// Do whatever you need
addGesture()
}
#objc func addGesture() {
// Add your gesture
}
}

windowShouldClose reporting unresolved identifier

I'm trying to trigger a save of my CoreData on a window close as its only a single window application.
I've got the following code in my viewDidLoad and viewDidAppear
override func viewDidLoad() {
super.viewDidLoad()
if windowShouldClose(self) {
saveValues()
}
}
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
}
however im still getting the following error
Use of unresolved identifier 'windowShouldClose'
Any advice as to why i'm still getting this error after declaring the window delegate as self?
Set the delegate in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.view.window?.delegate = self
}
and implement the delegate method
func windowWillClose(notification: NSNotification) {
saveValues()
}
windowShouldClose is different. It asks for permission to close the window and expects a boolean return value.

How to use requestSupplementaryLexiconWithCompletion

I am not sure as to how to use the requestSupplementaryLexiconWithCompletion as outlined on the Apple Developer site here.
I have the following function
override func requestSupplementaryLexiconWithCompletion(completionHandler: ((UILexicon!) -> Void)!) {
appleLexicon = UILexicon
}
I am just lost as how to get a the UILexicon, then look at the pair values returned. E.g print them to the console to see its output.
You can try to use it like:
func handler(lexicon: UILexicon!) {
println(lexicon.description)
}
#IBAction func click(sender: AnyObject) {
let controller = UIInputViewController()
controller.requestSupplementaryLexiconWithCompletion(handler)
}
Or like:
#IBAction func click(sender: AnyObject) {
let controller = UIInputViewController()
controller.requestSupplementaryLexiconWithCompletion({
lexicon in
println(lexicon.description)
})
}
click method is just a UIButton tap event handler