2017-12-29 31 views
0

UICollectionViewControllerから別のUICollectionViewControllerにプログラムでデータを渡すときに問題が発生しています。次のようにプログラムでスムーズにデータを渡す問題

現在、私のセットアップは次のとおりです。

  1. データを渡しているUICollectionViewController(RestaurantController

    1A。 UICollectionViewCell(RestaurantCell

    • このUICollectionViewCellは別のカスタムUICollectionViewCellデータを受信して​​いる(RestaurantCollectionViewCell
  2. UICollectionViewController(MenuController

    2aとその中のネストされたUICollectionViewControllerを有しています。 var restaurants = [RestaurantModel]():私のRestaurantCell私はJSONからデータをロードし、それを呼ばれるレストランとして新しい配列を付加していますの内側UICollectionViewCell(MenuCell

。しかし、MenuControllerにレストラン名やレストランオブジェクトをロードしようとすると、var restaurant: RestaurantModel?を使用しても値はゼロになります。私の設定が間違っているか、どこかで愚かな間違いをしていると感じています。おそらく両方。私は各クラスの下に私のコードを貼り付けました。

値はMenuControllerの内側にはnil戻ってきている

print("Restaurant Name:", restaurant?.name)

print("Restaurant Id:", restaurant?.id)

は、問題の原因カスタム委任ですか?

あなたのお手伝いをさせていただきます。内部

RestaurantController:内部

import UIKit 
import FBSDKLoginKit 

class RestaurantController: UICollectionViewController, UICollectionViewDelegateFlowLayout, SWRevealViewControllerDelegate, UISearchBarDelegate, RestaurantDelegate { 

var restaurantCell: RestaurantCell? 

private let restaurantCellId = "restaurantCellId" 

override func viewDidLoad() { 
    super.viewDidLoad() 

    collectionView?.backgroundColor = UIColor.qpizzaWhite() 
    collectionView?.register(RestaurantCell.self, forCellWithReuseIdentifier: restaurantCellId) 


    if self.revealViewController() != nil { 
     navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "icon_menu_24dp").withRenderingMode(.alwaysOriginal), style: .plain, target: self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:))) 
     self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) 
    } 

} 

// FIXME: issue with this...navigationcontroller is presenting, not pushing ontop of stack view 
func didTapRestaurantCell(cell: RestaurantCell) { 
    print("Did Tap Restaurant Cell - Restaurant Controller") 

    let layout = UICollectionViewFlowLayout() 
    let controller = MenuController(collectionViewLayout: layout) 
    navigationController?.pushViewController(controller, animated: true) 

} 

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: restaurantCellId, for: indexPath) as! RestaurantCell 
    cell.delegate = self 
    return cell 
} 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return 1 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 
    return CGSize(width: view.frame.width, height: view.frame.height) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 
    return 1 
} 
} 

RestaurantCell:私のMenuCellの内部

import UIKit 

class MenuController: UICollectionViewController, UICollectionViewDelegateFlowLayout, SWRevealViewControllerDelegate { 

private let menuCellId = "menuCellId" 

var restaurant: RestaurantModel? 
var menuItems = [MenuItemsModel]() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    collectionView?.backgroundColor = UIColor.qpizzaWhite() 
    collectionView?.register(MenuCell.self, forCellWithReuseIdentifier: menuCellId) 
    collectionView?.alwaysBounceVertical = true 

    if self.revealViewController() != nil { 
     navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "menu2-black-32").withRenderingMode(.alwaysOriginal), style: .plain, target: self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:))) 
     self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) 
    } 

    print("Restaurant Name:", restaurant?.name) // returns nil 
    if let restaurantName = restaurant?.name { 
     self.navigationItem.title = restaurantName 
    } 

    loadMenuItems() 

} 

