I am creating document based app and I have strange problem - I can't open files which I saved. Each time I receive this error: "The document /name/ could not be opened". Here is output from NSError: The operation couldn’t be completed. (OSStatus error -4.)
Error Domain=NSOSStatusErrorDomain Code=-4 "kCFMessagePortTransportError / kCSIdentityDeletedErr / unimpErr: / / unimplemented core routine"
And my document class:
import Cocoa
class Document: NSDocument {
var saved: String = ""
let encoding = NSUTF8StringEncoding
override init() {
super.init()
// Add your subclass-specific initialization here.
}
override func windowControllerDidLoadNib(aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
override class func autosavesInPlace() -> Bool {
return true
}
override func makeWindowControllers() {
// Returns the Storyboard that contains your Document window.
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let windowController = storyboard.instantiateControllerWithIdentifier("Document Window Controller") as! WindowController
self.addWindowController(windowController)
}
override func dataOfType(typeName: String) throws -> NSData {
saved = "tekst"
let dict: [String : AnyObject] = ["saved" : saved]
let data: NSData = NSKeyedArchiver.archivedDataWithRootObject(dict)
return data
}
override func readFromData(data: NSData, ofType typeName: String) throws {
let dict: NSDictionary = NSKeyedUnarchiver.unarchiveObjectWithData(data)! as! NSDictionary
print(dict.objectForKey("saved")!)
print("^^")
let e = NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
print("localized desc: ")
print(e.localizedDescription)
throw e
}
}
I really can't find any solution.
Related
I'm apparently designing a drag and drop dropbox which can either select files by clicking it or dragging and dropping the files on it, and I want the selected files to be visible in a table next to it. My design logic is that whenever the user selects files from an NSOpenPanel, it passes the selected file paths into the CoreData and then an array retrieves them one by one from the CoreData, and finally, update the NSTableView's content by using reloadData().
Basically, my problem is that whenever I try to call ViewController().getDroppedFiles() from DropboxButton class, I always get a Fatal error: unexpectedly found nil while unwrapping an optional value.
My ViewController.swift:
import Cocoa
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
getDroppedFiles()
}
#IBOutlet weak var DroppedFilesTableView: NSTableView!
var droppedFiles: [DroppedFiles] = [] // Core Data class definition: DroppedFiles
func numberOfRows(in tableView: NSTableView) -> Int {
return droppedFiles.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let droppedFilesCollection = droppedFiles[row]
if (tableView?.identifier)!.rawValue == "fileNameColumn" {
if let fileNameCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "fileNameCell")) as? NSTableCellView {
fileNameCell.textField?.stringValue = droppedFilesCollection.fileName!
return fileNameCell
}
} else if (tableView?.identifier)!.rawValue == "filePathColumn" {
if let filePathCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "filePathCell")) as? NSTableCellView {
filePathCell.textField?.stringValue = droppedFilesCollection.filePath!
return filePathCell
}
}
return nil
}
#IBAction func DropboxClicked(_ sender: NSButton) {
// selected file paths
for filePath in selectedFilePaths {
if let context = (NSApp.delegate as? AppDelegate)?.persistentContainer.viewContext {
let droppedFilesData = DroppedFiles(context: context)
droppedFilesData.fileName = getFileName(withPath: filePath)
droppedFilesData.filePath = filePath
do {
try context.save()
} catch {
print("Unable to save core data.")
}
}
getDroppedFiles()
}
}
func getDroppedFiles() {
if let context = (NSApp.delegate as? AppDelegate)?.persistentContainer.viewContext {
do {
try droppedFiles = context.fetch(DroppedFiles.fetchRequest())
} catch {
print("Unable to fetch core data.")
}
}
DroppedFilesTableView.reloadData() // Fatal Error: unexpectedly found nil while unwrapping an optional value (whenever I call this function in other class)
}
}
I'm using a push button (NSButton) as the dropbox (it has its own class), which can easily be clicked and also supports dragging options.
My DropboxButton.swift:
import Cocoa
class DropboxButton: NSButton {
required init?(coder: NSCoder) {
super.init(coder: coder)
registerForDraggedTypes([NSPasteboard.PasteboardType.URL, NSPasteboard.PasteboardType.fileURL])
}
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
// some other codes
return .copy
}
override func draggingExited(_ sender: NSDraggingInfo?) {
// some other codes
}
override func draggingEnded(_ sender: NSDraggingInfo) {
// some other codes
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
guard let pasteboard = sender.draggingPasteboard.propertyList(forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")) as? NSArray,
let filePaths = pasteboard as? [String] else {
return false
}
for filePath in filePaths {
if let context = (NSApp.delegate as? AppDelegate)?.persistentContainer.viewContext {
let droppedFilesData = DroppedFiles(context: context)
droppedFilesData.fileName = getFileName(withPath: filePath)
droppedFilesData.filePath = filePath
do {
try context.save()
} catch {
print("Unable to save core data.")
}
}
ViewController().getDroppedFiles() // found nil with reloadData() in ViewController.swift
}
return true
}
}
And this is my interface and code logic:
So, how can I reloadData() for the table view in my ViewController class from another class (DropboxButton: NSButton) so that whenever the user drags and drops files into the dropbox, the table view will reload?
P.S. To get this done means a lot to me, I really need to get this fixed in a short time, is there anyone can spend some time and help me?
You need to call getDroppedFiles() on a loaded instance of ViewController.
With ViewController().getDroppedFiles() you're creating a new instance of ViewController that is not shown anywhere (so controls are not initialized resulting in the nil error).
I found this solution useful for my case.
I used observer to pass through data and call functions from other controller classes, now I understand that I was creating a new instance of ViewController which is not loaded. Here is my code:
ViewController.swift:
class ViewController: NSViewController {
// other codes
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(getDroppedFiles), name: NSNotification.Name(rawValue: "reloadTableViewData"), object: nil)
}
#objc func getDroppedFiles() {
DroppedFilesTableView.reloadData()
}
}
DropboxButton.swift:
class DropboxButton: NSButton {
// other codes
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
// other codes
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableViewData"), object: nil)
return true
}
}
And now, everything works perfectly, I can even add an userInfo: to pass data between files and classes.
How to define objects in the code and of which type?
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate=UIApplication.sharedApplication().delegate as! AppDelegate
let context=appDelegate.managedObjectContext
let request=NSFetchRequest(entityName:lineEntityName)
do{
let objects = try context.executeFetchRequest(request)
}
catch let error as NSError {
print(error)
}
if let objectList=objects
{
for oneObject in objectList
{
let lineNum=oneObject.valueForKey(lineNumberKey) as integerValue
let lineText=oneObject.valueForKey(lineTextKey) as String
let lineField=lineFields(lineNum)
textField.text=lineText
}
}
else
{
print("There was an Error")
}
let app=UIApplication.sharedApplication()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"applicationWillResignActiveNotification", name: UIApplicationWillResignActiveNotification, object: app)
// Do any additional setup after loading the view, typically from a nib.
}
The recommended way is to put all good code in the do clause which solves the problem.
And executeFetchRequest returns a non-optional array so the optional binding can be omitted.
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context = appDelegate.managedObjectContext
let request = NSFetchRequest(entityName:lineEntityName)
do {
let objects = try context.executeFetchRequest(request)
for oneObject in objects
{
let lineNum = oneObject.valueForKey(lineNumberKey) as integerValue
let lineText = oneObject.valueForKey(lineTextKey) as String
let lineField = lineFields(lineNum)
textField.text = lineText
}
let app = UIApplication.sharedApplication()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"applicationWillResignActiveNotification", name: UIApplicationWillResignActiveNotification, object: app)
// Do any additional setup after loading the view, typically from a nib.
}
catch let error as NSError {
print(error)
}
}
import UIKit
import Parse
class HomePageViewController: UIViewController, UITableViewDelegate {
#IBOutlet weak var homPageTableView: UITableView!
var imageFiles = [PFFile]()
var imageText = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// DO any additional setup after loading the view
var query = PFQuery(className: "Posts")
query.orderByAscending("createdAt")
query.findObjectsInBackgroundWithBlock {
(posts : [AnyObject]?, error : NSError?) -> Void in
if error == nil {
//success fetxhing objects
println(posts?.count)
for post in posts! {
self.imageFiles.append(post["imageFile"] as! PFFile) ---------error here
self.imageText.append(post["imageText"] as! String)
}
println(self.imageFiles.count)
}else{ println(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
As a title, It is keep saying "unexpectedly found nil while unwrapping an Optional value" at the line I draw.
There are a lot of questions about this, it is hard to read code for me, And even if I undertood, mine didn't go right.
where should I use optional binding?
And can u explain it with really easy example what is optional binding?
Thank you
Your post dictionary does not contain an imageFile key. When you access a dictionary using post["imageFile"] the result is the value (if the key exists) and nil (if the key does not exist). You can distinguish between these cases using
if let imageFile = post["imageFile"],
let imageText = post["imageText"] {
self.imageFiles.append(imageFile as! PFFile)
self.imageText.append(imageText as! String)
} else {
print("imageFile and/or imageText missing from \(post)")
}
You need to unwrap your posts before looping through them because posts: [AnyObject]? is optional.
if error == nil {
if let postData = posts{
//success fetxhing objects
println(postData?.count)
for post in postData! {
self.imageFiles.append(post["imageFile"] as! PFFile)
self.imageText.append(post["imageText"] as! String)
}
println(self.imageFiles.count)
}
}else{
println(error)
}
this is what i have so far:
import Foundation
import Parse
import UIKit
import Bolts
class SignUpViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var createAccountButton: UIButton!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
emailTextField.delegate = self;
passwordTextField.delegate = self;
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func createAccountButtonPressed(sender: AnyObject) {
if verifyEmailDomain(self.emailTextField.text)
{
createAccount(self.emailTextField.text, password: self.passwordTextField.text)
}
else
{
//self.statusLabel.text = "Email domain is not valid.";
let alert = UIAlertView()
alert.title = "Invalid Email Domain"
alert.message = "Make sure you entered in your address correctly. If you did, ask your system about using PageMD! Thanks."
alert.addButtonWithTitle("Close")
alert.show()
}
}
func verifyEmailDomain(email: String) -> Bool
{
var isVerifiedDomain = false
let userDomain: String = (email.componentsSeparatedByString("#")).last!
//NSLog(userDomain)
let validDomainsFileLocation = NSBundle.mainBundle().pathForResource("ValidDomains", ofType: "txt")
var validDomainsFileContent = NSString(contentsOfFile: validDomainsFileLocation!, encoding: NSUTF8StringEncoding, error: nil)
// NSLog(validDomainsFileContent! as String)
let validDomains = validDomainsFileContent!.componentsSeparatedByString("\n")
for domain in validDomains
{
NSLog(domain as! NSString as String)
if userDomain == (domain as? NSString)
{
isVerifiedDomain = true
break
}
}
return isVerifiedDomain
}
func createAccount(email: String, password: String)
{
var newUser = PFUser()
newUser.username = email // We want the user to login only with their email.
newUser.email = email
newUser.password = password
newUser.signUpInBackgroundWithBlock { (succeeded: Bool, error: NSError?) -> Void in
if error == nil
{
// Account created successfully!
if succeeded == true
{
self.statusLabel.text = "Account created!"
}
}
else
{
if let errorField = error!.userInfo
{
self.statusLabel.text = (errorField["error"] as! NSString) as String
}
else
{
// No userInfo dictionary present
// Help from http://stackoverflow.com/questions/25381338/nsobject-anyobject-does-not-have-a-member-named-subscript-error-in-xcode
}
}
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool
{
textField.resignFirstResponder()
return true;
}
}
when i run it i receive this in my terminal for xcode:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
and highlighted in green is:
var validDomainsFileContent = NSString(contentsOfFile: validDomainsFileLocation!, encoding: NSUTF8StringEncoding, error: nil)
what can i do to avoid this error?
I'm trying to create a login that uses the emailVerified feature from parse but I keep receiving this error and cant save the email to the core or send the verification email to the user. What can i do to make this code work and stop the error from coming up?
In that case, the file at validDominsfileContent wasn't found. You need to make sure that the file is included in your Bundle.
To do that, open the Bundle-Resources:
Project > App target > Build Phases > Copy bundle resources
There you save your file. Now it should be found by Swift.
I'm trying to setup a sign in page using parse and swift in Xcode but I keep getting an error with 'signInBackgroundWithBlock' how do I make this work?
I keep receiving the message
Cannot invoke 'signUpInBackgroundWithBlock' with an argument list of
type ((Bool!, NSError!) -> Void)
so far this is what I have and I just have an error with that part.
import UIKit
import Parse
class EmailLogin: UIViewController, UITextFieldDelegate {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var createAccountButton: UIButton!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
emailTextField.delegate = self;
passwordTextField.delegate = self;
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func createAccountButtonPressed(sender: AnyObject)
{
if verifyEmailDomain(self.emailTextField.text)
{
createAccount(self.emailTextField.text, password: self.passwordTextField.text)
}
else
{
//self.statusLabel.text = "Email domain is not valid.";
let alert = UIAlertView()
alert.title = "Invalid Email Domain"
alert.message = "Make sure you entered in your address correctly. If you did, ask your system about using PageMD! Thanks."
alert.addButtonWithTitle("Close")
alert.show()
}
}
func verifyEmailDomain(email: String) -> Bool
{
var isVerifiedDomain = false
let userDomain: String = (email.componentsSeparatedByString("#")).last!
//NSLog(userDomain)
let validDomainsFileLocation = NSBundle.mainBundle().pathForResource("ValidDomains", ofType: "txt")
var validDomainsFileContent = NSString(contentsOfFile: validDomainsFileLocation!, encoding: NSUTF8StringEncoding, error: nil)
//NSLog(validDomainsFileContent!)
let validDomains = validDomainsFileContent!.componentsSeparatedByString("\n")
for domain in validDomains
{
NSLog(domain as! NSString as String)
if userDomain == (domain as! NSString)
{
isVerifiedDomain = true
break
}
}
return isVerifiedDomain
}
func createAccount(email: String, password: String)
{
var newUser = PFUser()
newUser.username = email // We want the user to login only with their email.
newUser.email = email
newUser.password = password
//this where i get my error//
newUser.signUpInBackgroundWithBlock { (succeeded: Bool!, error: NSError!) -> Void in
if error == nil
{
// Account created successfully!
if succeeded == true
{
self.statusLabel.text = "Account created!"
}
}
else
{
if let errorField = error.userInfo
{
self.statusLabel.text = (errorField["error"] as NSString)
}
else
{
// No userInfo dictionary present
// Help from http://stackoverflow.com/questions/25381338/nsobject-anyobject-does-not-have-a-member-named-subscript-error-in-xcode
}
}
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool
{
textField.resignFirstResponder()
return true;
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
If you are using swift 1.2 (Xcode 6.3) you need to call the function by:
newUser.signUpInBackgroundWithBlock({(succeeded:Bool, error:NSError?) -> Void in
})
And if you are using swift 1.1 (Xcode 6.1, 6.2) you need to call the function by:
newUser.signUpInBackgroundWithBlock({(succeded:Bool, error:NSError!) -> Void in
})
This is different because of the swift update 1.2 which has changes with using optionals.
Another way is to write it like this:
(Works in old and new swift)
newuser.signUpInBackgroundWithBlock { (succeded, error) -> Void in
}