XCODE SWIFT如何在按下按钮之后但在另一个文件/类中执行代码?

如何解决XCODE SWIFT如何在按下按钮之后但在另一个文件/类中执行代码?

我正在使用MapKit,用户可以添加注释。他们可以点击屏幕,提示他们是否要使用UIAlert添加注释,如果他们回答“是”,它将显示一个视图控制器,以便用户可以输入有关注释的信息,例如位置名称,描述等。该视图控制器顶部有一个“ Done” BarButtonItem,以确认他们输入的信息并创建注释。

@IBAction func doneButtonpressed(_ sender: UIBarButtonItem) {
        doneButtonHasBeenpressed = true
        dismiss(animated: true,completion: nil)
}

问题是,必须在原始视图控制器的“ touchesEnded”函数中创建注释,该注释将用户发送到视图控制器,在此他们输入注释信息,因为这是从()获取CLCoordinate2D的地方使用touchesEnded)。正是在相同的touchsEnded函数中,我将用户发送到下一个视图控制器。这是touchesEnded代码及其使用的辅助函数

override func touchesEnded(_ touches: Set<UITouch>,with event: UIEvent?) {
    
    if let touch = touches.first {
        let touchLocation = touch.location(in: view)
        
        // Converts CGPoint coordinates and UIView to CLLocationCordinate2D (map coordinates) Remember to rename if addButtonpressed order of creation of annotation gets changed!
        let coordinatesTouchedToCreateAnnotation = mapView.convert(touchLocation,toCoordinateFrom: view)
        
        if userIsAllowedToAddAnnotation {
            
            let alertController = UIAlertController(title: "Confirm",message: "Are you sure you want to add a jump location here?",preferredStyle: .alert)
            
            let noAction = UIAlertAction(title: "No",style: .cancel,handler: nil)
            
            let yesAction = UIAlertAction(title: "Yes",style: .default) { (action) in
                
                // Segue takes user to JumpSpotCreatorController to input information about the jump location
                self.performSegue(withIdentifier: "CreateJumpSpot",sender: self)
                
                
                    if self.jumpSpotCreatorController.doneButtonHasBeenpressed == true {

                        self.jumpSpotCreatorController.doneButtonHasBeenpressed = false
                        self.createJumpSpotAnnotation(coordinatesDeterminedByTouch: coordinatesTouchedToCreateAnnotation)
                        self.userIsAllowedToAddAnnotation = false
                        self.tapToAddJumpSpotLabel.isHidden = true

                    }
                
                
                
            }
            alertController.addAction(noAction)
            alertController.addAction(yesAction)
            
            present(alertController,animated: true,completion: nil)
            
        } else {
            return
        }
    }
}

// Force unwrap is okay because this will only be called if 'Done' button is pressed in the JumpSpotCreatorController,which mandates that those inputs not be nil.
func createJumpSpotAnnotation(coordinatesDeterminedByTouch: CLLocationCoordinate2D) {
    mapView.addAnnotation(JumpSpotAnnotation(name: jumpSpotCreatorController.nameTextField.text!,coordinate: coordinatesDeterminedByTouch,estimatedHeight: jumpSpotCreatorController.estimatedHeightTextField.text!,locationDescription: jumpSpotCreatorController.descripitionTextView.text,warnings: jumpSpotCreatorController.warningsTextView.text ?? "",image: jumpSpotCreatorController.jumpSpotimageView.image ?? UIImage(imageLiteralResourceName: "Image-1")))
}

如您所见,在touchesEnded函数中创建注释的代码块(位于我向alertController添加动作的位置的上方,以防您找不到它。大约4行),将立即执行,而不是在需要时(在我的其他视图控制器(JumpSpotCreatorController)中按下“完成”按钮)。我尝试使用doneButtonHasBeenpressed变量修复该问题,但这没有什么区别(出于明显的原因)。仅在按下“完成”按钮后如何执行?我不能将另一个视图控制器初始化为主对象中的一个对象(带有touchesEnded的对象是主要对象),因为它将在两个视图控制器之间创建无限循环的引用。 dispatchQueue可以以某种方式提供帮助吗?我已经研究了几个小时,但还不太清楚如何在这里应用它。非常感谢。

解决方法

如果我做对了,那么您正在尝试获得如下内容:

Class A {
   weak var referenceToB: B?
   @IBAction func buttonAction(_ sender: Any) {
      guard var referenceToB = referenceToB else {
          fatalError("referenceToB not set!")
      }
      referenceToB!.otherFunction()
   }
}
Class B {
   func otherFunction() {
      //stuff
   }
}

在您的情况下,实例化VC之后,将引用分配给包含所需功能的类的对象。

,

我不会100%跟踪,但这会有所帮助:

  • 按钮被点击,您处于“ A”状态

  • “ A”调用B做某事,并且

  • “ A”带有对自身的引用

