Can't create/send iMessage in my extension on any view except the initial view - swift

I'm currently working on an iMessage app which has the users sign in on storyboard view 1 and then allows them to generate/send a message on storyboard view 2. After many attempts, I'm finding that the MSMessage portion of the code just doesn't execute on any view except view 1 - the initial view controller.
I'm sure this is a simple fix but I honestly just can't find out why. Any help would be appreciated.
Message generation/send code:
#IBAction func Testing(_ sender: Any) {
let layout = MSMessageTemplateLayout()
layout.caption = "Hello World"
let message = MSMessage()
message.layout = layout
activeConversation?.insert(message, completionHandler: nil)
}

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
}

Application crashing without information about crash when transitioning to another view controller

I have two view controllers, LoginViewController and TermsAndPrivacyViewController.
On first view controller, there is a button that has IBAction, which opens TermsAndPrivacyViewController. On TermsAndPrivacyViewController I have web view, that loads url I am passing from LoginViewController. So, this is the code(Login view controller):
#IBAction func tosAction(_ sender: Any) {
if let vc = UIStoryboard(name: "Login", bundle: nil).instantiateViewController(withIdentifier: kTOSViewControllerIdentifier) as? TermsAndPrivacyViewController{
vc.url = URL(string: kTOSUrl)
self.navigationController?.pushViewController(vc, animated: true)
}
}
On TermsAndPrivacyViewController, I have this:
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
if let `url` = url {
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
}
}
So, when I hit a button, app crashes SIGABRT message, and nothing else. Also, I don't get any crash report on Firebase Crashlytics (I have detached an app from a debugger first, and produced a crash).
Now, the strange part :/ ... If I put a breakpoint on a first line of tosAction() method, and go step by step (or just let it continue), everything works normally. No crash???
Am I missing something obvious here? What is the reason of crashing? Also, I tried to put Exception Breakpoint but nothing changes. I only get this:
and a console:
so, kinda no information about crash at all.
EDIT
Ok, now the even more strange part :) I just tried app on different phones.
App crashes on iPhone 6s+, iOS 12.1(16B5059d), but it works normally on iPhone 6, iOS 12.0 (16A366)
maybe you use library or framework that not supported by those device.
you must see the error
did you try this?
when the app crashing, in the console press cmd+F and search exception.
now you can see your error
hope to helpful.
Maybe you can use segue methods inside your LoginViewController.
#IBAction func tosAction(_ sender: Any) {
performSegue(withIdentifier: "GoToWeb", sender: nil)
}
}
And call prepareForSegue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "GoToWeb") {
let vc = segue.destination as! TermsAndPrivacyViewController
vc.url = "YOUR_URL"
}
And the code inside TermsAndPrivacyViewController don't change
Edit:
Maybe your not binding well your UIButton, can you verify in the right panel, in the section "Show the connection inspector" if your button is call only once.
To get further information on this type of crashes, open the Breakpoints menu (or press CMD+8), click the plus icon in the bottom left corner and press Exception Breakpoint.... Right click, then edit. Add an action of the type Debugger Command and enter the following:
Reproduce the crash again, this time the console will output a more useful error message.

iOS QR code scanner triggering actions multiple times

