Swift 4.2:无法使用简单的委托协议

时间:2019-01-29 12:41:21

标签: ios swift

YouTube Screenrecord of my workflow

FirstViewController

import UIKit

class FirstViewController: UIViewController {
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        let secondViewController = SecondViewController()
        secondViewController.delegate = self
    }
}

extension FirstViewController: DataEnteredDelegate {
    func userDidEnterInformation(info: String) {
        label.text = info
        print("label changed")
    }
}

SecondViewController

import UIKit

protocol DataEnteredDelegate: class {
    func userDidEnterInformation(info: String)
}

class SecondViewController: UIViewController {
    weak var delegate: DataEnteredDelegate? = nil

    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(_ sender: UIButton) {
        print("button tapped")
        delegate?.userDidEnterInformation(info: textField.text!)
    }
}

9 个答案:

答案 0 :(得分:2)

除了缺少代表采用

class FirstViewController: UIViewController, DataEnteredDelegate {
如果视图控制器是在情节提要中设计的,则

不能工作。

let secondViewController = SecondViewController()

创建一个全新的SecondViewController实例,它不是情节提要中的实例,不是,并且所有插座都连接。

您必须使用segueinstantiate并出示第二个视图控制器才能获得对目标控制器的实际引用。

注意:

就Swift协议/委托而言,在控制器之间共享数据是 objective-c-ish
回调关闭更轻巧,更轻巧

答案 1 :(得分:1)

您必须将第一个视图控制器更改为

main.R

原因是第一个视图控制器未实现协议,因此强制转换不会发生

答案 2 :(得分:1)

将协议实施到您的第一个视图控制器。好的做法是扩展控制器,然后将协议的委托方法用于此扩展

extension FirstViewController: DataEnteredDelegate {
    func userDidEnterInformation(info: String) {
        ...
    }
}
接下来,您要为其设置委托的第二个视图控制器可能不是您稍后要介绍的控制器。要正确设置委托,请设置将显示的控制器委托。如果您使用的是segues,请覆盖prepare(for:sender:)并设置向下转换的segue目的地的委托。如果您是手动显示或按下视图控制器,请设置要显示/推动的该控制器的委托。

答案 3 :(得分:0)

检查并更新。

InputStream

答案 4 :(得分:0)

将以下代码用于FirstView Controller

import UIKit

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!

    func userDidEnterInformation(info: String) {
        label.text = info
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let secondViewController = SecondViewController()
        secondViewController.delegate = self
    }

    func userDidEnterInformation(info: String){
      // do your stuff here
    }

}

答案 5 :(得分:0)

我相信您正在面临此问题,因为您将委托设置为nil。

尝试这样设置:

    weak var delegate: DataEnteredDelegate? = FirstViewController.self as! DataEnteredDelegate

答案 6 :(得分:0)

在这里,SecondViewController的直接初始化是不可接受的。此外,经过两个步骤,第二个ViewController将被释放并且不存在。

   override func viewDidLoad() {
    super.viewDidLoad()

    let secondViewController = SecondViewController() // Not the right way to initialize!
    secondViewController.delegate = self. //secondViewController  will be released!
    }

答案 7 :(得分:0)

问题是,您正在创建一个新的SecondViewController,而不是标签栏实际使用的UITabBarController。您需要访问viewDidLoad所使用的第二个视图控制器,而不是分配新的实例,为此,将override func viewDidLoad() { super.viewDidLoad() let secondViewController = self.tabBarController?.viewControllers?.last as? SecondViewController secondViewController.delegate = self } 的实现更改为:

@Override
public void getUsersForTwentyMiles() {
    FirebaseFirestore db = FirebaseFirestore.getInstance();

    double latitude = 33.0076665;
    double longitude = 35.1011336;

    int distance = 20;   //20 milles

    GeoPoint lg = new GeoPoint(latitude, longitude);

    // ~1 mile of lat and lon in degrees
    double lat = 0.0144927536231884;
    double lon = 0.0181818181818182;

    final double lowerLat = latitude - (lat * distance);
    final double lowerLon = longitude - (lon * distance);

    double greaterLat = latitude + (lat * distance);
    final double greaterLon = longitude + (lon * distance);

    final GeoPoint lesserGeopoint = new GeoPoint(lowerLat, lowerLon);
    final GeoPoint greaterGeopoint = new GeoPoint(greaterLat, greaterLon);

    Log.d(LOG_TAG, "local general lovation " + lg);
    Log.d(LOG_TAG, "local lesserGeopoint " + lesserGeopoint);
    Log.d(LOG_TAG, "local greaterGeopoint " + greaterGeopoint);

    //get users for twenty miles by only a latitude 
    db.collection("users")
            .whereGreaterThan("location", lesserGeopoint)
            .whereLessThan("location", greaterGeopoint)
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (QueryDocumentSnapshot document : task.getResult()) {

                            UserData user = document.toObject(UserData.class);

                            //here a longitude condition (myLocation - 20 <= myLocation <= myLocation +20)
                            if (lowerLon <= user.getUserGeoPoint().getLongitude() && user.getUserGeoPoint().getLongitude() <= greaterLon) {
                                Log.d(LOG_TAG, "location: " + document.getId());
                            }                        
                        }  
                    } else {
                        Log.d(LOG_TAG, "Error getting documents: ", task.getException());
                    }
                }
            });
}

答案 8 :(得分:0)

enter image description here

您的UIWndow的rootViewController是UITabBarController,您共享的YouTube视频链接上可以看到它UITabBarController,因此您需要使用此代码段从该位置获取SecoundViewController

class FirstViewController: UIViewController {

@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let rootController = appDelegate.window?.rootViewController as! UITabBarController
    if let viewControllers = rootController.viewControllers {
        if viewControllers.count > 0 {
            if let secondViewController = viewControllers[1] as? SecondViewController {
                secondViewController.delegate = self
            }
        }
    }
}}

这样您的代表将不会为零。

在当前解决方案中,您的SecondViewController获得了新实例,但未从情节提要中加载,并且委托中没有nil,因此委托方法无法调用。

// you have nil refrence to delegate check it here
if (self.delegate != nil) {
    self.delegate?.userDidEnterInformation(info: textField.text ?? "")
}

希望有帮助。