iOS 8 swift change parent content - ios

i am new to iOS, so i am confronted with this problem: I wrote an UICollectionView in an UIViewController (parent) with an UICollectionResuableView as a header.
class ParentViewController: UIViewController, SideBarDelegate {
#IBOutlet weak var mPreviewsCollection: UICollectionView!
override func viewDidLoad() {
...
}
...
}
This UICollectionResuableView contain another UICollectionView (child) to provide dynamic customized tabs (maybe not the best idea, but it looks as was intended).
class ChildHeaderCollectionReusableView: UICollectionReusableView {
#IBOutlet var mTabHeader: UICollectionView!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
...
}
...
Now i want to to change the content of the parent UICollectionView (reloadData()) when selecting a cell in the child. How can i do that? How can i execute methods in the running instance of the parent from outside?
e.g. var rootViewController = self.window!.rootViewController as KioskViewController returns another instance of my parent UIViewController with zero content

Related

The myLabel outlet from the UICollectionView to the UILabel is invalid. Outlets cannot be connected to repeating content

I coded my first CollectionView but the build fails with this error message:
"Illegal Configuration: The myLabel outlet from the UICollectionView to the UILabel is invalid. Outlets cannot be connected to repeating content."
I read other questions on StackOverflow with the same error, and the solution was to set the content of the UILabel which is in a prototype cell and has an outlet to "CollectionViewCell.swift" from static to dynamic. I couldn't try this because this option doesn't appear. I think it's gone with the newer versions of Xcode.
My code in "CollectionViewCell.swift":
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myLabel: UILabel!
}
My code in "ViewController.swift":
class LibraryViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
#IBOutlet weak var sortCollectionView: UICollectionView!
func numberOfSections(in sortCollectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ sortCollectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ sortCollectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let sortCell = sortCollectionView.dequeueReusableCell(withReuseIdentifier: "sortCell", for: indexPath) as! CollectionViewCell
sortCell.myLabel.text = "hi"
return sortCell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
Thank you for every helpful answer :'D
Select your UILabel from Storyboard and check connections of it, there might be an old connection of it. Remove that old connection and you are good to go.
Ok, I fixed it by myself!
For everyone who search for the solution:
Double check if there are no other Outlets than the CollectionViewCell!
In my case the Label had an outlet to another thing :^)

Why do I need to override method not even implemented in superclass?

I have a plain FriendsController class which is UICollectionViewController subclass, so when I implement UICollectionViewDataSource protocol required functions why do I need to put override key word in front of func declaration it is even do not implemented in UICollectionViewController parent class.
class FriendsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
fileprivate let cellId = "cellId"
var messages: [Message]?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Recent"
collectionView?.backgroundColor = UIColor.white
collectionView?.register(MessageCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.alwaysBounceVertical = true
setupData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = messages?.count {
return count
}
return 0
}
I've seen that UIViewCollectionController did not implement protocol required functions:
open class UICollectionViewController : UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
public init(collectionViewLayout layout: UICollectionViewLayout)
public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
public init?(coder aDecoder: NSCoder)
open var collectionView: UICollectionView?
// Defaults to YES, and if YES, any selection is cleared in viewWillAppear:
// This property has no effect if the useLayoutToLayoutNavigationTransitions property is set to YES
open var clearsSelectionOnViewWillAppear: Bool
// Set to YES before pushing a a UICollectionViewController onto a
// UINavigationController. The top view controller of the navigation controller
// must be a UICollectionViewController that was pushed with this property set
// to NO. This property should NOT be changed on a UICollectionViewController that
// has already been pushed onto a UINavigationController.
#available(iOS 7.0, *)
open var useLayoutToLayoutNavigationTransitions: Bool
// The layout object is needed when defining interactive layout to layout transitions.
#available(iOS 7.0, *)
open var collectionViewLayout: UICollectionViewLayout { get }
// Defaults to YES, and if YES, a system standard reordering gesture is used to drive collection view reordering
#available(iOS 9.0, *)
open var installsStandardGestureForInteractiveMovement: Bool
}
UICollectionViewController conforms to UICollectionViewDataSource and UICollectionViewDelegate so it has to implement the required methods of those protocols, including numberOfItemsIn:, which is why you need to use override
It's not a superclass, much rather a protocol, which your class needs to conform to.

