Remove done button in M13PDFKit swift - swift

I'm using M13PDFKit and having a little problem. In the example the done button is not there, but when I try it shows. I don't know how to remove it. The done button looks like this. Im using Swift
in View controller just like this
import UIKit
import M13PDFKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "NEXT" {
let viewer: PDFKBasicPDFViewer = segue.destinationViewController as! PDFKBasicPDFViewer
viewer.enableBookmarks = true
viewer.enableBookmarks = true
viewer.enableOpening = true
viewer.enablePrinting = true
viewer.enableSharing = true
viewer.enableThumbnailSlider = true
//Load the document (pdfUrl represents the path on the phone of the pdf document you wish to load)
let pdfUrl = "/Users/developer/Library/Developer/CoreSimulator/Devices/C8DC5F44-B2FC-4FC3-8E10-B87FC00791FA/data/Containers/Data/Application/047BE9AD-F43C-421E-B5B5-943B0C79B592/Documents/Yudi Seven.pdf"
let document: PDFKDocument = PDFKDocument(contentsOfFile: pdfUrl, password: nil)
viewer.loadDocument(document)
}
}
}

Goto PDFKBasicPDFViewer.m disable the line(line 247) that highlighted in the first image and run the project....
Output:

Related

only instance methods can be declared #IBAction building audio app

I've been trying to build an IOS app that will allow me to click a button and have audio play and I'm getting stuck on this error only instance methods can be declared #IBAction. I've had a search and it doesn't seem like I've closed it out of the class or anything like that but it still doesn't want to work
import UIKit
import AVFoundation
class LevelAStartingSoundViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
#IBAction func Sbutton(_ sender: Any, forEvent event: UIEvent) {
playSound(sound: "Ssound", type: "wav")
}
}
}
If you reformat your code (Ctrl + i), you'll notice that Sbutton is inside viewDidLoad.
You need to move it outside.
#IBAction func sButton(_ sender: UIButton) { /// make sure you have the right function signature
playSound(sound: "Ssound", type: "wav")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}

Get selected image in imagePickerController and pass it to coreML

I'm trying to do the recognition by using coreML, the function working and showing the result correctly. But I want to call the method into a button, like when I pressed the catDog button and it runs the method. But since the finalResult() and identifyCatOrDog() is its own function, so that I can't call it into the button. I tried to copy and paste the method inside the button, but it doesn't show me anything. How can I edit the code so that findResult() only work when I pressed the button not running automatically?
import UIKit
import CoreML
import Vision
import Photos
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var loadImage: UIImageView!
#IBOutlet var Result: UILabel!
#IBAction func photoBtn(_ sender: UIButton) {
getPhoto()
}
#IBAction func cameraBtn(_ sender: UIButton) {
}
#IBAction func catDog(_ sender: UIButton) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getPhoto() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let gotImage = info[.originalImage] as? UIImage else {
fatalError("No picture chosen")
}
loadImage.image = gotImage
identifyCatOrDog(image: gotImage)
}
func identifyCatOrDog(image: UIImage) {
let modelFile = ImageClassifier()
let model = try! VNCoreMLModel(for: modelFile.model)
let handler = VNImageRequestHandler(cgImage: image.cgImage!, options: [ : ])
let request = VNCoreMLRequest(model: model, completionHandler: findResults)
try! handler.perform([request])
}
func findResults(request: VNRequest, error: Error?) {
guard let results = request.results as? [VNClassificationObservation] else {
fatalError("Unable to get results")
}
var bestGuess = ""
var bestConfidence: VNConfidence = 0
for classification in results {
if (classification.confidence > bestConfidence) {
bestConfidence = classification.confidence
bestGuess = classification.identifier
}
}
Result.text = "Image is: \(bestGuess) with confidence \(bestConfidence) out of 1"
}
I take it that the problem is that sometimes when the image picker is dismissed, you want to call identifyCatOrDog, but other times you don’t.
One rather crude possibility is this: In the button action method, raise a bool instance property flag so that when didFinishPickingMedia is called you know whether or not to call identifyCatOrDog.
A more sophisticated way would be to divide things off into helper classes so that the operation of the image picker after pressing the catDog button takes place within a completely different code world.

SWIFT - Variable resetting when back from second ViewController

I have been searching for hours here and Google but still didn't find the answer. Everything point to passing variable from a VC to an other but not how to keep variables alive on the VC.
I can pass variables from a VC to an other using multiple methods such as singleton but when I go from second VC to the main VC I'm still facing the same problem.
Exemple you have the main VC which have a label and 2 buttons. When you click one of the button the label text change and then you click the second button to Segue to the second VC. Then when you comeback to the first VC the problem appear: the label is reseted to it's initial text "label". Why?
I tried using global variable in a separate swift file. I said to myself well the value is stored in an other swift file there is no reason why the value of the label reset.. but well it's still resetting.
Thanks so much.
Example in video: https://youtu.be/Wx5blkQqU7E
Very basic example:
varTest.swift
import Foundation
var myVar2: String!
Main ViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet var mylabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func dsfg(_ sender: UIButton) {
performSegue(withIdentifier: "switchForm", sender: self)
}
#IBAction func changeLabeltext(_ sender: UIButton) {
myVar2 = "Good."
mylabel.text = myVar2
}
}
Second ViewController
import UIKit
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnPrint(_ sender: UIButton) {
performSegue(withIdentifier: "returnForm", sender: self)
}
}
I think the problem is that you are not returning back from ViewController2 to ViewController, but you are pushing a new ViewController instance, which will display a new UILabel with its default value. You can create an unwind segue from your second view controller to the first view controller, or you can call dismiss(animated:completion:) on the second view controller. This article can guide you to create an unwind segue.
When you "performSegue", the values in the ViewController class are reset - don't use segue.
Or alternatively: You mention that you tried to use global variables in a separate swift file. Use a temp file stored on the client side instead.
Use these func to create a file and write to it:
//This OVERWRITES already existing files!
func createFileinDocumentDirectory(filename: String){
let blank = ""
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = dir.appendingPathComponent(filename)
do {
try blank.write(to: fileURL, atomically: false, encoding: .utf8)
}
catch let error as NSError {
print("Ooooops! Something went wrong: \(error)")
}
}
}
func writeToFileInDocumentDirectory(filename: String, textToAdd: String){
do {
let dir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! as URL
let url = dir.appendingPathComponent(filename)
try textToAdd.appendLineToURL(fileURL: url as URL)
}
catch {
print("Could not write to file")
}
}

