使用代理/协议传递数据

时间:2015-12-04 15:33:50

标签: ios swift delegates

我有一个带有CollectionReusableView标头的UICollectionView。我想将一个字符串从collecitonview传递到标头,以便标头根据字符串知道要加载哪些数据。我正在尝试使用委托/协议来执行此操作,但在解开可选值时不断意外地发现nil。"这是我的代码:

protocol UserToQuery {
    func thisUser(x: String)
}


class Profile: UICollectionViewController {

    var ownProfile = true
    var delegate:UserToQuery?

    override func viewDidLoad() {
        super.viewDidLoad()

        if self.ownProfile == true {
            let username = PFUser.currentUser()?.username
            self.delegate!.thisUser(username!)
        }
    }
}

以下是Header视图的代码:

class ProfileHeader: UICollectionReusableView, UserToQuery {

    var id1 = String()
    var controller = Profile()


    override func awakeFromNib() {
        print(id1)
        controller.delegate? = self
    }

    func thisUser(x: String) {
        self.id1 = x
        getProfileInfo()
    }

    func getUserData() {
        // code here uses the id1 value to get data
    }

}   

我对委托/协议的理解是:如果要将数据(即字符串)传递到另一个视图,则使接收字符串的视图符合协议。此协议包含一个用于传递字符串的函数,当调用该函数时,它会通知另一个视图该字符串现在可供使用,然后您可以编写所需的代码并使用该字符串。那是准确的吗?

2 个答案:

答案 0 :(得分:1)

ProfileHeader中,您有一个变量controller,它正在创建一个 Profile实例, NOT 故事板中的Profile视图控制器。这就是self.delegate!nilProfile.viewDidLoad()的原因。

我将假设ProfileHeaderProfile视图控制器中的视图。在viewDidLoad中,您应该将代理设置为ProfileHeader。请参阅下面的示例代码(我假设ProfileHeader视图的出口):

编辑:ProfileHeader不是出口,如评论中所述。更新了我的回答以反映出来。

class Profile: UICollectionViewController {

    var ownProfile = true
    var delegate:UserToQuery?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the delegate!
        self.delegate = ProfileHeader()

        if self.ownProfile == true {
            let username = PFUser.currentUser()?.username
                // Delegate won't be nil now
                self.delegate!.thisUser(username!)
            }
        }
    }
}

作为一般流程,视图控制器应该保持对视图的引用,而不是相反。因此,请从controller视图中删除ProfileHeader媒体资源。视图不应该关心控制器控制它的是什么。

答案 1 :(得分:0)

您对协议/委托有一些误解,但在开始iOS开发时这是正常的。

首先,为什么应用程序崩溃: 变量delegate是可选的UserQuery。委托是可选的,但它永远不会在你的代码中设置,所以当你打电话时:

 self.delegate!.thisUser(username!)  

你试图强制展开一个nil变量,这会导致崩溃。

<强>协议

现在,让我们谈谈协议/委托关系。

您有一个UICollectionViewController子类,它嵌入了一个UICollectionView对象。这个UICollectionView将包含页眉,页脚和单元格的混合。因此,您的ProfileHeader课程将显示在UICollectionView

为了填充UICollectionView,您不需要创建自己的协议:已经有两个协议:

  • UICollectionViewDataSource是符合的主要协议,因为它允许您填充集合视图
  • UICollectionViewDelegate用于进一步自定义您的tableview,即自定义外观和处理事件。

由于您的Profile类继承自UICollectionViewController,因此您不必在类名后命名这些协议,因为UICollectionViewController已符合Apple docs中所述的协议

您必须覆盖委托和协议方法才能显示某些数据。我的建议是,在使用页眉和页脚之前,只能使用UICollectionViewCell个对象轻松启动。

通过覆盖方法-collectionView:numberOfItemsInSection:- collectionView:cellForItemAtIndexPath:,您将能够填充集合视图。