Quicklook always displays "no file to preview" error (url is valid) - swift

I'm trying to use QuickLookController subclass as a child controller, setting its view as a subview in the parent. However, it always displays "no file to preview" message in the opening window. URL in the data source is valid, but the controller is never trying to get it! func previewItemAt index is never invoked!
func "numberOfPreviewItems" invokes always.
Please, help!

I get it. driven by example in article https://williamboles.me/hosting-viewcontrollers-in-cells/ I loaded my controller from bundle:
static func createFromStoryBoard() -> PreviewControler {
let storyboard = UIStoryboard(name: "PreviewControler", bundle: Bundle(for: PreviewControler.self))
guard let viewController = storyboard.instantiateViewController(withIdentifier: "PreviewControler") as? PreviewControler else {
fatalError("PreviewControler should be present in storyboard")
}
return viewController
}
But QuickLook controller must be created with it's constructor, so change to
let viewController = PreviewController()
solved the problem. Now all is fine.

Related

Going from one storyboard to another from a tableView in Swift 5 / Cocoa

have search on that topic without finding a solution that work.
I am building a accounting application with several storyboard. Main, Customer( clients), invoice (factures)... etc. I can go from the main storyboard to the customer of Invoice storyboard by click a button no problem... The button (main SB) is linked to the Customer or Invoice storyboard reference.
In the clients storyboard, I have a tableView with that list the purchased historic of that customer. I would like to to be able to double clic on a specific invoice, and open that invoice in the Invoice storyboard.
The double clic part work fine, print message work... but the program crash after with the message: Could not cast value of type '__NSCFBoolean' (0x7fffaab000c8) to '__C.NSViewControllerPresentationAnimator'
That code was taken andadapted from another post. I have tried different variation withou success ie same error message.
I have not work on the part where I transfer the Invoice number from the client SB to the Invoice SB. I will likely transfer the Invoice number with a segue and have the Invoices program look if that variable if not nil, after loading
Invoice storyboard filename : factures.storyboard
facture ViewController Class : FacturesVC
ViewController storyboardID : facturesVC_id
#objc func tableViewDoubleClick(_ sender:AnyObject) {
if tableView.selectedRow >= 0 {
print ("VC545:", tableView.selectedRow)
//let storyboard = NSStoryboard(name: "factures", bundle: nil)
//let VC = storyboard.instantiateViewController(withIdentifier: "facturesVC_id") // give same error
let VC = NSStoryboard(name: "factures", bundle: nil).instantiateController(withIdentifier: "facturesVC_id") as! FacturesVC
self.present(VC as NSViewController, animator: true as! NSViewControllerPresentationAnimator)
}
}
Your code does not make sense.
It looks like you are trying to call present(_:animator:). If you call that, you need to pass it an animator (an object of type NSViewControllerPresentationAnimator.)
Your code does not create a NSViewControllerPresentationAnimator.
Here is an outline of how you need to change it:
let vc = NSStoryboard(name: "factures", bundle: nil).instantiateController(withIdentifier: "facturesVC_id") as! FacturesVC
let animator = // Code to create an NSViewControllerPresentationAnimator
self.present(vc, animator: animator)
I haven't worked with NSViewControllerPresentationAnimators before. (I mostly work with iOS these days.) You should probably search for tutorials on NSViewControllerPresentationAnimator if you are unsure how to proceed.
Finally, I have found the answer I was looking for...
Here is the code.
#objc func tableViewDoubleClick(_ sender:AnyObject) {
if tableView.selectedRow >= 0 {
let srow = tableView.selectedRow
//print ("VC551:", srow)
fact_nb = Int(fact_tbv[srow].id_f) ?? 0 // invoice nb that you want to segue
let storyboard = NSStoryboard(name: "factures", bundle: nil)
let VC = storyboard.instantiateController(withIdentifier: "facturesVC_id")
//self.presentAsSheet(VC as! NSViewController) work fine for sheet
// self.presentingViewController // data are laoded but nothing show up
// self.presentAsModalWindow(VC as! NSViewController) // OK for modal, cannot be resize , yellow button missing on bar
// self.present(VC as! NSViewController, animator: false as! NSViewControllerPresentationAnimator) // true or false... need a animator
let window = NSWindow(contentViewController: VC as! NSViewController)
window.center()
let windowController = NSWindowController(window: window)
windowController.showWindow(nil)
//see How to Perform Segue https://www.youtube.com/watch?v=JL0xuZ4TXrM
self.performSegue(withIdentifier: "gotofact", sender: nil) // segue identifier name : gotofact
}
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let sb = segue.destinationController as! FacturesVC
print ("VC569:", fact_nb)
sb.factnb = fact_nb
}