(也就是说,在B中的该调用中“添加参数”,这是类“ A”的变量。假设该变量的名称为“ callMeWhenYou'reFinished”)

  • 当“ B”完成其应做的工作

  • 只需调用callMeWhenYou'reFinished#WhateverFunction

...然后走开!

作为一种“一般编程问题”(忘记了Swift中的可用功能,等等),您只是在描述“回调”。如果我正确地跟随了您,希望对您有所帮助!


进一步:

具有某种循环引用是完全可以的。 (因此,A知道有关B的信息,而B则得到了对A中某物的回调。)

很显然,如果您随后错误地进行了无限循环,那就是无限循环。但是“意外地造成无限循环”与您是否具有单独的类,引用等完全无关。

,

有很多方法可以做到这一点-每种都有优点和缺点。

这种方法使用委托/协议模式。

我们定义了一个协议,该协议将允许类在其委托类中执行函数:

// protocol / delegate pttern
protocol JumpSpotDelegate: class {
    func createJumpSpotAnnotation(_ name: String,estimatedHeight: String,locationDescription: String,warnings: String,image: UIImage?)
    func cancelAnnotation()
}

在具有您的地图视图的控制器中,我们遵守该委托:

class MapViewController: UIViewController,JumpSpotDelegate {

JumpSpotCreatorController中,我们设置了一个delegate属性:

class JumpSpotCreatorController: UIViewController {
    weak var delegate: JumpSpotDelegate?

当我们导航到JumpSpotCreatorController时,我们将self分配为其委托:

    override func prepare(for segue: UIStoryboardSegue,sender: Any?) {
        // make sure we're acting on the correct segue
        if segue.identifier == "CreateJumpSpot",let vc = segue.destination as? JumpSpotCreatorController {
            // set the delegate in the JumpSpotCreatorController we're navigating to
            vc.delegate = self
        }
    }

JumpSpotCreatorController中,点击完成按钮后,我们通过委托函数告诉地图控制器:

    delegate?.createJumpSpotAnnotation(name,estimatedHeight: estimatedHeight,locationDescription: description,warnings: warnings,image: img)

在这里。我通过let语句添加了对象来编写此代码……我希望您将它们作为@IBOutlet连接:

// protocol / delegate pttern
protocol JumpSpotDelegate: class {
    func createJumpSpotAnnotation(_ name: String,image: UIImage?)
    func cancelAnnotation()
}

class MapViewController: UIViewController,JumpSpotDelegate {
    
    // this will hold the touch point while we navigate to and back from the JumpSpotCreatorController
    var lastTouch: CLLocationCoordinate2D?
    
    let mapView: MKMapView!
    
    var userIsAllowedToAddAnnotation = true
    let tapToAddJumpSpotLabel = UILabel()
    
    override func touchesEnded(_ touches: Set<UITouch>,with event: UIEvent?) {
        
        if let touch = touches.first {
            let touchLocation = touch.location(in: view)
            
            // Converts CGPoint coordinates and UIView to CLLocationCordinate2D (map coordinates)
            // store in class property
            self.lastTouch = mapView.convert(touchLocation,toCoordinateFrom: view)
            
            if userIsAllowedToAddAnnotation {
                
                let alertController = UIAlertController(title: "Confirm",message: "Are you sure you want to add a jump location here?",preferredStyle: .alert)
                
                let noAction = UIAlertAction(title: "No",style: .cancel,handler: nil)
                
                let yesAction = UIAlertAction(title: "Yes",style: .default) { (action) in
                    
                    // Segue takes user to JumpSpotCreatorController to input information about the jump location
                    self.performSegue(withIdentifier: "CreateJumpSpot",sender: self)
                    
                }
                alertController.addAction(noAction)
                alertController.addAction(yesAction)
                
                present(alertController,animated: true,completion: nil)
                
            } else {
                return
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue,let vc = segue.destination as? JumpSpotCreatorController {
            // set the delegate in the JumpSpotCreatorController we're navigating to
            vc.delegate = self
        }
    }

    // called by Button action in JumpSpotCreatorController
    func createJumpSpotAnnotation(_ name: String,image: UIImage?) {
        // the coordinate parameter was stored in our class property "lastTouch"
        guard let lastTouch = self.lastTouch else {
            // self.lastTouch was not set!
            return
        }
        mapView.addAnnotation(JumpSpotAnnotation(name: name,coordinate: lastTouch,image: image ?? UIImage(imageLiteralResourceName: "Image-1")))
        
        self.userIsAllowedToAddAnnotation = false
        self.tapToAddJumpSpotLabel.isHidden = true

        // pop from JumpSpotCreatorController back to self
        self.navigationController?.popViewController(animated: true)
    }
    
    // I'm assuming you would also have a Cancel button?
    func cancelAnnotation() {
        self.lastTouch = nil
        // pop from JumpSpotCreatorController back to self
        self.navigationController?.popViewController(animated: true)
    }

}

class JumpSpotCreatorController: UIViewController {
    weak var delegate: JumpSpotDelegate?

    let nameTextField = UITextField()
    let estimatedHeightTextField = UITextField()
    let descripitionTextView = UITextView()
    let warningsTextView = UITextView()
    let jumpSpotImageView = UIImageView()
    
    @IBAction func doneBtnTapped() {
        // presumably,you'll validate all these
        guard let name = nameTextField.text,let estimatedHeight = estimatedHeightTextField.text,let description = descripitionTextView.text,let warnings = warningsTextView.text,let img = jumpSpotImageView.image else {
                // notify user required fields were blank
                return
        }
        
        delegate?.createJumpSpotAnnotation(name,image: img)
    }
    
    @IBAction func cancelBtnTapped() {
        delegate?.cancelAnnotation()
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?