instantiateViewControllerWithIdentifier 之后的 IBOutlet nil

Posted

技术标签:

【中文标题】instantiateViewControllerWithIdentifier 之后的 IBOutlet nil【英文标题】:IBOutlet nil after instantiateViewControllerWithIdentifier 【发布时间】:2015-02-25 23:57:18 【问题描述】:

不确定我在这里做错了什么。我已经列出了我的问题和我的代码。很想得到一些帮助。

谢谢!

问题:

VC1 提供 VC2。 来自 VC1 的 IBOutlets 现在为零。 VC2 解散回 VC1。 VC1 中的 IBOutlets 仍然为零。

VC1 从 flickR 加载图片网格。 VC2 有一个 searchBar 控制器,当 VC2 被关闭时,它会运行 flickR 查询。在我的 self.collectionView.reload() 失败之前,因为 self.collectionView 是 nil :(

VC1

import UIKit

class MainViewController: UIViewController, UICollectionViewDelegate,    UICollectionViewDataSource 

@IBOutlet var collectionView: UICollectionView!
@IBOutlet var searchMask: UIView!

let api_key = "f87357398a52b80e0c9f76bf94c8ee94"

var flickResults:NSMutableArray! = NSMutableArray()
var titleResults:NSMutableArray! = NSMutableArray()

override func viewDidLoad() 
    super.viewDidLoad()
     loadPhotos("Brasil")
    // Do any additional setup after loading the view.


override func viewDidAppear(animated: Bool) 
    super.viewDidAppear(animated)


func loadPhotos(searchString: String) 
    let flickr:FlickrHelper = FlickrHelper()
    println("Collection: \(self.collectionView)")
    flickr.request(searchString, per_page: 50, completion:  (searchStr, flickrPhotos, photoTitle) -> () in
        dispatch_async(dispatch_get_main_queue(), 
            self.flickResults = flickrPhotos
            self.titleResults = photoTitle
            self.collectionView.reloadData()
        )
    )


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


override func preferredStatusBarStyle() -> UIStatusBarStyle 
    return UIStatusBarStyle.LightContent



func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 

    let cell: PhotoCell = self.collectionView.dequeueReusableCellWithReuseIdentifier("photoCell", forIndexPath: indexPath) as PhotoCell
    cell.photoImageView.alpha = 0
    let queue:dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

    dispatch_async(queue, 
        let searchURL: String = self.flickResults.objectAtIndex(indexPath.item) as String
        let title: String = self.titleResults.objectAtIndex(indexPath.item) as String
        let image: UIImage = self.loadImage(searchURL)
        dispatch_async(dispatch_get_main_queue(), 
            UIView.animateWithDuration(0.5, animations: 
                cell.photoImageView.image = image
                cell.photoTitle.text = title.capitalizedString
                cell.photoImageView.alpha = 1
            )

        )
    )

    insertBlurView(cell.titleMask, UIBlurEffectStyle.Dark)

    return cell


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return self.flickResults.count


func loadImage(imageUrl: String) -> UIImage
    let url = NSURL(string: imageUrl)
    let data = NSData(contentsOfURL: url!)
    let image = UIImage(data: data!)
    return image!



@IBAction func searchButtonPressed(sender: UIButton) 
    let storyboard = UIStoryboard(name: "Main", bundle: nil);
    let vc: SearchViewController = storyboard.instantiateViewControllerWithIdentifier("Search") as SearchViewController
    providesPresentationContextTransitionStyle = true
    definesPresentationContext = true
    vc.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
    self.presentViewController(vc, animated: false, completion: nil)



VC2

 import UIKit


 class SearchViewController: UIViewController, UITextFieldDelegate, UISearchBarDelegate, UICollectionViewDelegate 


@IBOutlet var searchMask: UIView!
@IBOutlet var searchField: UITextField!
@IBOutlet var searchBar: UISearchBar!

override func viewDidLoad() 
    super.viewDidLoad()
    insertBlurView(self.searchMask, UIBlurEffectStyle.Dark)


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


@IBAction func exitTap(sender: UIButton) 
    self.dismissViewControllerAnimated(true, completion: nil)



func searchBarSearchButtonClicked(searchBar: UISearchBar) 
    self.dismissViewControllerAnimated(true, completion: 
        let mainvc = self.storyboard?.instantiateViewControllerWithIdentifier("Main") as MainViewController
        mainvc.loadPhotos(searchBar.text)
    )
  

【问题讨论】:

使用 performSegueWithIdentifier() 不会给您带来任何问题。不确定 instantiateViewControllerWithIdentifier 是否会导致错误。 你展示了VC2之后怎么知道VC1的outlets是nil(应该不是这样)?为什么,在 searchBarSearchButtonClicked 方法中,您要创建 MainViewController 的新实例?你不应该那样做。在您要返回的控制器中调用方法的标准方法是使用委托。 感谢您的回复 :) 在 VC2s viewDidLoad() 函数中,我运行这段代码 println(MainViewController().controllerView) 来查看它是否存在,但它总是返回 nil。我将尝试委托方法并更新此帖子。 你得到 nil 是因为 MainViewController() 只是分配了一个新的视图控制器,而不是在故事板中制作的一个连接了它的插座。 能够弄清楚,再次感谢。我在下面发布了一个答案。如果您发现任何错误,请告诉我。干杯 【参考方案1】:

感谢 rdelmar,我能够使用协议解决这个问题。

这是我添加的内容:

搜索代理 SearchDelegate 函数 runSearch()

VC1

class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, SearchDelegate   

func runSearch(searchString: String) 
    loadPhotos(searchString)
 


VC2

protocol SearchDelegate 
    func runSearch(searchString: String)
 

class SearchViewController: UIViewController, UITextFieldDelegate, UISearchBarDelegate, UICollectionViewDelegate 


@IBOutlet var searchMask: UIView!
@IBOutlet var searchField: UITextField!
@IBOutlet var searchBar: UISearchBar!

var delegate: SearchDelegate?

func searchBarSearchButtonClicked(searchBar: UISearchBar) 
    delegate?.runSearch(searchBar.text)
    self.dismissViewControllerAnimated(true, completion:nil)


【讨论】:

以上是关于instantiateViewControllerWithIdentifier 之后的 IBOutlet nil的主要内容,如果未能解决你的问题,请参考以下文章

Swift:prepareForSegue 和 instantiateViewController 之间的区别

动态呈现 ViewController

导航项未添加

无法关闭 Popover UITableViewController

视图的奇怪行为

幽灵视图控制器