How do I pop out a ViewController(like a modal) programmatically?

All:
I am doing a swift , cocoa macos app project with multiple ViewControllers in one storyboard.
I know if I do segue and link the segue from second ViewController to first ViewController.
I can pop out ViewController.
But what if I have a function and want to call another ViewController to present programmatically from first ViewController?
I search a lot of examples start with UIStoryBoard, but my Storyboard is NSStoryboard.
Could anyone hint me a little to start with?
my code:
func checkPassword(SystemMsg:String) -> String{
//print("x")
let storyBoard = NSStoryboard(name: "Main", bundle: nil)
let mainViewController : NSViewController = storyBoard.instantiateController(withIdentifier: "PasswordInput") as! NSViewController
//self.present(mainViewController, asPopoverRelativeTo: <#T##NSRect#>, of: sender, preferredEdge: NSRectEdge, behavior: <#T##NSPopover.Behavior#>)
return ""
}
And my viewController in storyboard look like(no segue,no link):
enter image description here
If anyone can guide me through this step by step would be appreciated.
I figure it out myself.
The most simple way contains 4 steps:
Identify your main ViewController and second ViewController in storyboard
Create your main ViewController with instantiateController
Create your second ViewController with instantiateController
use presentAsModalWindow or presentAsSheet to present secondController on main ViewController
first we need to Identify storyboard correctly:
Identify first storyboard , we need to click top blue cube and then name it in Storyboard Id area
Identify second storyboard , we need to click top blue cube and then name it in Storyboard Id area
example code:
func checkPassword(SystemMsg:String) -> String{
//print("x")
//let storyBoard = NSStoryboard(name: "Main", bundle: nil)
let mainViewController : NSViewController = self.storyboard?.instantiateController(withIdentifier: "MainController") as! NSViewController
let passwordInputViewController : NSViewController = self.storyboard?.instantiateController(withIdentifier: "PasswordInput") as! NSViewController
mainViewController.presentAsModalWindow(passwordInputViewController)
//Or
mainViewController.presentAsSheet(passwordInputViewController)
return ""
}
If I miss something please correct me gently.
reference: Transitioning between view controller, OS X
PS. if you want to pass value between ViewController, this is good reference : https://learnappmaking.com/pass-data-between-view-controllers-swift-how-to/#back-properties

Cannot Programmatically Switch Storyboards

I'm attempting to switch storyboards when a button only if a condition (The textfield not being empty) is met. I found this piece of code as an answer to a similar question, and it doesn't seem to be working. My program crashes with "'Storyboard () doesn't contain a view controller with identifier 'Avatar Controller''"
I'm not completely sure as to where to find the view controller identifies, or whether or not I have to add '.storyboard' at the end of the storyboard name.
let storyboard = UIStoryboard(name: "Avatar", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Avatar Controller")
self.navigationController!.pushViewController(vc, animated: true)
To make it works, Use Storyboard ID has to be checked
This could be happening for 2 reasons.
1) Because in your Avatar.storyboard you are referencing a view controller with the id Avatar Controller but you have not set that value on any of the view controllers in the storyboard file. Go into your Avatar.storyboard, click on the view controller you want to show and go to this panel:
Make sure that the Storyboard ID for your viewController matches what value you use in storyboard.instantiateViewController(withIdentifier: "Avatar Controller")
2) Because you are not providing a bundle when you are loading your storyboard. You are calling this
let storyboard = UIStoryboard(name: "Avatar", bundle: nil);
but because you specify bundle as nil it doesn't know where to look for the Avatar.storyboard file. To fix it, specify bundle as Bundle.main:
let storyboard = UIStoryboard(name: "Avatar", bundle: Bundle.main);