iOS Swift: Loading a XIB file containing a UICollectionView causing nil error?

I created a UICollectionView in an .xib file like so:
Based on this post: CanĀ“t add items to UICollectionView inside UIView xib
I understand that you cannot directly add a UICollectionViewCell within a UICollectionView that is contained in a .xib, but instead have to create another .xib with only the UICollectionViewCell, which is what I did:
I create a GridViewCell class and add it as the Custom Class for the UICollectionViewCell:
class GridViewCell: UICollectionViewCell
{
#IBOutlet var clothingImageView: UIImageView!
override func awakeFromNib()
{
super.awakeFromNib()
// Initialization code
}
}
I also created a GridViewGallery class and associated with my UICollectionView .xib file:
extension GridViewGallery: UICollectionViewDelegate
{
}
extension GridViewGallery: UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return clothingImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GridViewCell", for: indexPath) as! GridViewCell
cell.clothingImageView.image = clothingImages[indexPath.row].image
return cell
}
}
class GridViewGallery: UIView
{
#IBOutlet var gridLayoutCollectionView: UICollectionView!
var clothingImages = [INSPhotoViewable]()
override init(frame: CGRect)
{
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
let gridViewCell = UINib(nibName: "GridViewCell", bundle: nil)
gridLayoutCollectionView.register(gridViewCell, forCellWithReuseIdentifier: "GridViewCell")
}
func storeGridViewImages(photos: [INSPhotoViewable])
{
clothingImages = photos
gridLayoutCollectionView.dataSource = self
gridLayoutCollectionView.delegate = self
}
}
However, I get a unexpectedly found nil while unwrapping an Optional value error when I tried to load the XIB file to a UIView in another class:
#IBAction func gridViewLayout(_ sender: UIBarButtonItem)
{
if let gridView = Bundle.main.loadNibNamed("GridViewGallery", owner: self, options: nil)?.first as? GridViewGallery
{
print("GRID VIEW FOUND")
self.addSubview(gridView)
}
}
The GridViewGallery File Owner's Custom Class is empty, as I set the Custom Class on the UIView property instead as seen in the first screenshot:
However, if I instead set the File Owner's Custom Class to GridViewGallery and leave the Custom Class as blank from the UIView itself, then I get a crash with error this class is not key value coding-compliant for the key gridLayoutCollectionView.
I'm not sure I understand what is causing this, and which way I should be setting the Custom Class.
Can someone assist me?
Thanks.

UICollectionView + custom cell

