How to fix error: memory read failed for 0x0 - swift4.2

I have clicked login button and the message throw in notification center and a country picker opened and when I click on button in country picker log in view Controller must be opened but it throws an error:
memory read failed for 0x0 ........
this error comes in between obtaining controller object and present.
what should I do now??
I am using Xcode 10.1 and Swift 4
#objc func showSpinningWheel(_ notification: NSNotification) {
if whichbuttonclick == true
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(vc, animated: true, completion: nil)
}
else
{
self.performSegue(withIdentifier: "Register", sender: self)
}
}
I expect it to jump over login controller but it throws error.

This is how i add Notification Observer :
NotificationCenter.default.addObserver(
self,
selector: #selector(self.showSpinningWheel(:)),
name: Notification.Name(rawValue: "opencontrollermessagenotification"),
object: nil
)
#objc func showSpinningWheel( notification: NSNotification)
{
if whichbuttonclick == true {
self.performSegue(withIdentifier: "Login", sender: self)
} else {
self.performSegue(withIdentifier: "Register", sender: self)
}
}
and This is how i Post it :
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "opencontrollermessagenotification"), object: nil, userInfo: nil)

Related

RxSwift trigger observable on button tap

I am creating a custom observable that will present a UIAlertController which would like to trigger an API Call when pressed. However, I can't seem to get the Alert to pop unless I manually subscribe to it. Is there a way to get this triggered from the viewModel?
MyController.swift
class MyController: UIViewController {
#IBOutlet weak var nextBarButton: UIBarButtonItem!
var viewModel: ViewModel!
override func viewDidLoad() {
super.viewDidLoad()
viewModel = ViewModel( nextBarButton.rx.tap.asDriver(), alertController()asDriver(onErrorJustReturn: ""))
}
func alertController() -> Observable<String> {
return Observable.create { [weak alert = self] observer in
guard let alert = alert else {
observer.on(.completed)
return Disposables.create()
}
let alertVc = UIAlertController(title: "My Title", message: "My Message", preferredStyle: .alert)
let submit = UIAlertAction(title: "Continue", style: .default) { _ in
observer.onNext("Test")
observer.on(.completed)
}
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in
observer.on(.completed)
}
alertVc.addAction(cancel)
alertVc.addAction(submit)
alert.present(alertVc, animated: true, completion: nil)
return Disposables.create {
alertVc.dismiss(animated: true, completion: nil)
}
}
}
}
ViewModel.swift
public final class ViewModel {
init(_ manager: SessionManager, _ trigger: Driver<Void>, _ alert: Driver<String>) {
let _ = trigger.withLatestFrom(alert)
.flatMap { text in
return manager.rx
.request(urlRequest: Api.test)
.retry(3)
.asDriverOnErrorJustComplete()
}
}
}
You forgot to subscribe() in your ViewModel and you should flatMapLatest when chaining events from UIButton. It should look like:
public final class ViewModel {
init(_ manager: SessionManager, _ trigger: Driver<Void>, _ alert: Driver<String>) {
let _ = trigger.flatMapLatest{ alert }
.flatMap { text in
return manager.rx
.request(urlRequest: Api.test)
.retry(3)
.asDriverOnErrorJustComplete()
}
.subscribe()
}
}

My function in my main view controller is not working