Dynamic Popups in Swift on label word selection

I'm looking for a way to show a dynamically show a popup within a view controller when a user selects a particular word within a label.
For example
Click here for a link, click here for another link
The label text is pulled from a database so is dynamically added based on the content a user is viewing, i was hoping to use the URL schemes within Swift to show the correct popup depending on what a user selected, but when i add the following within app delegate the popup shows within a separate view controller and not as a pop up view controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("glossaryPopupID") as! UIViewController
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
return true
When the popup is close the screen behind is now blank rather than showing the original view controller.
SO my question is, whether this is the best way to achieve this as im not sure its best practice to used URL links within an app to link to other parts of the same app, or is there another way i am missing.
Think i have resolved this now, using the following;
let storyboard = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("test") as! ViewController
let popOverVC = UIStoryboard(name:"Main", bundle: nil).instantiateViewControllerWithIdentifier("sbPopUpID") as! PopUpViewController
storyboard.addChildViewController(popOverVC)
popOverVC.view.frame = storyboard.view.frame
storyboard.view.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(storyboard)
self.window?.rootViewController?.presentViewController(storyboard, animated: true, completion: nil)

Change ViewController Swift

i have an issue. I would like to change the view controller in swift.
This is a part of my code:
if success == "1" {
NSLog("Login SUCCESS");
var prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
prefs.setObject(mobile, forKey: "USERNAME")
prefs.setInteger(1, forKey: "ISLOGGEDIN")
prefs.synchronize()
self.presentViewController(OtpVC(), animated: true, completion: nil)
}
my OtpVC file is:
class OtpVC: UIViewController {
#IBOutlet weak var smsfield: UITextField!
#IBAction func continueButton(sender: AnyObject) {
}
}
The problem now is that when is login successful the page change and goes all black!
How i can fix that? Thanks in advance.
The page in blank is an indicator of that your view has not being loaded. And it seems like that's the case:
Please take a closer look, you are creating an instance of that class, but you are not instantiating the view of it.
In swift you can have single classes affecting several views in your
storyboards.
The correct way, should be:
if success == "1" {
NSLog("Login SUCCESS");
var prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
prefs.setObject(mobile, forKey: "USERNAME")
prefs.setInteger(1, forKey: "ISLOGGEDIN")
prefs.synchronize()
var storyboard = UIStoryboard(name: "Main", bundle: nil)
"Main" here should be the name of the storyboard in which the OtpVC view is.
var controller = storyboard.instantiateViewControllerWithIdentifier("OtpVC") as! OtpVC
"OtpVC" here should be the storyboard identifier of your view
self.presentViewController(controller, animated: true, completion: nil)
}
Update:
Another root cause may be that your identifier is not well set at storyboard.
At your Identity Inspector settings should be similar to:
Here in Module, like I have no such Class on my targets it says None.
This could be something you may want to have a look at. Maybe in your storyboard you are referencing other target than the one with such OptVC class implementation.
You can also use segues.
Set a segue from one view controller to the one where you want to shift in the storyboard.
Also set the identifier of the segue in storyboard.
Now use below code
self.performSegueWithIdentifier("identifier", sender: self)
self.presentViewController(OtpVC(), animated: true, completion: nil)
With the line above, you'll create a new instance of OtpVC programmatically. It's not a problem if that's what you want and the view controller is coded properly to be initialized like that.
But because it's all black I assume you've created OtpVC in storyboard so you'll either need to use a segue like Sukhdeep Singh Kalra has suggested or instantiate it with:
let destination = storyboard?.instantiateViewControllerWithIdentifier("identifier") as! OtpVC
presentViewController(destination, animated: true, completion: nil)
Both options, you'll have to set an identifier.
To set an identifier for the latter, go to storyboard and click on your view controller. Make sure the view controller is selected by clicking the left yellow button on top of your view controller. Then in identity inspector, type in the identifier name and replace "identifier" in my example with that name.