func loadMenuItems() { 
    print("Restaurant Id:", restaurant?.id) // returns nil 
    if let restaurantId = restaurant?.id { 
     print("RestaurantId:", restaurantId) 
    } 
} 

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: menuCellId, for: indexPath) as! MenuCell 
    return cell 
} 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return 3 
} 

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    let layout = UICollectionViewFlowLayout() 
    let controller = MenuDetailsController(collectionViewLayout: layout) 
    navigationController?.pushViewController(controller, animated: true) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 
    return CGSize(width: view.frame.width, height: 120) 
} 

} 

:私のMenuControllerの内部

protocol RestaurantDelegate { 
    func didTapRestaurantCell(cell: RestaurantCell) 
} 


class RestaurantCell: BaseCell, UISearchBarDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 

var delegate: RestaurantDelegate? 
var restaurants = [RestaurantModel]() 
var filteredRestaurants = [RestaurantModel]() 

private let restaurantCollectionViewCell = "restaurantCollectionViewCell" 
private let activityIndicator = UIActivityIndicatorView() 

lazy var searchBar: UISearchBar = { 
    let sb = UISearchBar() 
    sb.placeholder = "Search Restaurant" 
    sb.barTintColor = .white 
    UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = UIColor.qpizzaWhite() 
    sb.delegate = self 
    return sb 
}() 

lazy var collectionView: UICollectionView = { 
    let layout = UICollectionViewFlowLayout() 
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) 
    cv.backgroundColor = .white 
    return cv 
}() 

override func setupViews() { 
    super.setupViews() 
    collectionView.register(RestaurantCollectionViewCell.self, forCellWithReuseIdentifier: restaurantCollectionViewCell) 
    collectionView.delegate = self 
    collectionView.dataSource = self 

    backgroundColor = UIColor.qpizzaRed() 

    addSubview(searchBar) 
    addSubview(collectionView) 

    _ = searchBar.anchor(topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 4, leftConstant: 4, bottomConstant: 0, rightConstant: 4, widthConstant: 0, heightConstant: 50) 

    _ = collectionView.anchor(searchBar.bottomAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0) 

    loadRestaurants() 

} 

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 
    print(searchText) 

    filteredRestaurants = self.restaurants.filter({ (restaruant: RestaurantModel) -> Bool in 

     return restaruant.name?.lowercased().range(of: searchText.lowercased()) != nil 
    }) 

    self.collectionView.reloadData() 
} 

// MARK - Helper Methods 
func loadRestaurants() { 

    showActivityIndicator() 

    APIManager.shared.getRestaurants { (json) in 
     if json != .null { 
      //    print("Restaurant JSON:", json) 
      self.restaurants = [] 

      if let restaurantList = json["restaurants"].array { 
       for item in restaurantList { 
        let restaurant = RestaurantModel(json: item) 
        self.restaurants.append(restaurant) 
       } 
       self.collectionView.reloadData() 
       self.hideActivityIndicator() 
      } 
     } else { 
      print("Error loading JSON into Restaurant ViewController") 
     } 
    } 
} 

func loadImage(imageView: UIImageView, urlString: String) { 

    let imageUrl: URL = URL(string: urlString)! 
    URLSession.shared.dataTask(with: imageUrl) { (data, response, error) in 
     if let error = error { 
      print("Error loading image for Restaurant Controller:", error.localizedDescription) 
     } 
     guard let data = data, error == nil else { return } 

     DispatchQueue.main.async(execute: { 
      imageView.image = UIImage(data: data) 
     }) 
     }.resume() 
} 

func showActivityIndicator() { 
    activityIndicator.frame = CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0) 
    activityIndicator.center = center 
    activityIndicator.hidesWhenStopped = true 
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge 
    activityIndicator.color = UIColor.qpizzaGold() 

    addSubview(activityIndicator) 
    activityIndicator.startAnimating() 
} 

func hideActivityIndicator() { 
    activityIndicator.stopAnimating() 
} 