I am using the QR code reader code from AppCoda (http://www.appcoda.com/qr-code-reader-swift/#comments) and converted it to Swift 3. The base code works perfectly fine.
However, what I want to achieve is to retrieve a String from the QR reader, store it in a variable, and pass the variable to a following view controller. So I added a bit of code to it to get the following:
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
messageLabel.text = "No barcode/QR code is detected"
return
}
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if supportedBarCodes.contains(metadataObj.type) {
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
if metadataObj.stringValue != nil {
messageLabel.text = metadataObj.stringValue
}
//
//
// CODE I ADDED STARTS BELOW
//
performSegue(withIdentifier: "showMenu", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMenu"{
let tabVc = segue.destination as! UITabBarController
let navVc = tabVc.viewControllers?.first as! UINavigationController
let menuVc = navVc.viewControllers.first as! MenuViewController
menuVc.qrScan = self.messageLabel.text
}
It actually achieves what I wanted it to do, but it somehow triggers the "performSegue" multiple times. The transition animation of the first segue goes halfway, and then the second one happens.
The segue "showMenu" is a manual segue connected from the view controller of the QR Reader view to a tab bar controller that houses a navigation controller and Menu view controller.
Things I've tried:
Print the passed on variable in the viewdidload function of Menu view controller. The string gets printed out twice.
Added a hidden button on the QR reader view and change the segue connection of "showMenu" from the view controller to the button. Removed perform segue from code. While holding the camera in place to scan qr codes, pressing the button performs the intended function and the segue is only triggered once.
With the same setting as (2), I programmatically trigger the button by using a touch up inside event when a qr code is scanned. The segue gets triggered twice.
Added breakpoints for performSegue and the if clause right above it. After I scan something, and press the "continue program execution" button, the program loops between the two breakpoints on and on.
If anyone can enlighten me a bit over here, I would be very grateful. Thanks a bunch for the help in advance.
The issue was fixed by adding the following line of code after the segue was performed:
self.captureSession?.stopRunning()
However, the question of why doesn't unwind segue have a similar issue still remains.
I've just solved the same problem. You have to create an unwind to the previous view.
To do this in the interface builder, you have to ctrl-drag from the controller to the exit in the controller you're actually in (not the one you want to unwind).
Once you have done this, you have to set an identifier to this unwind segue (in your case "showMenu". To do this, you have to the unwind segue from the scenes menu on the left part and set the identifier name on the Attributes inspector.

Is it possible to have 2 times prepare for segue for 2 different view controllers?

I am swift beginner and I am struggling with my first application. Sorry if my question is too basic, but I get an error message in my code here:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let secVC: NavigationViewController = segue.destinationViewController as! NavigationViewController // here is the error
secVC.receiveImeNaSladkarnica = Label1.text!
secVC.KordaA = Shirina.text!
secVC.KordaB = Duljina.text!
secVC.PodImeNaObekt = Label2.text!
I have created 2 different buttons: Navi Me and More Info buttons.
The first one (Navi Me) is connected with another view controller which is called NavigationViewContorller, there I send all of the data I need by using prepare for segue. Everything was working perfect, but now I have created another button which is called (MoreInfo).It is connected with 3rd viewcontroller called MoreInfoViewController. I think I have connected everything fine, but still when I click on the MoreInfo button the app stops working and I get the following error: Thread 1: signal SIGBART in the marked line. I cannot understand why is it breaking when this segue is for another view controller, nt for the MoreInfoViewController. Would you please advice me what to do or provide me with an example how to fix it
I have tried that:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
switch segue.identifier {
//error here-> case "VC1" :
let secVC: NavigationViewController = segue.destinationViewController as! NavigationViewController
secVC.receiveImeNaSladkarnica = Label1.text!
secVC.KordaA = Shirina.text!
secVC.KordaB = Duljina.text!
secVC.PodImeNaObekt = Label2.text!
//error here -> case "VC2" :
let secVC2: MoreInfoViewController = segue.destinationViewController as! MoreInfoViewController
secVC2.receiveImeNaSladkarnica = Label1.text!
secVC2.KordaA = Shirina.text!
secVC2.KordaB = Duljina.text!
secVC2.PodImeNaObekt = Label2.text!
default:
break
It still doesn't work
Each segue is supposed to have an unique string identifier.
For multiple view controllers use a switch statement
switch segue.identifier {
case "vc1" :
// prepare to go to vc1
case "vc2" :
// prepare to go to vc2
default : break
}
Once again my yesterday comment:
Since you are a beginner in Swift please learn first to consider the naming convention that variable names start with a lowercase letter.

How do you make a modal view appear outside of a controller?

I am trying to program a little game just to apply the concepts I learned in this course myself. When the game opens up, I would like for a custom modal view to tell the user how to play. Likewise, when they lose, I want to present a results page, which would be inside an if statement. I've searched all over the internet, and I can't find a way to display these views without an error. All that this video shows is how to show a display a view when a button is pressed; how do I display a custom modal view on command in code? (I am very new to Swift, so try to put it in layman's terms.) Thanks!
import UIKit
var numberValue = 0
let randomInt = getRandomNumber()
class ViewController: UIViewController {
#IBOutlet weak var buttonLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("HowToPlayView") as! HowToPlay
self.presentViewController(vc, animated: true, completion: nil)
// 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 buttonPressed() {
numberValue += 1
updateButtonValue(buttonLabel)
}
}
#IBAction func buttonPressed() {
numberValue += 1
updateButtonValue(buttonLabel)
}
}
That's my view controller. Getting error: Thread 1: EXC_BAD_ACCESS
My view in interface and connections
enter image description here
Ok, let's try a different approach to solve this issue. Above your ViewController you should see three different buttons like this:
Click on the first button and Ctrl + Drag to the view that you want to display and choose display modally. After that is done you should see this arrow appear:
This is called the segue from the first view to the second view and you can call this in your code to transition from one view to the next, but first we have to give our segue an identifier. You can do this by clicking on the arrow and a window should come up like this:
As you can see you will have to fill out the identifier field, and in my case I just named it "myAwesomeSegue".
Lastly, in the first ViewController run this code when you need to present the next view controller:
performSegueWithIdentifier("myAwesomeSegue", sender: nil)
Please note that if you use this method just delete the previous code you had before as this is a brand new approach (so basically delete this code):
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("HowToPlayView") as! HowToPlay
self.presentViewController(vc, animated: true, completion: nil)
Final code for the firstViewController: