How use SFAuthorizationView in a swift project. I already tried by creating a bridging header and imported SecurityInterface/SFAuthorizationView.h . My code is given below.
My reference -https://github.com/dominikhofacker/SFAuthorizationView.
The Authorization View and lock icon appeared on my output screen. But when i click on the lock button nothing happens.
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var auth: SFAuthorizationView!
#IBOutlet weak var button: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var items = [ AuthorizationItem(name: kAuthorizationRuleIsAdmin, valueLength: 0, value: nil, flags: 0), ]
var rights = AuthorizationRights(count: UInt32(items.count), items: &items)
auth.setAuthorizationRights(&rights)
auth.setDelegate(self)
auth.updateStatus(nil)
button.isEnabled = isUnlocked()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func isUnlocked() -> Bool {
return auth.authorizationState() == SFAuthorizationViewUnlockedState;
}
override func authorizationViewDidAuthorize(_ view: SFAuthorizationView!) {
button.isEnabled = isUnlocked()
}
override func authorizationViewDidDeauthorize(_ view: SFAuthorizationView!) {
button.isEnabled = isUnlocked()
}
#IBAction func button(_ sender: Any) {
print("hihi")
}
}
Seems like you just forgot to disable sandbox mode at Capabilities tab of your project target
Related
I am using Xcode 10.1 two create a simple single window application. The issue is that I see two windows instantiated when I run it instead of the single one I expect. Here is my code
//AppDelegate
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var mainWindowController: WindowController!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
print("loading")
let mainWindowController = WindowController()
mainWindowController.showWindow(self)
self.mainWindowController = mainWindowController
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
print("closed")
}
}
//WindowController.swift
import Cocoa
class WindowController: NSWindowController, NSSpeechSynthesizerDelegate {
#IBOutlet weak var textField: NSTextField!
#IBOutlet weak var speakButton: NSButton!
#IBOutlet weak var stopButton: NSButton!
override var windowNibName: String {
return "Window"
}
let speechSynth = NSSpeechSynthesizer()
var isStarted: Bool = false {
didSet {
updateButtons()
}
}
override func windowDidLoad() {
super.windowDidLoad()
viewDidLoad()
}
func viewDidLoad() {
// super.viewDidLoad()
updateButtons()
speechSynth.delegate = self
print("view load")
// Do any additional setup after loading the view.
}
#IBAction func speakIt(sender: NSButton) {
let string = textField.stringValue
if string.isEmpty {
print("String is empty")
}
else {
print(string)
speechSynth.startSpeaking(string)
isStarted = true
}
}
#IBAction func stopIt(sender: NSButton) {
speechSynth.stopSpeaking()
isStarted = false
}
func updateButtons() {
if isStarted {
speakButton.isEnabled = false
stopButton.isEnabled = true
} else {
stopButton.isEnabled = false
speakButton.isEnabled = true
}
}
func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
isStarted = false
}
}
My Xib has the option checked "Visible at launch". If I uncheck it, I see no window.
Basically, I am attempting a program from the book "Cocoa Programming for OSX". However, the book is obsolete. But I am trying to find my way through new Xcode and Swift. Any help?
Also a point worth noting is that only one window is functional, the second window IBOutlets and IBAction are not connected. So nothing happens in the second window.
I can't figure out why is this happening?
I'm doing a test of a custom keyboard. This is what I need:
It has to have two UITextFields. Cannot be labels.
The keyboard is an embedded UIView.
The default keyboard should be disabled.
It cannot be a keyboard extension.
Not sure why the app is crashing. PS: Not all the keys are on the code yet. Here is an image of what I'm trying to do and the two View Controllers.
Edit: The error is: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
First ViewController:
import UIKit
class HomeVC: UIViewController, ButtonTapDelegate {
#IBOutlet var textField1: UITextField!
#IBOutlet var textField2: UITextField!
#IBOutlet var keyboardView: UIView!
var buttonPressed = [String]()
override func viewDidLoad() {
addKeyboard(view: keyboardView)
buttonPressed = [String]()
textField1.inputView = UIView()
textField2.inputView = UIView()
}
func addKeyboard(view: UIView) {
let keyboard = KeyboardVC(nibName: "KeyboardVC", bundle: nil)
view.addSubview(keyboard.view)
addChild(keyboard)
}
func didTapButton(sender: UIButton) {
if sender.tag == 5 {
textField1.text?.append(contentsOf: " ")
} else if sender.tag == 6 {
textField1.text?.removeAll()
buttonPressed = [String]()
} else {
let val = sender.titleLabel?.text
textField1.text?.append(contentsOf: val!)
}
self.textField1.text = buttonPressed.joined(separator: "")
}
}
Here is the second View Controller:
import UIKit
protocol ButtonTapDelegate {
func didTapButton(sender: UIButton)
}
class KeyboardVC: UIViewController {
var delegate: ButtonTapDelegate!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttons(_ sender: UIButton) {
delegate.didTapButton(sender: sender)
print(sender)
}
}
var delegate: ButtonTapDelegate!
An implicitly unwrapped optional is essentially a promise that you're definitely going to give the variable a value before you try to access it. The problem in this case is that you haven't done that. Most likely, you want to do this in your first view controller:
func addKeyboard(view: UIView) {
let keyboard = KeyboardVC(nibName: "KeyboardVC", bundle: nil)
keyboard.delegate = self // Now "delegate" will have a value before the function gets called
view.addSubview(keyboard.view)
addChild(keyboard)
}
guys.
I'm asking for help. It seems a very easy task, but I can solve it for the whole day.
I'm trying to create a side menu using container view. When a user presses More button(barButtonItem), the whole view slide to the right and menu table appears. I know how to make it using Notifications. But I would like to solve it through delegation. Here is my storyboard.
enter image description here
and code:
import UIKit
class RootViewController: UIViewController, SideMenuDelegate {
#IBOutlet weak var leading: NSLayoutConstraint!
var sideMenuIsOpen = false
var sideMenu: MainViewController?
override func viewDidLoad() {
super.viewDidLoad()
sideMenu?.delegate = self
}
func openSideMenu() {
toggleSideMenu()
}
func toggleSideMenu() {
if sideMenuIsOpen {
leading.constant = 0
} else {
leading.constant = 240
}
}
}
and:
import UIKit
protocol SideMenuDelegate {
func openSideMenu()
}
class MainViewController: UIViewController {
var delegate: SideMenuDelegate?
#IBAction func toggleSideMenu(_ sender: UIBarButtonItem) {
if let delegateUnwrapped = delegate {
delegateUnwrapped.openSideMenu()
} else {
print("nil")
}
}
override func viewDidLoad() {
super.viewDidLoad()
BackgroundImageView.createBackground(insideView: self, image: .mainViewBackground)
}
}
Thank you!
This
var sideMenu: MainViewController? // is nil
override func viewDidLoad() {
super.viewDidLoad()
sideMenu?.delegate = self
}
has no reference to the current displayed main , it's nil when you present the main from the Root give it the reference
I'm very new to Swift MacOS programming and have been learning by writing small test applications.
The aim of this application is to enable the pushbutton when the 2nd textfield has the focus, and disable it when it is not focused.
I have found that by subclassing the NSTextField I can override becomeFirstResponder() however don't know how to set the button to be disabled from the subclass.
ViewController:
class ViewController: NSViewController {
#IBOutlet public weak var pushButton: NSButton!
#IBOutlet weak var textField3: NSTextField!
#IBOutlet weak var textField2: GSTextField!
#IBOutlet weak var textField1: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
textField2.delegate = self
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func chgButton(onoff: Bool){
pushButton.isEnabled = onoff
}
}
// When the field completes editing make the pushbutton disabled.
extension ViewController: NSTextFieldDelegate {
override func controlTextDidEndEditing(_ obj: Notification) {
print("did end")
chgButton(onoff: false)
}
}
GSTextField.Swift
class GSTextField: NSTextField {
override func becomeFirstResponder() -> Bool {
print("GSTextField Firstresponder")
////*** I need to set the button to be enabled here
return super.becomeFirstResponder()
}
}
Your NSTextField subclass needs to be able to communicate with the pushButton. The easiest way to do this is to pass a reference to the pushButton to your text field and then update the push button from there.
Update your ViewController like this:
override func viewDidLoad() {
super.viewDidLoad()
textField2.delegate = self
textField2.pushButton = pushButton
// Do any additional setup after loading the view.
}
And your GSTextField like this:
class GSTextField: NSTextField {
weak var pushButton: NSButton?
override func becomeFirstResponder() -> Bool {
print("GSTextField Firstresponder")
pushButton?.isEnabled = true
return super.becomeFirstResponder()
}
override func resignFirstResponder() -> Bool {
pushButton?.isEnabled = false
return super.resignFirstResponder()
}
}
It should be noted that while this works fine in this toy example, this is a sub-optimal solution to this problem because it tightly couples the pushButton and the GSTextField. A better solution would be to use delegation to communicate the focus changes to the ViewController, and let the ViewController handle the updates.
Your GSTextField would look like this:
protocol FocusObservable: class {
func didGainFocus(sender: Any)
func didLoseFocus(sender: Any)
}
class GSTextField: NSTextField {
weak var focusDelegate: FocusObservable?
override func becomeFirstResponder() -> Bool {
print("GSTextField Firstresponder")
focusDelegate?.didGainFocus(sender: self)
return super.becomeFirstResponder()
}
override func resignFirstResponder() -> Bool {
focusDelegate?.didLoseFocus(sender: self)
return super.resignFirstResponder()
}
}
And then you would add protocol conformance to the ViewController:
extension ViewController: FocusObservable {
func didGainFocus(sender: Any) {
pushButton.isEnabled = true
}
func didLoseFocus(sender: Any) {
pushButton.isEnabled = false
}
}
and set the focusDelegate of the text field:
override func viewDidLoad() {
super.viewDidLoad()
textField2.delegate = self
textField2.focusDelegate = self
// Do any additional setup after loading the view.
}
This is the error Xcode outputs
Unexpectedly found nil while unwrapping an Optional value
I have a viewcontroller that has a tableview and a few buttons; the buttons allow me to insert or remove data. It seems that when I click on Add (which brings up a new viewcontroller via segue as a sheet) the app crashes with the error above. Clicking on remove doesn't have this affect. So it has to do with something regarding the new viewcontroller as a guess. The console doesn't go further into the error other than printing out (lldb)
Here's my code
override func viewDidLoad() {
super.viewDidLoad()
alarmTableView.dataSource = self //error occurs here
alarmTableView.delegate = self //if i remove the above line if will occur here too.
}
My Viewcontroller which the above viewDidLoad func is embedded lists the protocols I need
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var addAlarm: NSButton!
#IBOutlet weak var resetDataButton: NSButton!
#IBOutlet var alarmArrayController: NSArrayController!
#IBOutlet weak var alarmTableView: NSTableView!
#IBOutlet weak var deleteAll: NSButton!
#objc let moc: NSManagedObjectContext
required init?(coder: NSCoder) {
self.moc = CoreDataHandler.getContext()
super.init(coder: coder)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let destinationController = segue.destinationController as! AddAlarmViewController
//pass data to next controller here
}
#IBAction func deleteAllAction(_ sender: Any) {
if (alarmTableView.selectedRow >= 0) {
if (CoreDataHandler.deleteAllObjectsInEntity(entityName: "Alarm")) {
//remove from nsarray controller
for object in alarmArrayController.arrangedObjects as! [Alarm] {
print(object)
alarmArrayController.removeObject(object)
}
alarmTableView.reloadData()
}
}
else {
printInfo(str: "There are no alarms to delete")
}
}
/* Response to the remove alarm button - It removes a selected alarm object from the table */
#IBAction func resetDataAction(_ sender: Any) {
if (alarmTableView.selectedRow >= 0) {
let selectedAlarm = self.alarmArrayController.selectedObjects.first as! Alarm
alarmArrayController.remove(atArrangedObjectIndex: alarmTableView.selectedRow)
CoreDataHandler.deleteObjectInEntity(entityName: "Alarm", obj: selectedAlarm)
alarmTableView.reloadData()
}
else {
//will need a warning or play a sound.
printInfo(str: "Please select an alarm")
}
}
override func viewDidLoad() {
super.viewDidLoad()
printInfo(str: "viewdidload")
print(alarmTableView)
if (alarmTableView != nil) {
printInfo(str: "AlarmTableView Is initialised")
alarmTableView.dataSource = self
alarmTableView.delegate = self
}
else {
printInfo(str: "AlarmTableView is not initialised")
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func printInfo(str: String) {
print("ViewController: \(str)")
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
return 100.0
}
}
class AddAlarmViewController: ViewController {
#IBOutlet weak var closeButton: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
printClassInfo(str: "viewDidLoad")
CoreDataHandler.saveTestData()
}
#IBAction func closeButtonAction(_ sender: Any) {
self.dismissViewController(self)
}
func printClassInfo(str: String) {
print("AddAlarmViewController \(str)")
}
}
If I remove the lines where the error occurs the app run fine. But I want to override the delegate and datasource and use the functions to further customise the table. I'm also using Cocoa Bindings.
Why am I getting this error?
Update
I haven't solved it yet, but i placed a couple of print statements in my viewDidLoad function. It seems that when the app is first loaded, the table view is initialised. But after when I clicked on the Add button, the table view is then set to nil for some odd reason, as if another table view has been initialised. However the data is still visible
Problem:
class AddAlarmViewController: ViewController {
//...
override func viewDidLoad() {
super.viewDidLoad()
//...
}
}
Your AddAlarmViewController is a subclass of ViewController instead of NSViewController.
In AddAlarmViewController's viewDidLoad you call super.viewDidLoad() which basically calls ViewController's viewDidLoad.
But... in this case ViewController is a new instance as the super class of AddAlarmViewController and none of it's properties are initialized.
Whatever it be, it's probably not what you want.
Solution:
class AddAlarmViewController: NSViewController {
//... rest as it is
}