please help me with custom cell in collection
i have an error:
..this class is not key value coding-compliant for the key cell_label..
you can download full project here:
https://drive.google.com/file/d/0B1nXU0xmeKg8WTRYRXJVbWdMVlU/view?usp=sharing
i want to show collection with custom cell in modalview
PS: i use xcode 7 beta and swift 2 and separate xib for every view
import UIKit
class ModalController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var myCollection: UICollectionView!
#IBOutlet weak var myCell: colywCell!
var tableData: [String] = ["XXX", "YYY", "ZZZ"]
override func viewDidLoad() {
super.viewDidLoad()
self.title="modal W"
myCollection.dataSource = self
myCollection.delegate = self
let nipName=UINib(nibName: "colywCell", bundle:nil)
myCollection.registerNib(nipName, forCellWithReuseIdentifier: "cell1")
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tableData.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
self.myCell = myCollection.dequeueReusableCellWithReuseIdentifier("cell1", forIndexPath: indexPath) as! colywCell
self.myCell.Cell_label.text = tableData[indexPath.row]
return self.myCell
}
}
and custom cell file
import UIKit
class colywCell: UICollectionViewCell {
#IBOutlet weak var Cell_label: UILabel!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
you need to aware of who the owner is, and which class should be loaded with the nib.
in nutshell, you need to aware of those in your colywCell.nib:
1a.
make sure that the File's Owner is not a custom class.
1b.
make sure to disconnect every outlet from File's Owner.
2a.
make sure that the actual UICollectionViewCell is your custom class.
2b.
optionally connect the outlets to your custom class.
This is a common error, it usually means that you have an Outlet set on your view that is not binded to any IBOutlet on your Cell.
This happens when you bind a view with some var in your class and then you remove that var and not it's bind on your xib.

How to embed a UITableView in a custom view

Goal
I want to create a custom view that has a UITableView as a subview.
The custom view creates the table view programmatically. To the outside world (i.e., the ViewController), though, the custom view itself would appear to be a table view.
What I've tried
import UIKit
class CustomTableView: UIView {
// Do I make outlets?
//#IBOutlet var dataSource: UITableViewDataSource?
//#IBOutlet var delegate: UITableViewDelegate?
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect){
super.init(frame: frame)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
super.layoutSubviews()
var tableView: UITableView!
tableView = UITableView(frame: self.bounds)
// I'm not sure how to set the delegate and dataSource
// tableView.dataSource = ???
// tableView.delegate = ???
self.addSubview(tableView)
}
}
After creating the UITableView programmatically and adding it as a subview to the custom view parent, I can't figure out how to get the custom view to act like it is the table view. That is, I don't know how to get the custom view to do the communication between the View Controller and the table view for the delegate and dataSource.
What I've read
Designing Your Data Source and Delegate
Create a static UITableView without Storyboards
These articles seemed good, but I got a little lost.
How do I make the custom view act like it's own table subview with regard to delegate and data source?
The solution is to make the tableView a property of the custom class (as #BaseZen suggested). Then provide properties and methods in the custom class to mimic and pass along the properties and methods needed from tableView.
import UIKit
#IBDesignable class UICustomTableView: UIView {
private var myTableView: UITableView
required init(coder aDecoder: NSCoder) {
myTableView = UITableView()
super.init(coder: aDecoder)
}
override init(frame: CGRect){
myTableView = UITableView()
super.init(frame: frame)
}
override func awakeFromNib() {
super.awakeFromNib()
}
// TODO: #IBOutlet still can't be set in IB
#IBOutlet weak var delegate: UITableViewDelegate? {
get {
return myTableView.delegate
}
set {
myTableView.delegate = newValue
}
}
// TODO: #IBOutlet still can't be set in IB
#IBOutlet weak var dataSource: UITableViewDataSource? {
get {
return myTableView.dataSource
}
set {
myTableView.dataSource = newValue
}
}
func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String) {
myTableView.registerClass(cellClass, forCellReuseIdentifier: identifier)
}
func dequeueReusableCellWithIdentifier(identifier: String) -> UITableViewCell? {
return myTableView.dequeueReusableCellWithIdentifier(identifier)
}
override func layoutSubviews() {
super.layoutSubviews()
// ...
// setup UITableView
myTableView.frame = self.bounds
self.addSubview(myTableView)
// ...
}
}
Then it can be used like a normal UITableView:
import UIKit
class TableViewDemoVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var customTableView: UICustomTableView!
var items: [String] = ["One", "Two", "Three"]
override func viewDidLoad() {
super.viewDidLoad()
// setup the table view from the IB reference
customTableView.delegate = self
customTableView.dataSource = self
customTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = self.customTableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
// ...
}
It's not the most elegant, but jump out a level:
class MyCustomViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
myCustomView = CustomTableView()
myCustomView.frame = ... /* layout programatically */
/* Alternatively to the above 2 lines,
lay out myCustomView in StoryBoard,
and capture it as an #IBOutlet. It will then be ready here
to muck with, well before it gets displayed and needs the data */
myCustomView.tableView.delegate = self
myCustomView.tableView.dataSource = self
}
/* Now implement all your dataSource and delegate methods */
}
* IMPORTANT *
The key that you're missing is that tableView must be a stored property of your custom view. It's important and needs to be promoted from a silly local! It should also be initialized in the awakeFromNib() function, even if you don't know the frame size. Then reset its frame at layout time.
At a higher level, I don't know "What You're Really Trying To Do." It may not actually be the right implementation technique to be embedding a UITableView within a custom view; consider just laying out the UITableView in the main view. Then if you need decoration around it, lay those out as separate views in StoryBoard.

Resources