//MARK: CollectionView Delegate & DataSource Methods 
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: restaurantCollectionViewCell, for: indexPath) as! RestaurantCollectionViewCell 
    let restaurant: RestaurantModel 

    if searchBar.text != "" { 
     restaurant = filteredRestaurants[indexPath.item] 
    } else { 
     restaurant = restaurants[indexPath.item] 
    } 

    cell.restaurantNameLabel.text = restaurant.name 
    cell.restaurantAddressLabel.text = restaurant.address 

    if let logoName = restaurant.logo { 
     let url = "\(logoName)" 
     loadImage(imageView: cell.restaurantLogoImageView, urlString: url) 
    } 

    return cell 
} 


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    if searchBar.text != "" { 
     return self.filteredRestaurants.count 
    } 

    return self.restaurants.count 
} 

//FIXME: Restaurant Name Navigation Title is still not be passed from RestaurantCell to MenuController 
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    print("Did Select Item - Restaurant Cell") 

    let layout = UICollectionViewFlowLayout() 
    let controller = MenuController(collectionViewLayout: layout) 
    controller.restaurant = self.restaurants[indexPath.item] 

    print("Controller", controller.restaurant) // Optional(QpizzaDelivery.RestaurantModel) 
    print("Restaurant:", self.restaurants) // [QpizzaDelivery.RestaurantModel, QpizzaDelivery.RestaurantModel, QpizzaDelivery.RestaurantModel] 
    print("IndexPath:", self.restaurants[indexPath.item]) // QpizzaDelivery.RestaurantModel 

    delegate?.didTapRestaurantCell(cell: self) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 
    return CGSize(width: frame.width, height: 200) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 
    return 0.5 
} 

} 

import UIKit 

class MenuCell: BaseCell { 

let restaurantLabel: UILabel = { 
    let label = UILabel() 
    label.text = "Restaurant King" 
    label.font = UIFont.boldSystemFont(ofSize: 16) 
    label.textColor = .black 
    label.numberOfLines = 0 
    return label 
}() 

let mealImageView: UIImageView = { 
    let iv = UIImageView() 
    iv.image = #imageLiteral(resourceName: "button_chicken").withRenderingMode(.alwaysOriginal) 
    iv.contentMode = .scaleAspectFill 
    iv.clipsToBounds = true 
    return iv 
}() 

let mealDetailsLabel: UILabel = { 
    let label = UILabel() 
    label.text = "Grass fed grass, American cheese, and friez" 
    label.font = UIFont.boldSystemFont(ofSize: 12) 
    label.textColor = UIColor.qpizzaBlack() 
    label.numberOfLines = 0 
    return label 
}() 

let mealPriceLabel: UILabel = { 
    let label = UILabel() 
    label.text = "$12.00" 
    label.font = UIFont.boldSystemFont(ofSize: 12) 
    label.textColor = UIColor.qpizzaBlack() 
    return label 
}() 

let sepereatorView: UIView = { 
    let view = UIView() 
    view.backgroundColor = UIColor.lightGray 
    return view 
}() 


override func setupViews() { 
    super.setupViews() 

    backgroundColor = UIColor.qpizzaWhite() 

    addSubview(restaurantLabel) 
    addSubview(mealImageView) 
    addSubview(mealDetailsLabel) 
    addSubview(mealPriceLabel) 
    addSubview(sepereatorView) 

    _ = mealImageView.anchor(topAnchor, left: nil, bottom: nil, right: rightAnchor, topConstant: 14, leftConstant: 0, bottomConstant: 0, rightConstant: 12, widthConstant: 60, heightConstant: 60) 
    _ = restaurantLabel.anchor(topAnchor, left: leftAnchor, bottom: nil, right: mealImageView.leftAnchor, topConstant: 14, leftConstant: 12, bottomConstant: 0, rightConstant: 10, widthConstant: 0, heightConstant: 20) 
    _ = mealDetailsLabel.anchor(restaurantLabel.bottomAnchor, left: leftAnchor, bottom: nil, right: mealImageView.leftAnchor, topConstant: 12, leftConstant: 12, bottomConstant: 0, rightConstant: 10, widthConstant: 0, heightConstant: 30) 
    _ = mealPriceLabel.anchor(mealDetailsLabel.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 10, leftConstant: 12, bottomConstant: 10, rightConstant: 10, widthConstant: 0, heightConstant: 20) 
    _ = sepereatorView.anchor(nil, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, topConstant: 0, leftConstant: 20, bottomConstant: 4, rightConstant: 20, widthConstant: 0, heightConstant: 1) 


} 
} 
+0

