Parse PFUser not registering subclass - swift

I am trying to use Parse PFUser in a software for OSX desktop. When I try to use it PFUser.query() it gives a message: Failed to set (contentViewController) user defined inspected property on (NSWindow): The class PFUser must be registered with registerSubclass before using Parse.
It is happening without registering the class.
I tried it registering the class this way: PFUser.registerSubclass() but it still doesn't work.
I will use the default PFUser without adding any fields to it, so I don't need to create a custom class to be my PFUser.
I tried to use PFUser.enableAutomaticUser() without success
Code below:
AppDelegate.swift
import Cocoa
import Parse
import Bolts
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let APP_ID = "app_id"
let CLIENT_KEY = "client_key"
let SERVER = "https://parseserver.com/"
func applicationDidFinishLaunching(_ aNotification: Notification) {
PFUser.registerSubclass()
let configuracaoParse = ParseClientConfiguration {
$0.applicationId = self.APP_ID
$0.clientKey = self.CLIENT_KEY
$0.server = self.SERVER
}
Parse.initialize(with: configuracaoParse)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
ViewController.swift
import Cocoa
import Parse
class ViewController: NSViewController {
#IBOutlet weak var emailTextField: NSTextField!
#IBOutlet weak var senhaSecureTextField: NSSecureTextField!
override func viewDidLoad() {
super.viewDidLoad()
contaUsuarios()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func entrarButtonClicked(_ sender: NSButton) {
}
func contaUsuarios() {
let query = PFUser.query()
query?.countObjectsInBackground(block: {
(count, error) -> Void in
let numeroUsers = Int(UInt32(count))
if numeroUsers > 0 {
}
print(numeroUsers)
})
}
}

Reading some content on the internet I discovered that in OSX the ViewController is launched before the AppDelegate finishes loading, so I initialized the Parse connection and subclassing in the ViewController's viewDidLoad instead of AppDelegate and it is working just fine.

Related

How to implement Evenkit in order to request permission

I'm building a mac application which should add a reminder in calendar. The build goes without errors nor warning but when the app launch, I get the following error :
"Reminder failed with error Access to this event store is unauthorized."
I have search the web for the right way to request access to calendar on the mac but have not found any.
I have try to translate the following exemple from ios to mac but it failed: https://github.com/andrewcbancroft/EventTracker/tree/ask-for-permission
Here is my code :
import Cocoa
import EventKit
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate
{
#IBOutlet weak var window: NSWindow!
var eventStore = EKEventStore()
var calendars: [EKCalendar]?
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let reminder = EKReminder(eventStore: self.eventStore)
reminder.title = "Go to the store and buy milk"
reminder.calendar = eventStore.defaultCalendarForNewReminders()
do
{
try eventStore.save(reminder,
commit: true)
} catch let error {
print("Reminder failed with error \(error.localizedDescription)")
}
}
func applicationWillTerminate(_ aNotification: Notification)
{
// Insert code here to tear down your application
}
}
Thank you for your attention.
You have to call requestAccess(to:completion: on the event store for example
let eventStore = EKEventStore()
eventStore.requestAccess(to: .reminder) { (granted, error) in
if let error = error {
print(error)
return
}
if granted {
// go on managing reminders
}
}
import Cocoa
import EventKit
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate {
#IBOutlet weak var window: NSWindow!
var eventStore = EKEventStore()
func applicationDidFinishLaunching(_ aNotification: Notification)
{
eventStore.requestAccess(to: .reminder)
{ (granted, error) in
if let error = error
{
print(error)
return
}
if granted
{
let reminder = EKReminder(eventStore: self.eventStore)
reminder.title = "Go to the store and buy milk"
reminder.calendar = self.eventStore.defaultCalendarForNewReminders()
let date : NSDate = NSDate()
let alarm : EKAlarm = EKAlarm (absoluteDate: date.addingTimeInterval(10) as Date)
reminder.addAlarm(alarm)
do
{
try self.eventStore.save(reminder,commit: true)
}
catch let error {print("Reminder failed with error \(error.localizedDescription)")}
}
}
}
func applicationWillTerminate(_ aNotification: Notification)
{
// Insert code here to tear down your application
}
}

How to create a Event in a normal class by swift?

I want to create an login template in a normal class,but in the class,the view can't call the event,no "sss" be printed when the Event triggered
import UIKit
class ViewController: UIViewController ,UITextFieldDelegate{
override func viewDidLoad() {
super.viewDidLoad()
let loginView=login(view: self.view,controller:self)
loginView.setView();
}
}
import UIKit
class login{
let PassWord=UITextField()
let view:UIView!
let controller:ViewController
init(view:UIView,controller:ViewController){
self.view=view
self.controller=controller
}
func setView(){
initPassWord()
print("1")
}
func initPassWord(){
PassWord.placeholder="PassWord"
PassWord.addTarget(self, action: #selector(login.exits(_:)), for:.allEvents)
//PassWord.addTarget(controller, action: #selector(login.exits(_:)), for:.allEvents)
}
#IBAction func exits(_ sender:UITextField){
print("sss")
}
You need
var loginView:Login! // hold a strong reference here , start class names with capital letter
override func viewDidLoad() {
super.viewDidLoad()
loginView = Login(controller:self)
loginView.setView();
}
Also make it weak
weak var controller:ViewController
as not to cause retain cycles
BTW you only need to send the controller , and there you can access it's view

TextField will not load from RealmSwift

So here is the problem that I have been going crazy with. I have an app that uses Realm as its Database. I have used Realm in the past with tableviews and it works properly. I can't seem to get the textField data that I saved to load into my view on viewDidLoad. With tableViews there is a reloadData method, but that isn't the case with textFields. I need the data that is in my data base to load into the view on viewDidLoad and I have confirmed several times that data has been saved and is sitting in the dataBase just waiting to load into the view, but it will not load.
import Cocoa
import RealmSwift
class PublisherViewController: NSViewController {
#IBOutlet weak var publisherName: NSTextField!
let realm = try! Realm()
var pubData : Results<Pub>?
override func viewDidLoad() {
super.viewDidLoad()
// Here is where textField.stringValues should load into the viewDidLoad
let theData = Pub()
theData.pubName = publisherName.stringValue
print("print \(theData)")
}
func save(pubData: Pub) {
do {
try realm.write {
realm.add(pubData)
}
} catch {
print("there was an error saving pubData \(error)")
}
}
#IBAction func savePublisher(_ sender: NSButton) {
let publisherData = Pub()
publisherData.pubName = publisherName.stringValue
save(pubData: publisherData)
}
}
Here is my data model
import Foundation
import RealmSwift
class Pub: Object {
#objc dynamic var pubName : String = """
}
Thanks to Mrkrisher on Discord here is the answer on how to display the last saved textViews and textFields from Realm into your viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
publisherName.stringValue = (pubData?.last?.pubName)?? ""
}

Swift OSX - Delegate protocol function returns nil, crashes when unwrapping textfield value

I'm working on an OSX app with Swift which makes use of an NSSplitView which holds two view controllers: "TableViewController" and "EntryViewController". I'm using delegates in order to transmit a custom NSObject ("Entry") on click from TableViewController up to the SplitViewController, then back down to the EntryViewController.
My problem is this: When the Entry object is received in the EntryViewController, any attempt to assign its properties to a text field value result in an unexpectedly found nil type error, never mind that the IBOutlets are properly linked, and that it can both print the Entry.property and the textfield string value (provided it is in a different, unrelated function).
I have tried many arrangements to solve this problem, which is why the current configuration might be a bit over-complicated. A delegate relation straight from Table VC to Entry VC caused the same issues.
Is there some way that the IBOutlets are not connecting, even though the view has loaded before the delegate is called? I've read many many articles on delegation—mostly for iOS—and yet can't seem to find the root of my problems. I'll be the first to admit that my grasp of Swift is a little bit piecemeal, so I am open to the possibility that what I am trying to do is simply bad/hacky coding and that I should try something completely different.
Thanks for your help!
TableViewController:
protocol SplitViewSelectionDelegate: class {
func sendSelection(_ entrySelection: NSObject)
}
class TableViewController: NSViewController {
#IBOutlet weak var searchField: NSSearchField!
#IBOutlet var tableArrayController: NSArrayController!
#IBOutlet weak var tableView: NSTableView!
var sendDelegate: SplitViewSelectionDelegate?
dynamic var dataArray = [Entry]()
// load array from .plist array of dictionaries
func getItems(){
let home = FileManager.default.homeDirectoryForCurrentUser
let path = "Documents/resources.plist"
let urlUse = home.appendingPathComponent(path)
let referenceArray = NSArray(contentsOf: urlUse)
dataArray = [Entry]()
for item in referenceArray! {
let headwordValue = (item as AnyObject).value(forKey: "headword") as! String
let defValue = (item as AnyObject).value(forKey: "definition") as! String
let notesValue = (item as AnyObject).value(forKey: "notes") as! String
dataArray.append(Entry(headword: headwordValue, definition: defValue, notes: notesValue))
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.sendDelegate = SplitViewController()
getItems()
print("TVC loaded")
// Do any additional setup after loading the view.
}
// send selection forward to entryviewcontroller
#IBAction func tableViewSelection(_ sender: Any) {
let index = tableArrayController.selectionIndex
let array = tableArrayController.arrangedObjects as! Array<Any>
let obj: Entry
let arraySize = array.count
if index <= arraySize {
obj = array[index] as! Entry
print(index)
print(obj)
sendDelegate?.sendSelection(obj)
}
else {
print("index unassigned")
}
}
}
SplitViewController:
protocol EntryViewSelectionDelegate: class {
func sendSecondSelection(_ entrySelection: NSObject)
}
class SplitViewController: NSSplitViewController, SplitViewSelectionDelegate {
var delegate: EntryViewSelectionDelegate?
#IBOutlet weak var mySplitView: NSSplitView!
var leftPane: NSViewController?
var contentView: NSViewController?
var entrySelectionObject: NSObject!
override func viewDidLoad() {
super.viewDidLoad()
// assign tableview and entryview as child view controllers
let story = self.storyboard
leftPane = story?.instantiateController(withIdentifier: "TableViewController") as! TableViewController?
contentView = story?.instantiateController(withIdentifier: "EntryViewController") as! EntryViewController?
self.addChildViewController(leftPane!)
self.addChildViewController(contentView!)
print("SVC loaded")
}
func sendSelection(_ entrySelection: NSObject) {
self.delegate = EntryViewController() //if this goes in viewDidLoad, then delegate is never called/assigned
entrySelectionObject = entrySelection
print("SVC:", entrySelectionObject!)
let obj = entrySelectionObject!
delegate?.sendSecondSelection(obj)
}
}
And Finally, EntryViewController:
class EntryViewController: NSViewController, EntryViewSelectionDelegate {
#IBOutlet weak var definitionField: NSTextField!
#IBOutlet weak var notesField: NSTextField!
#IBOutlet weak var entryField: NSTextField!
var entryObject: Entry!
override func viewDidLoad() {
super.viewDidLoad()
print("EVC loaded")
}
func sendSecondSelection(_ entrySelection: NSObject) {
self.entryObject = entrySelection as! Entry
print("EVC:", entryObject)
print(entryObject.headword)
// The Error gets thrown here:
entryField.stringValue = entryObject.headword
}
}
You don't need a delegate / protocol since there is a reference to EntryViewController (contentView) – by the way the instance created with EntryViewController() is not the instantiated instance in viewDidLoad.
Just use the contentView reference:
func sendSelection(_ entrySelection: NSObject) {
contentView?.sendSecondSelection(entrySelection)
}

NSTextViewDelegate crashing

I have a small project with an NSTextview and a delegate that catches changes in text, as below. The object EditViewHandler works fine when it's a global but crashes when text is added to the view if it's local to viewDidLoad(). So this is obviously the wrong way to do it but what would be the correct way of doing this:
#IBOutlet var EditPaneOutlet: NSTextView!
override func viewDidLoad() {
super.viewDidLoad()
let e = EditViewHandler( EditPaneOutlet: EditPaneOutlet )
}
class EditViewHandler : NSObject, NSTextViewDelegate {
var EditPaneOutlet: NSTextView! = nil
init( EditPaneOutlet: NSTextView ) {
super.init()
self.EditPaneOutlet = EditPaneOutlet
self.EditPaneOutlet!.delegate = self
}
func textDidChange(_ notification: Notification) {
print( "text changed")
}
}