performSegueWithIdentifier not working if called from viewDidLoad

I have a simple app with a loading screen. Here I check for some user details in NSUserDefaults and jump to either the login or the sign up screen.
The viewDidLoad() for the loading screen looks like this:
override func viewDidLoad()
{
super.viewDidLoad()
loadingVM = LoadingVM() as LoadingVM
print("LoadingVC")
checkStoredUser()
}
Here is the checkStoredUser()
func checkStoredUser()
{
storedUserStatus = loadingVM.returnStoredUserStatus()
if(storedUserStatus == true)
{
performSegueWithIdentifier("loadingToLoginVC", sender: self)
}
else
{
performSegueWithIdentifier("loadingToSignUpVC", sender: self)
}
}
As you can see, I decide where to go from here based on what the loadingVM.returnStoredUserStatus() returns. I am sure this returns what it's supposed to return but nothing happens.
Here is the prepareForSegue()
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
print("prepareForSegue")
if(segue.identifier == "loadingToSignUpVC")
{
let signUpViewCotroller = (segue.destinationViewController as! LocalSignUpVC)
}
else if(segue.identifier == "loadingToLoginVC")
{
print("loadingToLoginVC")
let loginViewCotroller = (segue.destinationViewController as! LoginVC)
}
}
I did some digging and found a weird suggestion that seems to be working but It's not very practical not to mention right to do it like this:
func checkStoredUser()
{
storedUserStatus = loadingVM.returnStoredUserStatus()
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1.0 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue())
{
if(self.storedUserStatus == false)
{
self.performSegueWithIdentifier("loadingToSignUpVC", sender: self)
}
else
{
self.performSegueWithIdentifier("loadingToLoginVC", sender: self)
}
}
}
Can anyone explain to me what's going on here, why doesn't this work and how to make it work properly? It's the first time I encounter this and I can't seem to be able to find any info on this.
EXPLANATION:
Your View hasn't appeared yet when you call your checkStoredUser().
EASY FIX:
Put it in viewDidAppear() like this:
override func viewDidAppear(animated:Bool) {
super.viewDidAppear(false)
checkStoredUser()
}

prepareForSegue in SWRevealViewController with Swift

I'm trying to write prepareForSegue in SWRevealViewController with Swift.
Here is my code:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
{
if(segue!.identifier == "segueName")
{
var someText = "Text"
var rvc:newViewController = segue!.destinationViewController as newViewController
rvc.topText = someText
}
}
In newViewController I have topText as NSString
Of course I got nil text because I should make SWRevealViewControllerSegue but I don't know how it should look in Swift
I've found the solution.
First of all need to configure SWRevealControllerSegue. In swift it should looks like:
if(segue.isKindOfClass(SWRevealViewControllerSegue))
{
var rvcs: SWRevealViewControllerSegue = segue as SWRevealViewControllerSegue
var rvc:SWRevealViewController = self.revealViewController()
rvcs.performBlock = {(rvc_segue, svc, dvc) in
var nc:UINavigationController = dvc as UINavigationController
rvc.pushFrontViewController(nc, animated: true)
}
}
Second. XCode beta works bad right now with IBOutlet and segue like this. With variable everything is ok.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.isKindOfClass(SWRevealViewControllerSegue))
{
var rvcs: SWRevealViewControllerSegue = segue as SWRevealViewControllerSegue
var rvc:SWRevealViewController = self.revealViewController()
rvcs.performBlock = {(rvc_segue, svc, dvc) in
var nc:UINavigationController = self.revealViewController().frontViewController as UINavigationController
nc.setViewControllers([dvc], animated: true)
self.revealViewController().setFrontViewPosition(FrontViewPositionLeft, animated: true)
}
}
}
This doesn't work with the latest version. The release notes state:
Took a cleaner approach to storyboard support. SWRevealViewControllerSegue is now deprecated and you should use SWRevealViewControllerSegueSetController and SWRevealViewControllerSeguePushController instead.
There aren't any swift examples anywhere I can find that explain this though.
The performBlock method no longer exists.
Appreciate any help. It seems impossible to do swift without first learning objective c at the moment :)
What was newViewController? This should work:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
{
if(segue.identifier == "segueName")
{
let someText = "Text"
let rvc = segue.destinationViewController as SWRevealViewController
rvc.topText = someText
}
}