I want to change value of temperature in UIView (blue square), when I tapping on cell in collection view (date). I am trying to use delegate for it, but i can't do it. I want to change value of selectedIndex and pass this value to UIView in viewModel.weather[selectedIndex]
ViewController with collectionView
protocol WeekCityWeatherViewControllerDelegate {
func reloadWeatherData()
}
class WeekCityWeatherViewController: UIViewController {
var delegate: WeekCityWeatherViewControllerDelegate?
...
extension WeekCityWeatherViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "dateCell", for: indexPath) as! DateWeekWeatherScreenCell
cell.layer.cornerRadius = 5
if selectedIndex == indexPath.row {
cell.backgroundColor = UIColor.blue
cell.dateLabel.textColor = UIColor.white
} else {
cell.backgroundColor = UIColor.white
cell.dateLabel.textColor = UIColor.black
}
if let dateInt = viewModel.weather.first?.week.daily[indexPath.item].dt {
let timeInterval = TimeInterval(dateInt)
let myNSDate = Date(timeIntervalSince1970: timeInterval)
let dateFormatter2 = DateFormatter()
dateFormatter2.dateFormat = "dd/MM E"
dateFormatter2.locale = Locale(identifier: "ru_RU")
let dateString = dateFormatter2.string(from: myNSDate)
cell.dateLabel.text = dateString
}
return cell
}
}
extension WeekCityWeatherViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width / 5, height: collectionView.frame.height)
}
}
extension WeekCityWeatherViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedIndex = indexPath.row
self.dateCollectionView.reloadData()
delegate?.reloadWeatherData()
}
}
UIView
class DayView: UIView, WeekCityWeatherViewControllerDelegate {
var viewModel: GeneralViewModel
var selectedIndex: Int
var currentIndex: Int
init(frame: CGRect, viewModel: GeneralViewModel, selectedIndex: Int, currentIndex: Int) {
self.viewModel = viewModel
self.selectedIndex = selectedIndex
self.currentIndex = currentIndex
super.init(frame: frame)
createSubviews()
reloadWeatherData()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func reloadWeatherData() {
self.reloadInputViews()
}
private func createSubviews() {
let weekCityWeatherViewController = WeekCityWeatherViewController(viewModel: viewModel, currentIndex: currentIndex)
weekCityWeatherViewController.delegate = self
let tempLabel = UILabel()
tempLabel.textColor = .black
tempLabel.translatesAutoresizingMaskIntoConstraints = false
tempLabel.font = UIFont(name: "Rubik-Regular", size: 30)
if let maxTemp = viewModel.weather[selectedIndex].week.daily[0].temp.max {
tempLabel.text = String(format: "%.0f", maxTemp) + " " + "°"
}
addSubview(tempLabel)
NSLayoutConstraint.activate([
tempLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
tempLabel.topAnchor.constraint(equalTo: topAnchor, constant: 10),
tempLabel.heightAnchor.constraint(equalToConstant: 50),
tempLabel.widthAnchor.constraint(equalToConstant: 50),
])
}
}
create a protocol and send the target cell as a parameter in the trigger method.
Here is the steps;
// 1. protocol and trigger method
protocol ItemTableViewCellDelegate: AnyObject {
func doneButtonTapped(_ cell: ItemTableViewCell)
}
// 2. implement delegate and send the trigger method in your case
class ItemTableViewCell: UITableViewCell {
weak var delegate: ItemTableViewCellDelegate?
//...
}
// MARK: - Implementation
extension ViewController: ItemTableViewCellDelegate {
func doneButtonTapped(_ cell: ItemTableViewCell) {
// 3. find the index of item you tapped the button, via cell as a parameter
guard let indexPath = tableView.indexPath(for: cell) else { return }
var item = MainScreenModel.dummyModel[indexPath.row]
// 4. reload the cell by indexpath
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
Related
I am trying to create UICollectionView with cells that adjust the width based on the content of the cell using layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize but it doesn't update. Bellow is two images of what am trying to achieve and the next is what I have achieved.
Here is what am trying to achieve.
Correct display
Here is what I have been able to achieve
What I have now
And here is my code
import UIKit
struct Model {
let name: String
let color: String
}
class DisplayTagsView: UIView {
// Collection View
var projectTagsCollectionView: UICollectionView!
var projectTagsCollectionViewHeightConstraint: NSLayoutConstraint!
private var tagsObjects = [Any]() // Object to allow add button
private var tags: [Model] = [] // Tags
// MARK: - Init
init() {
super.init(frame: .zero)
initViews()
initTags()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func initTags() {
self.tags.append(Model(name: "Some tag", color: "color"))
self.tags.append(Model(name: "Twotwo", color: "color"))
self.tags.append(Model(name: "Smartparking", color: "color"))
self.tags.append(Model(name: "Development", color: "color"))
self.tagsObjects = self.tags
self.tagsObjects.append(AddButtonCollectionViewCell.self)
}
// MARK: - Private
private func initViews() {
initTagCollectionView()
}
private func initTagCollectionView() {
let layout = UICollectionViewFlowLayout()
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
layout.minimumLineSpacing = 5
layout.minimumInteritemSpacing = 5
layout.scrollDirection = .vertical
projectTagsCollectionView = UICollectionView(frame: self.frame, collectionViewLayout: layout)
projectTagsCollectionView.delegate = self
projectTagsCollectionView.dataSource = self
projectTagsCollectionView.register(cell: ProjectCollectionViewCell.self)
projectTagsCollectionView.register(cell: AddButtonCollectionViewCell.self)
projectTagsCollectionView.isScrollEnabled = false
projectTagsCollectionView.backgroundColor = .clear
}
// set up views
func setupView() {
addSubview(projectTagsCollectionView)
setCollectionHeight()
}
// update height
func setCollectionHeight() {
projectTagsCollectionViewHeightConstraint = projectTagsCollectionView.heightAnchor.constraint(equalToConstant: 200)
projectTagsCollectionViewHeightConstraint.isActive = true
}
// Button button
func addButton() -> UIButton {
let addButton = UIButton()
addButton.setImage(#imageLiteral(resourceName: "settings"), for: .normal)
return addButton
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension DisplayTagsView : UICollectionViewDelegateFlowLayout {
// Auto resizing of the cell tags
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout
var newEdgeInsets = UIEdgeInsets(top: flowLayout!.sectionInset.top, left: flowLayout!.sectionInset.left, bottom: flowLayout!.sectionInset.bottom, right: flowLayout!.sectionInset.right)
if collectionView.numberOfItems(inSection: section) == 1 {
let edgeInset = newEdgeInsets.right + (collectionView.frame.width - flowLayout!.itemSize.width)
newEdgeInsets.right = edgeInset
}
return newEdgeInsets
}
}
// MARK: - UICollectionViewDelegate
extension DisplayTagsView: UICollectionViewDelegate {
}
// MARK: - UICollectionViewDataSource
extension DisplayTagsView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tagsObjects.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let tagObject = self.tagsObjects[indexPath.item]
if let tag = tagObject as? Model {
let cell: ProjectCollectionViewCell = projectTagsCollectionView.dequeueTypedCell(forIndexPath: indexPath)
cell.configureCell(tagName: tag.name, tagBackground: tag.color)
return cell
} else {
// Adding button to the UICollection
let cell: AddButtonCollectionViewCell = membersCollectionView.dequeueTypedCell(forIndexPath: indexPath)
let addButto = addButton()
cell.contentView.subviews.forEach({$0.removeFromSuperview()})
cell.contentView.addSubview(addButton)
settingButton.snp.makeConstraints { make in
make.size.equalTo(cell.contentView)
}
return cell
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
Try Following library. TagList view.
https://github.com/ElaWorkshop/TagListView. It surely working ur conditions
I am trying to make countdown timer app with collectionView.
Features & Functions:
Each cell has own label and timer function.
CountDown timer will run if user touches a cell.
Time string have to updated as timer run.
I successfully build a timer in each cell but I'm stuck updating timeLabel (reload selected cell).
Please check the codes below and give me some hint.
class ListViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var recipeList: TimeRecipeList
var timer = Timer()
required init?(coder aDecoder: NSCoder) {
recipeList = TimeRecipeList()
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
let width = (view.frame.size.width - 10) / 2
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: width, height: width)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItemSegue" {
if let addItemVC = segue.destination as? AddRecipeViewController {
addItemVC.delegate = self
}
}
}
}
extension ListViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return recipeList.item.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeListCell", for: indexPath)
let item = recipeList.item[indexPath.row]
configureText(for: cell, with: item)
return cell
}
func configureText(for cell: UICollectionViewCell, with item: TimeRecipe) {
if let label = cell.viewWithTag(1) as? UILabel {
label.text = item.name
}
if let label = cell.viewWithTag(2) as? UILabel {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .abbreviated
let timeString = formatter.string(from: TimeInterval(item.time))
label.text = timeString
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeListCell", for: indexPath)
let item = recipeList.item[indexPath.row]
let cellTimer = TimerControl()
cellTimer.second = item.time
cellTimer.timerRun()
configureText(for: cell, with: item)
}
class TimerControl {
var timer = Timer()
var second: Int = 0
func timerRun() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(countDown), userInfo: nil, repeats: true)
}
#objc func countDown() {
//let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeListCell", for: indexPath)
if second <= 1 {
timer.invalidate()
} else {
second -= 1
//collectionView.reloadItems(at: [indexPath])
//MARK: Reload selected cell
}
}
}
}
extension ListViewController: AddRecipeViewControllerDelegate {
func addRecipeViewControllerDidCancel(_ controller: AddRecipeViewController) {
dismiss(animated: true)
}
func addRecipeViewControllerDisSave(_ controller: AddRecipeViewController, didFinishAdding item: TimeRecipe) {
dismiss(animated: true)
let rowIndex = recipeList.item.count
recipeList.item.append(item)
let indexPath = IndexPath(row: rowIndex, section: 0)
let indexPaths = [indexPath]
collectionView.insertItems(at: indexPaths)
}
}
#objc func countDown(indexPath: IndexPath) {
if second <= 1 {
timer.invalidate()
} else {
second -= 1
//MARK: Reload selected cell
yourarray[indexPath.row] = newvalues
collectionView.reloadItems(at: [indexPath])
}
}
I would like to create a planning app, what I have already done, but my problem is that now, I would like to create different cells as following:
I don't know if it is possible...
Today, I have this code:
func numberOfSections(in collectionView: UICollectionView) -> Int { //colonnes: models
if _event != nil && _event!.models.count > 0
{
return _event!.models.count + 1
}
return 0
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int //lignes: slots
{
if _event != nil && _event!.models.count > 0 && _event!.models[0].slots.count > 0
{
if (section == 0) // A vérifier
{
return _event!.models[0].slots.count + 1
}
else
{
return _event!.models[section - 1].slots.count + 1
}
}
return 0
}
With this result:
UICollectionViewLayout is definitely the way to go.
I've made a start on an example of this for you, It gets the number of sections and items and generates the layout you asked for, evenly distributing the items across the height of the UICollectionView.
I've cropped the screenshot above so I don't take up to much space, heres the code
class OrganiserLayout:UICollectionViewLayout {
let cellWidth:CGFloat = 100
var attrDict = Dictionary<IndexPath,UICollectionViewLayoutAttributes>()
var contentSize = CGSize.zero
override var collectionViewContentSize : CGSize {
return self.contentSize
}
override func prepare() {
// Generate the attributes for each cell based on the size of the collection view and our chosen cell width
if let cv = collectionView {
let collectionViewHeight = cv.frame.height
let numberOfSections = cv.numberOfSections
self.contentSize = cv.frame.size
self.contentSize.width = cellWidth*CGFloat(numberOfSections)
for section in 0...numberOfSections-1 {
let numberOfItemsInSection = cv.numberOfItems(inSection: section)
let itemHeight = collectionViewHeight/CGFloat(numberOfItemsInSection)
let itemXPos = cellWidth*CGFloat(section)
for item in 0...numberOfItemsInSection-1 {
let indexPath = IndexPath(item: item, section: section)
let itemYPos = itemHeight*CGFloat(item)
let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attr.frame = CGRect(x: itemXPos, y: itemYPos, width: cellWidth, height: itemHeight)
attrDict[indexPath] = attr
}
}
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// Here we return the layout attributes for cells in the current rectangle
var attributesInRect = [UICollectionViewLayoutAttributes]()
for cellAttributes in attrDict.values {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
// Here we return one attribute object for the specified indexPath
return attrDict[indexPath]!
}
}
To test this I made a basic UIViewController and UICollectionViewCell, here is the view controller:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Use our new OrganiserLayout subclass
let layout = OrganiserLayout()
// Init the collection view with the layout
let collection = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collection.delegate = self
collection.dataSource = self
collection.backgroundColor = UIColor.white
collection.register(OrganiserCollectionViewCell.self, forCellWithReuseIdentifier: "cell")
self.view.addSubview(collection)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch section {
case 0:
return 8
case 1:
return 6
case 2:
return 4
case 3:
return 2
case 4:
return 4
default:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! OrganiserCollectionViewCell
cell.label.text = "\(indexPath.section)/\(indexPath.row)"
switch indexPath.section {
case 1:
cell.backgroundColor = UIColor.blue
case 2:
cell.backgroundColor = UIColor.red
case 3:
cell.backgroundColor = UIColor.green
default:
cell.backgroundColor = UIColor.cyan
}
return cell
}
}
And the UICollectionViewCell looks like this:
class OrganiserCollectionViewCell:UICollectionViewCell {
var label:UILabel!
var seperator:UIView!
override init(frame: CGRect) {
super.init(frame: frame)
label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(label)
seperator = UIView()
seperator.backgroundColor = UIColor.black
seperator.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(seperator)
let views:[String:UIView] = [
"label":label,
"sep":seperator
]
let cons = [
"V:|-20-[label]",
"V:[sep(1)]|",
"H:|[label]|",
"H:|[sep]|"
]
for con in cons {
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: con, options: [], metrics: nil, views: views))
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Hope some of this helps, It's a very simplified example and you will probably need to modify it in order to achieve the calendar looking result that you require.
I believe you have to resolve to implementing your own custom layout for the collectionView - you will need to implement custom UICollectionViewLayout. This is not a trivial thing, but there are several good tutorials for it, for example this tutorial.
I have a custom UICollectionView cell with an imageView and a label, as listed below:
import UIKit
class PollCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var pollQuestion: UILabel!
}
I want to make each populated cell clickable and then pass information from that clicked cell into a new ViewController. Below is the ViewController that populates the custom cell.
import UIKit
import FirebaseDatabase
import FirebaseDatabaseUI
import FirebaseStorageUI
private let reuseIdentifier = "PollCell"
class TrendingViewController: UICollectionViewController {
var ref: FIRDatabaseReference!
var dataSource: FUICollectionViewDataSource!
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
self.dataSource = self.collectionView?.bind(to: self.ref.child("Polls")) { collectionView, indexPath, snap in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PollCell
/* populate cell */
cell.pollQuestion.text = snap.childSnapshot(forPath: "question").value as! String?
let urlPollImage = snap.childSnapshot(forPath: "image_URL").value as! String?
cell.imageView.sd_setImage(with: URL(string: urlPollImage!), placeholderImage: UIImage(named: "Fan_Polls_Logo.png"))
//Comment
return cell
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
}
I also have some code to "invert" the cells that populate in my inverted ViewController:
import Foundation
import UIKit
class InvertedStackLayout: UICollectionViewLayout {
let cellHeight: CGFloat = 100.00 // Your cell height here...
override func prepare() {
super.prepare()
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttrs = [UICollectionViewLayoutAttributes]()
if let collectionView = self.collectionView {
for section in 0 ..< collectionView.numberOfSections {
if let numberOfSectionItems = numberOfItemsInSection(section) {
for item in 0 ..< numberOfSectionItems {
let indexPath = IndexPath(item: item, section: section)
let layoutAttr = layoutAttributesForItem(at: indexPath)
if let layoutAttr = layoutAttr, layoutAttr.frame.intersects(rect) {
layoutAttrs.append(layoutAttr)
}
}
}
}
}
return layoutAttrs
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let layoutAttr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
let contentSize = self.collectionViewContentSize
layoutAttr.frame = CGRect(
x: 0, y: contentSize.height - CGFloat(indexPath.item + 1) * cellHeight,
width: contentSize.width, height: cellHeight)
return layoutAttr
}
func numberOfItemsInSection(_ section: Int) -> Int? {
if let collectionView = self.collectionView,
let numSectionItems = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: section)
{
return numSectionItems
}
return 0
}
override var collectionViewContentSize: CGSize {
get {
var height: CGFloat = 0.0
var bounds = CGRect.zero
if let collectionView = self.collectionView {
for section in 0 ..< collectionView.numberOfSections {
if let numItems = numberOfItemsInSection(section) {
height += CGFloat(numItems) * cellHeight
}
}
bounds = collectionView.bounds
}
return CGSize(width: bounds.width, height: max(height, bounds.height))
}
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
if let oldBounds = self.collectionView?.bounds,
oldBounds.width != newBounds.width || oldBounds.height != newBounds.height
{
return true
}
return false
}
}
You must to implement this method of UICollectionViewDelegate
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
debugPrint("this works")
}
I hope this helps you
This Function used to select the row of your collection view
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
Then you use function call. Whatever you need, just Defined the inside function. And easily called the function during the selected the row (inside the didSelectItemAt indexPath)
Make sure you have enabled UserIntraction for both UILabel and UIImageView, because both have default value as false.
self.dataSource = self.collectionView?.bind(to: self.ref.child("Polls")) { collectionView, indexPath, snap in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PollCell
/* populate cell */
cell.pollQuestion.userInteractionEnabled = true;
cell.imageView.userInteractionEnabled = true;
cell.pollQuestion.text = snap.childSnapshot(forPath: "question").value as! String?
let urlPollImage = snap.childSnapshot(forPath: "image_URL").value as! String?
cell.imageView.sd_setImage(with: URL(string: urlPollImage!), placeholderImage: UIImage(named: "Fan_Polls_Logo.png"))
//Comment
return cell
}
Then you need to use of UICollectionViewDelegate method:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
}
Add a segue in your storyboard from the cell to the view controller you want to transition to. You can use the prepare for segue method, prepare(for:sender:), to pass your data. Using the segue (UIStoryboarySegue documentation) parameter, you can access the 'destinationViewController`.
Check out the View Controller for iOS Programming Guide: Using Segues for more information about using segues.
This is the code form the 'Opgeslagen Rooster' Viewcontroller
class vcSavedTimetable: UIViewController {
#IBOutlet weak var noTimetableSavedLabel: UILabel!
var timetable: Timetable!
override func viewWillAppear(_ animated: Bool) {
prepareView()
}
override func viewWillDisappear(_ animated: Bool) {
noTimetableSavedLabel.isHidden = true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSavedTimetable"{
let viewController = segue.destination as! vcTimetableShow
viewController.timetable = self.timetable
viewController.willSave = false
}
}
func prepareView(){
let savedTimetable = getTimetableFromUserDefaults()
guard (savedTimetable != nil) else {
noTimetableSavedLabel.isHidden = false
return
}
self.timetable = savedTimetable!
performSegue(withIdentifier: "showSavedTimetable", sender: nil)
}
func getTimetableFromUserDefaults()->Timetable?{
let timetableID = UserDefaults.standard.string(forKey: "savedTimetableID")
if isConnectedToNetwork(){
if let id = timetableID{
let table = Timetable(timetableID: id)
return table
}
}
let val = UserDefaults.standard.data(forKey: "savedTimetable")
if let data = val{
let table = NSKeyedUnarchiver.unarchiveObject(with: data) as! Timetable
return table
}
return nil
}
}
This is the code of the destination viewcontroller 'Rooster Bekijken'. The viewdidload() function should be executed, which doesn't happen. I tested it using breakpoints
//
// vcTimetableShowCollectionViewController.swift
// Ostrea Rooster App
//
// Created by Giel-Jan Looij on 14-12-16.
// Copyright © 2016 GJ-Computers. All rights reserved.
//
import UIKit
private let reuseIdentifier = "Cell"
class vcTimetableShow: UICollectionViewController, UICollectionViewDelegateFlowLayout {
weak var timetable: Timetable?
var willSave = false
//UIVIEWCONTROLLER
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.delegate = self
collectionView?.register( UINib(nibName: "timetableViewCell", bundle: nil), forCellWithReuseIdentifier: "lessonEntry")
NotificationCenter.default.addObserver(self, selector: #selector(self.dataDidArrive(_:)), name: .didFetchTimetable, object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
deinit {
NotificationCenter.default.removeObserver(self)
}
//METHODES
func dataDidArrive(_ notification: NSNotification){
collectionView?.reloadData()
if let cv = self.collectionView {
cv.layoutIfNeeded()
let indexPath = IndexPath(item: 0, section: getDayOfWeek()-1)
if let attributes = cv.layoutAttributesForSupplementaryElement(ofKind: UICollectionElementKindSectionHeader, at: indexPath) {
let topOfHeader = CGPoint(x: 0, y: attributes.frame.origin.y - cv.contentInset.top)
cv.setContentOffset(topOfHeader, animated:true)
}
}
if willSave {
UserDefaults.standard.set(timetable!.timetableID, forKey: "savedTimetableID")
let encodedTimetable = NSKeyedArchiver.archivedData(withRootObject: self.timetable!)
UserDefaults.standard.set(encodedTimetable, forKey: "savedTimetable")
UserDefaults.standard.synchronize()
}
}
func getDayOfWeek()->Int {
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: Date())
if weekDay > 6 || weekDay < 2{
return 5
}
return weekDay-1
}
//UICOLLECTIONVIEW DATASOURCE
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return timetable!.days.count
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return timetable!.days[section+1]!.hour.count * 2
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 2 == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hourIndicator", for: indexPath)
let dayLabel = cell.viewWithTag(1) as! UILabel
let dayIndex = indexPath.section + 1
let hourIndex = indexPath.item/2 + 1
let cellHour = timetable!.days[dayIndex]!.hour[hourIndex]!
dayLabel.text = String(cellHour.hourID)
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 2
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "lessonEntry", for: indexPath) as! timetableViewCell
let dayIndex = indexPath.section + 1
let hourIndex = indexPath.item/2 + 1
let cellHour = timetable!.days[dayIndex]!.hour[hourIndex]!
cell.cellHour = cellHour
cell.prepareCell()
return cell
}
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "dayHeaderCell", for: indexPath as IndexPath)
let dayIndex = indexPath.section + 1
let dayName = timetable!.days[dayIndex]!.dayName
let day = cell.viewWithTag(1) as! UILabel
day.text = dayName
if timetable!.days[dayIndex]!.dayID == getDayOfWeek(){
cell.backgroundColor = UIColor.lightGray
}
return cell
}
//UICOLLECTIONVIEW DELEGATE
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 2 == 0{
let dayIndex = indexPath.section + 1
let hourIndex = indexPath.item/2 + 1
let cellHour = timetable!.days[dayIndex]!.hour[hourIndex]!
var cellHeight: CGFloat = 0
for _ in cellHour.lessons{
cellHeight += 23
}
if cellHour.notice != ""{
cellHeight += 23
}
return CGSize(width: 50, height: cellHeight)
}else{
let dayIndex = indexPath.section + 1
let hourIndex = indexPath.item/2 + 1
let cellHour = timetable!.days[dayIndex]!.hour[hourIndex]!
var cellHeight: CGFloat = 0
for _ in cellHour.lessons{
cellHeight += 23
}
if cellHour.notice != ""{
cellHeight += 23
}
return CGSize(width: 226.0, height: cellHeight)
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let edgeInset: CGFloat = (collectionView.frame.width - (226.0 + 50.0))/2
return UIEdgeInsets.init(top: 0, left: edgeInset, bottom: 30, right: edgeInset)
}
}
I'm trying to segue from 'Opgeslagen Rooster' to 'Rooster Bekijken', but it doesn't work. It is running in the main thread (thread 1), so that isn't the problem. It gets to prepare(for segue...), does everything. After that the view should change right? But that doesn't happen. The viewdidload method of the 'Rooster Bekijken' ViewController doesn't get called. It hangs after the last line in the pepare(for segue ....) function.
Why doesn't it change to the other viewcontroller? It does work when im accessing the 'Rooster Bekijken' viewcontroller form the other viewcontroller which segue's to it.