2017-12-29 9 views
0

한 UICollectionViewController에서 다른 UICollectionViewController로 프로그래밍 방식으로 데이터를 전달하는 데 문제가 있습니다. 다음프로그래밍 방식으로 데이터를 전달하는 문제

내 현재 설정은 다음

  1. 데이터 (RestaurantController)

    1A 전달된다 UICollectionViewController. UICollectionViewCell는 (RestaurantCell)

    • 이 UICollectionViewCell 데이터 (MenuController)

      2A를받는 다른 사용자 UICollectionViewCell (RestaurantCollectionViewCell)

  2. UICollectionViewController와 그 안에 내포 UICollectionViewController있다. UICollectionViewCell (MenuCell) 내 RestaurantCell 내가로드하고 JSON에서 데이터라는 레스토랑으로 그것을 새로운 배열을 추가의 내부

: var restaurants = [RestaurantModel](). 그러나 레스토랑 이름이나 MenuController에있는 레스토랑 객체를로드하려고 시도 할 때 var restaurant: RestaurantModel?을 사용하면 아무런 가치가 없습니다. 내 설치가 잘못되었거나 어리석은 실수를 저지르고 있다는 느낌이 들었습니다. 아마 둘 다. 각 클래스에 아래 코드를 붙여 넣었습니다.

어디 값은 MenuController의 내부 전무를 반환됩니다

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' 셀 및하지 컨트롤러입니까? 또한 두 개의 다른'MenuController' 인스턴스를 만들고 있는데, 하나는 셀의'didSelectItemAtIndexPath' 메소드에 넣고, 다른 하나는'restaurantDelegate'' didTapRestaurantCell' 메소드에서'restaurant' 속성을 설정하지 않는 것입니다. 처음에는 레스토랑을 설정했지만, 컨트롤러 인스턴스는 조금만 돌아 다니고 & 사용되지 않습니다. 이것은 nav 컨트롤러에 의해 푸시 된 것이 아닙니다. – mc01

+0

'didSelectItemAtIndexPath '는'RestaurantCell' 내부에 중첩 된 UICollectionViewController가 있기 때문에'RestaurantCell' 안에 있습니다. 당신은 두 개의 다른'MenuController'를 생성하고 있다고 말하면 정확합니다. 새 인스턴스를 만들지 않고'RestaurantCell' 내부에서'MenuController'를 참조하는 방법을 모르겠습니다 ... 팁이 있습니까? – a2b123

+0

'RestaurantController'에'MenuController'의 첫 번째 인스턴스가 필요합니다. 'RestaurantCell'의 스택에있는 Nav 컨트롤러와'MenuController'의 두 번째 인스턴스를 (내 Restaurant Model을 참조하는) 'Restaurant'의 참조를 얻기 위해 my '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. 필자는 그 방법을 여러 번 시도했지만, 그 조각에 접근하는 방법을 모르겠다. – a2b123

+0

이것으로 충분하지 않다. 셀을'restaurants' 배열의 요소에 매핑해야한다. – ahalls

+0

처음에 셀을 채우는 방법을 모르겠습니까? – ahalls

0

감사의 말을 전하고 도와 주신 모든 분들께 감사드립니다.프로토콜을 변경하고 컨트롤러를 매개 변수로 전달하여 문제를 해결할 수있었습니다. RestaurantCell에서

:

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) 
} 

RestaurantController에서 :

func didTapRestaurantCell(cell: RestaurantCell, withMenuController controller: MenuController) { 
    print("Did Tap Restaurant Cell - Restaurant Controller") 
    navigationController?.pushViewController(controller, animated: true) 
} 
내가 CollectionView 승/엉망 이후
관련 문제