secondTBLVControllert <- FirstTableVC <- UITableVC
In secondTBLVControllert i am not getting tableview and its cell, in this class i have used static cells and style is group, i have set datasource and delegate in IB and code also... Im using storyboard.
and i have tried by implementing and without implementing delegate and datasource methods.
import Foundation
import UIKit
class secondTBLVControllert : FirstTableVC {
override func viewDidLoad() {
super.viewDidLoad()
}
}
i am getting empty view.. i am not getting my designs
Related
I have created a custom UIView and have a protocol set for it. Now from the View Controller when I set the delegate to self I am getting an EXC_BAD_ACCESS.
---The View Controller Code------
class VerificationController: UIViewController, LoadingViewDelegate {
#IBOutlet weak var instructionView: LoadingView!
override func viewDidLoad() {
super.viewDidLoad()
instructionView.randomTextIndexes = [1]
instructionView.delegate = self
}
...
}
// "instructionView" is the UIView outlet and "LoadingView" is the class
--This is the custom View Code ------
protocol LoadingViewDelegate {
func generated(random code:String)
}
class LoadingView: UIView {
var delegate:LoadingViewDelegate?
var randomTextIndexes:[Int] = []
}
I am getting EXC_BAD_ACCESS when I try to access the delegate as well as the randomTextIndexes from the viewDidLoad() method of the view controller. Could you please tell me what I am missing here.
My best guess is that you forgot to set the class of the custom view in the Interface Builder. Check the Identity Inspector for your object in the IB, it should look like this:
If it isn't set, then that's the problem.
I'm trying to implement CVCalendar with my project. I have everything in, but at the end it asks for me to connect outlets. Here is an image of the instructions:
Click here for image
I have no idea what to do as I am new to swift and xcode development. Here is the link to the github page: https://github.com/CVCalendar/CVCalendar
Any help would be appreciated, thanks!
I assume you've extended CVCalendarMenuViewDelegate and CVCalendarViewDelegate on your ViewController and implemented the delegate methods required for CVCalendar such as presentationMode and firstWeekday.
class ViewController: UIViewController {
...
}
extension ViewController: CVCalendarMenuViewDelegate {
...
}
extension ViewController: CVCalendarViewDelegate {
func presentationMode() -> CalendarMode {
return CalendarMode.monthView
}
func firstWeekday() -> Weekday {
return Weekday.monday
}
}
The last thing to do is to connect CVCalendar's menuView and calendarView objects to this class. This means that whenever an action occurs with a calendarView or menuView object the action knows to be routed to the delegate methods of your ViewController because you've attached it as an outlet.
This can be done in InterfaceBuilder by holding the control key and dragging from the menuView and calendarView to the top of the scene and then choosing the delegate to connect to, as shown in this image.
Connecting an outlet
This can also be done programmatically in your ViewController's viewDidLoad method.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
calendarView.delegate = self
menuView.delegate = self
}
I'm constructing a tabView with a collectionView as one of the tabs. In the tabView, I have a button that takes a Photo and adds it to the collection view.
The problem I'm facing is reloading the collection view from the TabView, because I'm getting the following error:
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'"
In the TabView I'm calling this function:
PhotoListController().reloadData()
And in the PhotoListController, that function is:
func reloadData() {
getData() //function that goes through an array with the data of the images
self.collectionView!.reloadData()
}
When I had everything in the same class, it worked pretty well, but now I can't fix the problem :(
If anybody can give me a hand it would be very much appreciated.
Well I've finally found a solution within this topic:
How to reload data in a TableView from a different ViewController in Swift
and this one:
Swift: Reload collection view data from another view class with swift
The solution is related to use a NotificationCenter
in this code: PhotoListController().reloadData() you create a new copy of PhotoListController class, but you need to apply to the same instance of PhotoListController class that was already been created. I guess you need to apply the delegate pattern.
protocol PhotoListDelegate: AnyObject {
func reloadData()
}
class PhotoListController : UIViewController, PhotoListDelegate {
var tableView = TableView()
var collectionView = UICollectionView()
override func viewDidLoad() {
tableView.photoListDelegate = self
}
func reloadData() {
getData()
self.collectionView.reloadData()
}
func getData() {
// your code to get data
}
}
class TableView: UITableView {
weak var photoListDelegate : PhotoListDelegate?
// then in TableView Class:
func photoCatched() {
self.photoListDelegate?.reloadData()
}
}
I want to use protocols. I have a collection view and collection view cells which belongs to this collection view. I have a button in this cell. I want to call a method in collectionview class (not cell class) when user taps to this button.
I am defining my cell class with following code:
protocol testPro {
func replyClicked()
}
class MessageGalleryViewControllerCellCollectionViewCell: UICollectionViewCell {
var test1: testPro?
// ...
}
Then when user taps to button system calling following method in cell class.
func replyAction(sender:UIButton!)
{
test1?.replyClicked()
}
And My collection view class:
class ReceivedPhotosViewController: UIViewController,UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, testPro {
func replyClicked() {
print("clicked")
}
}
But I can't see any log like "clicked". So it is not working. Where is the problem?
You are not assigning your test1 to your cell. In your cellForItemAtindexPath, put cell.test1 = self after instantiating the cell.
I have a UICollectionView with a CollectionReusableView header. I want to pass a string from the collecitonview to the header, so that the header knows which data to load based on the string. I am trying to use delegates/protocols to do this, but keep getting "unexpectedly found nil while unwrapping an optional value." Here is my code:
protocol UserToQuery {
func thisUser(x: String)
}
class Profile: UICollectionViewController {
var ownProfile = true
var delegate:UserToQuery?
override func viewDidLoad() {
super.viewDidLoad()
if self.ownProfile == true {
let username = PFUser.currentUser()?.username
self.delegate!.thisUser(username!)
}
}
}
And here is the code for the Header view:
class ProfileHeader: UICollectionReusableView, UserToQuery {
var id1 = String()
var controller = Profile()
override func awakeFromNib() {
print(id1)
controller.delegate? = self
}
func thisUser(x: String) {
self.id1 = x
getProfileInfo()
}
func getUserData() {
// code here uses the id1 value to get data
}
}
My understanding of delegates/protocols is this: if you want to pass data (i.e., string), to another view, you make the view that receives the string conform to a protocol. This protocol includes a function that is used to pass the string, and when that function is called, it notifies the other view that the string is now available for use, and then you code what you want and use the string. Is that accurate?
In ProfileHeader, you have a variable, controller, which is creating a new instance of Profile, which is NOT the Profile view controller from your storyboard. This is why self.delegate! is nil in Profile.viewDidLoad().
I am going to make the assumption that ProfileHeader is a view in the Profile view controller. In your viewDidLoad, you should set the delegate to the ProfileHeader. See the example code below (I assume an outlet for the ProfileHeader view):
EDIT: ProfileHeader is not an outlet, as mentioned in the comments. Updated my answer to reflect that.
class Profile: UICollectionViewController {
var ownProfile = true
var delegate:UserToQuery?
override func viewDidLoad() {
super.viewDidLoad()
// Set the delegate!
self.delegate = ProfileHeader()
if self.ownProfile == true {
let username = PFUser.currentUser()?.username
// Delegate won't be nil now
self.delegate!.thisUser(username!)
}
}
}
}
As a general flow, the view controller should keep references to the view, not the other way around. So remove the controller property from your ProfileHeader view. The view shouldn't care what view controller is controlling it.
You have some misunderstandings about protocol/delegate, but it’s normal when you start iOS development.
First of all, why does the app crash :
The variable delegate is an optional UserQuery. It’s okay for a delegate to be optional, but it’s never set in your code, so when you call :
self.delegate!.thisUser(username!)
you try to force unwrapping a nil variable, which results in the crash.
Protocols
Now, let’s talk about the protocol/delegate relationship.
You have an UICollectionViewController subclass, which embeds an UICollectionView object. This UICollectionView will be contains a mix of header, footer and cell. Your ProfileHeader class will thus be displayed within your UICollectionView.
In order to populate an UICollectionView, you don’t need to create your own protocol : there are already two protocols for this :
UICollectionViewDataSource is the main protocol to conforms to, because it allows you to populate the collection view
UICollectionViewDelegate is used for further customization of your tableview, i.e. customizing the appearance and handling events.
Since your Profile class inherits from UICollectionViewControlleryou don’t have to named these protocols after your class name since UICollectionViewController already conforms to these protocols as written in Apple docs
You will have to override the delegate and protocol methods in order to display some data. My advice is, before using headers and footers, to use only UICollectionViewCell objects for start easily.
By overriding the method -collectionView:numberOfItemsInSection: and - collectionView:cellForItemAtIndexPath:, you will be able to populate the collection view.