I´m trying to use a function that I wrote in my main viewController, this is it.
func displayAlert(title: String, message: String)
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction((UIAlertAction(title: "Ok", style: .Default, handler:
{ (action) -> Void in
self .dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(alert, animated: true, completion: nil)
}
I´m trying to use it on other viewController call viewControllerRegistro, for some reason is not working. this is it...
#IBAction func signUp(sender: AnyObject)
{
//checar que el usuario copero al poner su correo electronico y su contraseña
if usernameRegistro.text == "" || correoRegistro.text == "" || contraseñaRegistro.text == ""
{
ViewController().displayAlert("Informando Error", message: "Porfavor completa los cuadros de registro")
}
any help?
I´m using xcode 7.0 beta 6 with swift 2
ViewController() creates a new ViewController instance. That view controller is not part of your view hierarchy (because you just created it, without adding it anywhere).
You have to call that method on the view controller that is currently visible. Because of that the function should not be part of your MainViewController class. It should be part of the ViewController class that needs it. Or if you need it in multiple view classes you could add the function to an extension of UIViewController:
extension UIViewController {
func displayAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction((UIAlertAction(title: "Ok", style: .Default, handler:
{ (action) -> Void in
self .dismissViewControllerAnimated(true, completion: nil)
})))
presentViewController(alert, animated: true, completion: nil)
}
}
With this extension you can call displayAlert on any UIViewController and UIViewController subclasses.

Error when loading UIAlertController

I want to load an alert when internet connection is not available. The function for checking internet connection is ready but I cannot load the alert. So I just put the alert code in viewDidLoad without any conditions etc. and got this error:
Warning: Attempt to present UIAlertController: 0x12752d400 on x.ViewController: 0x127646f00 whose view is not in the window hierarchy!
Code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Delegates
verificationCode.delegate = self
let alert = UIAlertController(title: "Oops!", message:"This feature isn't available right now", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { _ in }
alert.addAction(action)
self.presentViewController(alert, animated: true) {}
if (!Util.isConnectedToNetwork()) {
self.isConnected = false
}
}
Could you tell me how to fix it?
The error tells you what has gone wrong.
You are trying to present a view controller in viewDidLoad except the view, although loaded, is not in any hierarchy. Try putting the code in the viewDidAppear method, which is called after the view appears on screen, and is in a view hierarchy.
Swift 4 Update
I think this could help you for your problem :
override func viewDidLoad() {
super.viewDidLoad()
verificationCode.delegate = self
let alert = UIAlertController(title: "Oops!", message:"This feature isn't available right now", preferredStyle: .alert)
let delete = UIAlertAction(title: "OK", style: .default) { (_) in }
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alert.addAction(cancelAction)
alert.addAction(delete)
alert.popoverPresentationController?.sourceView = sender as UIView
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
if (!Util.isConnectedToNetwork()) {
self.isConnected = false
}
}
Move the code to viewDidAppear from viewDidLoad
override func viewDidAppear(animated: Bool) {
// Delegates
verificationCode.delegate = self
let alert = UIAlertController(title: "Oops!", message:"This feature isn't available right now", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { _ in }
alert.addAction(action)
self.presentViewController(alert, animated: true) {}
if (!Util.isConnectedToNetwork()) {
self.isConnected = false
}
}

Display alert keeps logging me out after error message on xcode using swift

I'm creating an Instagram like app, and whenever I dismiss the display alert that is displayed when an image or text is missing, it logs me out and logs me back in. How can I make it so that when I click "ok", only the display alert goes away and doesn't log me out?
Here is my image posting view control code:
import UIKit
import Parse
import Foundation
class PostViewControllerPage1: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
func displayAlert(title:String, error:String) {
var alert = UIAlertController(title: title, message: error, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
var photoSelected:Bool = false
#IBOutlet weak var imageToPost: UIImageView!
#IBAction func chooseImage(sender: AnyObject) {
var image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
image.allowsEditing = false
self.presentViewController(image, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
println("Image selected")
self.dismissViewControllerAnimated(true, completion: nil)
imageToPost.image = image
photoSelected = true
}
#IBOutlet weak var imageDescription: UITextField!
#IBAction func postImage(sender: AnyObject) {
var error = ""
if (photoSelected == false) {
error = "Please select an image to post"
} else if (imageDescription.text == "") {
error = "Please enter a message"
}
if (error != "") {
displayAlert("Cannot Post Image", error: error)
}
else {
var post = PFObject(className: "Post")
post["Title"] = imageDescription.text
post.saveInBackgroundWithBlock{(success: Bool, error: NSError?) -> Void in
if success == false {
self.displayAlert("Could Not Post Image", error: "Please try again later")
} else {
let imageData = UIImagePNGRepresentation(self.imageToPost.image)
let imageFile = PFFile(name: "image.png", data: imageData)
post["imageFile"] = imageFile
post.saveInBackgroundWithBlock{(success: Bool, error: NSError?) -> Void in
if success == false {
self.displayAlert("Could Not Post Image", error: "Please try again later")
} else {
println("posted successfully")
}
}
}
}
}
}
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.
}
}
What am I doing wrong?
Here is my login code, because I feel like that might be a part of the issue:
import Foundation
import Parse
import UIKit
import Bolts
class LoginViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var loginStatusLabel: UILabel!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var loginButton: 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 loginButtonPress(sender: AnyObject) {
login(emailTextField.text, password: passwordTextField.text)
}
func login(email: String, password: String)
{
PFUser.logInWithUsernameInBackground(email, password: password)
{
(user: PFUser?, error: NSError?) -> Void in
if user != nil
{
user!.fetchInBackground()
if user!.objectForKey("emailVerified") as! Bool
{
self.loginStatusLabel.text = "Success!"
println("successfulLogin")
self.performSegueWithIdentifier("login", sender: self)
}
else if !(user!.objectForKey("emailVerified") as! Bool)
{
self.loginStatusLabel.text = "Verify your email address!"
}
else // status is "missing"
{
//TODO: Handle this error better
self.loginStatusLabel.text = "Verification status: Missing"
}
}
else
{
if let errorField = error!.userInfo
{
self.loginStatusLabel.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
}
}
}
}
override func viewDidAppear(animated: Bool) {
if PFUser.currentUser() != nil {
self.performSegueWithIdentifier("login", sender: self)
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
override func viewWillAppear(animated: Bool) {
self.navigationController?.navigationBarHidden = true
}
override func viewWillDisappear(animated: Bool) {
self.navigationController?.navigationBarHidden = false
}
}
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.dismissViewControllerAnimated in this line will dismiss view controller that show alert and not an alert itself. So all you have to do is comment or delete this line of code

Saving an image to special album swift

I want to add a new photo to certain album, I'm trying to do it like that:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
albumName = "\(data.objectAtIndex(indexPath.row))"
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Choose image source", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
actionSheet.addAction(UIAlertAction(title: "Take Photo", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
imagePickerController.sourceType = UIImagePickerControllerSourceType.Camera
self.presentViewController(imagePickerController, animated: true, completion: {})
}))
actionSheet.addAction(UIAlertAction(title: "Camera Roll", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
imagePickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
self.presentViewController(actionSheet, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let image:UIImage = info[UIImagePickerControllerOriginalImage] as UIImage
var groupToAddTo: ALAssetsGroup = ALAssetsGroup()
self.library.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupAlbum),
usingBlock: {
(group: ALAssetsGroup!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumName){
groupToAddTo = group
}
},
failureBlock: {
(myerror: NSError!) -> Void in
println("error occurred: \(myerror.localizedDescription)")
})
var img: CGImageRef = image.CGImage
self.library.writeImageToSavedPhotosAlbum(img, metadata: nil, completionBlock: {
(assetUrl: NSURL!, error: NSError!) -> Void in
if error.code == 0 {
println("saved image completed: \(assetUrl)")
self.library.assetForURL(assetUrl, resultBlock: { (asset: ALAsset!) -> Void in
groupToAddTo.addAsset(asset)
return
}, failureBlock: {
(myerror: NSError!) -> Void in
println("error occurred: \(myerror.localizedDescription)")
})
} else {
println("saved image failed. \(error.localizedDescription) code \(error.code)")
}
} )
}
However, when I run this code, I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
in this line:
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumName){
So, the question is that, how to save an image to certain album in swift?
I am betting albumName is an optional value.
You should put an if statement to judge if almbumName is nil. When it's nil, create a newalbum name on your iPhone.
First:
if group != nil {
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumNames[indexPath.row]){
groupToAddTo = group
}
}
Second, when error = nil your app will crash because of "if error.code == 0." Do "if error == nil" instead.

Resources