はしばらく行った事が、なぜ 'didSelectItemAtIndexPath'セル内部&いないコントローラがありますか?もう2つの 'MenuController'インスタンスも作成しています.1つはセルの' didSelectItemAtIndexPath'メソッドに、もう1つは 'restaurantDelegate'のdidTapRestaurantCell'メソッドにあり、' restaurant'プロパティを設定していません。最初のものではレストランを設定しましたが、そのコントローラーのインスタンスはちょっとハングアップしていますが、使用されていません。これはnavコントローラがプッシュしたインスタンスではありません。 – mc01

+0

'didSelectItemAtIndexPath 'は' RestaurantCell'の中にあります。なぜなら、 'RestaurantCell'の中にネストされたUICollectionViewControllerがあるからです。私は2つの異なる 'MenuController'を作成していると言っても間違いありません。新しいインスタンスを作成せずに 'RestaurantCell'の中で' MenuController'をどのように参照するかわかりません...あなたはヒントを持っていますか? – a2b123

+0

'RestaurantController'に' MenuController'の最初のインスタンスが必要です。 'Restaurant'の参照を取得するために' RestaurantCell'の 'MenuController'のスタックとNavControllerの2ndインスタンスを私のRestaurant Modelを参照して取得する必要があります。 'MenuController' – a2b123

答えて

1

正しいタイプの変数を宣言するだけです。しかし、実際には、データまたはクラス参照を一度のクラスから次のクラスに移動するために代入(=)を行う必要があります。

func didTapRestaurantCell(cell: RestaurantCell) { 
    print("Did Tap Restaurant Cell - Restaurant Controller") 

    let layout = UICollectionViewFlowLayout() 
    let controller = MenuController(collectionViewLayout: layout) 
    navigationController?.pushViewController(controller, animated: true) 

    // you need to set the restaurant attribute of your new 
    // controller 
    let indexPath = indexPath(for: cell) 
    controller.restaurant = self.restaurants[indexPath.item] 
} 
+0

私の 'RestaurantController'でも'レストラン 'にアクセスするにはどうしたらいいですか?私は 'RestaurantCell'内でその変数を宣言しました。また、 'RestaurantController'の' indexPath.item'へのアクセス権はどのようにして得られますか? @ahalls。 iveはそのメソッドを何回か試してみましたが、それらの部分にアクセスする方法がわかりません。 – a2b123

+0

これは、 'restaurants'配列の要素にCellをマッピングするだけでは不十分です。 – ahalls

+0

最初にセルをどのように埋め込むのかわかりませんか? – ahalls

0

コメントしてくれた皆さん、ありがとうございました。プロトコルを変更してコントローラをパラメータとして渡すことで、私の問題を解決することができました。 RestaurantCell

RestaurantController
protocol RestaurantDelegate { 
    func didTapRestaurantCell(cell: RestaurantCell, withMenuController: MenuController) 
} 


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    print("Did Select Item - Restaurant Cell") 

    let layout = UICollectionViewFlowLayout() 
    let controller = MenuController(collectionViewLayout: layout) 
    controller.restaurant = self.restaurants[indexPath.item] 
    delegate?.didTapRestaurantCell(cell: self, withMenuController: controller) 
} 

:私はCollectionView/wを台無しので、

func didTapRestaurantCell(cell: RestaurantCell, withMenuController controller: MenuController) { 
    print("Did Tap Restaurant Cell - Restaurant Controller") 
    navigationController?.pushViewController(controller, animated: true) 
} 
関連する問題