Swift 3: Segue and pass in data from one class to another - swift

I have a simple UICollectionViewController called HomeController that has a bunch of cells. These cells have a class of their own called PostCell. I also have a NSObject class that holds all the data for every Post (these posts are my cells). Inside my PostCell I have a UIView called profileSegueContainer. When I tap this UIView, I want to segue to a new controller. I am able to achieve this with a presentViewController method but I also want to pass in the info of that specific post. For example, if I tap a cell that has the uid of "1234", I want to be able to not only segue to the new controller but also pass this uid into it. Of course if I tap the next cell and the post.uid of that cell is "4567", then I want to also pass that in when I segue. I hope this makes sense... I want it to work similar to Instagrams "tapped on a user to get to their profile" feature. I hope this makes sense. Any help will be highly appreciated and of course, I will mark as answer. Thank you. All the relevant code is below:
class Post: NSObject {
var author: String?
var avatar_image_url: String?
var likes: Int?
var postImageUrl: String?
var uid: String?
var post_id: String?
var hashtags: [String]?
}
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var postCell: PostCell?
var userProfileController: UserProfileController?
var posts = [Post]()
var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.backgroundColor = grayBackgroundColor
self.collectionView?.register(PostCell.self, forCellWithReuseIdentifier: reuseIdentifier)
self.collectionView?.contentInset = UIEdgeInsetsMake(16, 0, 16, 0)
self.collectionView?.alwaysBounceVertical = true
self.collectionView?.showsVerticalScrollIndicator = false
setupNavigationBarBranding()
checkIfUserIsLoggedIn()
fetchPosts()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameWidth = self.view.frame.size.width
let width = frameWidth - (16 + 16)
let height = frameWidth - (16 / 9) + 50 + 50
return CGSize(width: width, height: height)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PostCell
cell.homeController = self
cell.post = posts[indexPath.item]
userProfileController?.post = posts[indexPath.item]
return cell
}
}
class PostCell: BaseCell {
var homeController: HomeController?
var userProfileController: UserProfileController?
var post: Post? {
didSet {
if let postDisplayName = post?.author {
displayName.text = postDisplayName
}
if let postImageUrl = post?.postImageUrl {
postImage.loadImageUsingCacheWithUrlString(urlString: postImageUrl)
}
if let postProfileImage = post?.avatar_image_url {
profileImage.loadImageUsingCacheWithUrlString(urlString: postProfileImage)
}
}
}
lazy var profileSegueContainer: UIView = {
let view = UIView()
view.isUserInteractionEnabled = true
return view
}()
func handleProfileSegue() {
let userProfile = UserProfileController()
let navigationUserProfile = UINavigationController(rootViewController: userProfile)
homeController?.present(navigationUserProfile, animated: true, completion: nil)
}
override func setupViews() {
super.setupViews()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleProfileSegue))
profileSegueContainer.addGestureRecognizer(tap)
addSubview(profileSegueContainer)
_ = profileSegueContainer.anchor(profileImage.topAnchor, left: profileImage.leftAnchor, bottom: profileImage.bottomAnchor, right: displayName.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
}

Segue has a very specific meaning, in the context of View Controllers. You probably want to use the phrase "push another view controller" instead.
First off, UINavigationController is typically only used once in a scene -- it's the view controller that keeps track of a stack of sub-View Controllers. You only create one of them, and you probably want to set your HomeController as the nav controller's rootViewController.
Then when the user taps the view you should forward this to a method you will add to HomeController; this will create your custom UserProfile class, configure it with the data it needs, and then call: navigationController?.pushViewController(userProfile, animating: true)
There are many fine tutorials around that show you how this all works.

Related

SwiftUI view sizing is broken when added to UITableViewController

I need to display a SwiftUI view in an existing UITableViewController, as the tableHeaderView. However, it seems that the sizing of the SwiftUI view is broken when it is added to a UITableViewController.
If I simply convert my SwiftUI View to a UIView using a UIHostingController and set it to the tableHeaderView, the view is displayed off screen:
func addHeaderView() {
let view = VerticalTextStack()
let hostingController = UIHostingController(rootView: view)
tableView.tableHeaderView = hostingController.view
}
Incorrect layout
To counteract this, I've tried to fix the height of the view several different ways. Adding an NSLayoutConstraint didn't do anything. When setting tableHeaderView.frame.size manually, the results were better, since at least now the view is displayed on-screen, but the multiline Texts become single-line and truncated.
As you can see here, the 2nd Text gets truncated:
Here's a simplified example showcasing the problem:
/// `UITableViewController` displaying a `UIView` as its `tableHeaderView`
class TableViewController: UITableViewController {
let cellReuseIdentifier = "cell"
let data = ["A", "B", "C", "D", "E"]
let themeManager = AppThemeManager()
// MARK: - UIViewController lifecycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
addHeaderView()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
fixTableHeaderViewSize()
}
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath)
cell.textLabel?.text = data[indexPath.row]
return cell
}
// MARK: - SwiftUI view
func fixTableHeaderViewSize() {
guard let tableHeaderView = tableView?.tableHeaderView else { return }
let expectedHeight = tableHeaderView.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize).height
let expectedSize = CGSize(width: tableHeaderView.frame.width, height: expectedHeight)
tableHeaderView.frame.size = expectedSize
}
func addHeaderView() {
let view = VerticalTextStack()
let hostingController = UIHostingController(rootView: view)
tableView.tableHeaderView = hostingController.view
}
}
private struct VerticalTextStack: View {
let data = ["First", "I am a very long text that only fits in multiple lines. I still continue.", "Third"]
let themeManager = AppThemeManager()
var body: some View {
VStack(spacing: 10) {
ForEach(data, id: \.self) { value in
Text(value)
}
}
}
}
I've also tried moving addHeaderView to other UIViewController functions, such as viewWillLayoutSubviews, but that didn't change anything.
Setting lineLimit to nil or any large number on the Text inside VerticalTextStack and adding .layoutPriority(.greatestFiniteMagnitude) to the Text did not make the Text multiline either.
Here is a possible solution.
Change your add header view funcation with this.
func addHeaderView() {
let view = VerticalTextStack()
let hostingController = UIHostingController(rootView: view)
let headerViewMain = UIView()
headerViewMain.backgroundColor = .red
headerViewMain.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
hostingController.view.topAnchor.constraint(equalTo: headerViewMain.topAnchor),
hostingController.view.leftAnchor.constraint(equalTo: headerViewMain.leftAnchor),
headerViewMain.bottomAnchor.constraint(equalTo: hostingController.view.bottomAnchor),
headerViewMain.rightAnchor.constraint(equalTo: hostingController.view.rightAnchor)
]
NSLayoutConstraint.activate(constraints)
headerViewMain.frame.size.height = headerViewMain.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
headerViewMain.frame.size.width = headerViewMain.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
self.tableHeaderView = headerViewMain
self.layoutIfNeeded()
self.setNeedsLayout()
self.reloadData()
}

navigationController?.pushViewController is not working

I have a collection view controller. In collectionView cell I have label which I made clickable to push to the nextViewController.
I know that problem in navigationController. But I'm new in swift so can't fix. Hope you guys can help me.
Here's my SceneDelegate:
let layout = UICollectionViewFlowLayout()
// Create the root view controller as needed
let nc = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
let win = UIWindow(windowScene: winScene)
win.rootViewController = nc
win.makeKeyAndVisible()
window = win
and my label:
let text = UILabel()
text.text = "something"
text.isUserInteractionEnabled = true
self.addSubview(text)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(PopularCellTwo.labelTapped))
text.addGestureRecognizer(gestureRecognizer)
}
#objc func labelTapped() {
let nextVC = NextViewController()
self.navigationController?.pushViewController(nextVC, animated: true)
print("labelTapped tapped")
}
I also added screenshot. When I click on "Something" It should go next page.
[1]: https://i.stack.imgur.com/4oYwb.png
You can use delegate or closure to do this
class ItemCollectionViewCell: UICollectionViewCell {
var onTapGesture: (() -> ())?
}
Then in your function you do
#objc func labelTapped() {
onTapGesture?()
}
And in your controller
class HomeController: UICollectionViewController {
//...
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = // dequeue cell
cell.onTapGesture = { [unowned self] in
let nextVC = NextViewController()
self.navigationController?.pushViewController(nextVC, animated: true)
}
return cell
}
}
self.navigationController?.pushViewController(nextVC, animated: true)
what self are you referring to ? because you cant make push in child class
you have HomeController i assume its your parent controller .
just try to debug what self is this could attempt by debugging or debug by condition
print (self)
if (self.isKind(of: YourParentController.self)) {
// make push
}
or try to check , see if navigationcontroller somehow has nil value
Here is how you do it using closures. I've created a closure parameter in UICollectionViewCell sub-class. When the label gesture target is hit I call the closure which then executed the navigation in HomeController.
class HomeController: UICollectionViewController {
//...
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = // dequeue cell
cell.labelTap = { [weak self] in
guard let self = self else { return }
let nextVC = NextViewController()
self.navigationController?.pushViewController(nextVC, animated: true)
print("navigated")
}
return cell
}
}
class CollectionViewCell: UICollectionViewCell {
var labelTap: (() -> Void)?
#objc func labelTapped() {
print("labelTapped tapped")
labelTap?()
}
}

Navigation Bar is Hidden in JSQMessagesViewController

I am working on incorporating a chat feature in my app and everything is working smoothly using JSQMessagesViewController except that I can't get the navigation bar to show in the view controller. I have tried almost everything it seems like but it seems to be hidden by the view or something although I am not sure of this. Here is my code for the Conversation view controller:
import UIKit
import JSQMessagesViewController
import Firebase
import AVKit
class ConvoVC: JSQMessagesViewController {
var chatRoomId = Variables.chatRoomID
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
var messages = [JSQMessage]()
override func viewDidLoad() {
super.viewDidLoad()
senderId = uid!
senderDisplayName = uid!
let factory = JSQMessagesBubbleImageFactory()
incomingBubbleImageView = factory?.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleLightGray())
outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleBlue())
collectionView.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero
let query = ref.child("ChatRooms").child(chatRoomId!).child("Messages").queryLimited(toLast: 10)
query.observe(.childAdded, with: { (snapshot) in
if snapshot.exists(){
if let data = snapshot.value as? [String: String],
let id = data["sender_id"],
let name = data["name"],
let text = data["text"],
!text.isEmpty
{
if let message = JSQMessage(senderId: id, displayName: name, text: text)
{
self.messages.append(message)
self.finishReceivingMessage()
}
}
}
})
//let navigationBar = UINavigationBar(frame: CGRect(0, 0, self.view.frame.size.width, 64)) // Offset by 20 pixels vertically to take the status bar into account
//navigationBar.backgroundColor = UIColor.white
//navigationBar.delegate = self as! UINavigationBarDelegate
// Create a navigation item with a title
//let navigationItem = UINavigationItem()
//navigationItem.title = contacts[i].firstName
// Create right button for navigation item
setupBackButton()
// Make the navigation bar a subview of the current view controller
//self.view.addSubview(navigationBar)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
self.navigationController?.isNavigationBarHidden = false
}
func setupBackButton() {
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backButtonTapped))
navigationItem.leftBarButtonItem = backButton
}
#objc func backButtonTapped() {
dismiss(animated: true, completion: nil)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.white
} else {
cell.textView!.textColor = UIColor.black
}
return cell
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messages.count
}
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
let messageRef = ref.child("ChatRooms").child(chatRoomId!).child("Messages").childByAutoId()
let message = ["sender_id": senderId, "name": senderDisplayName, "text": text]
messageRef.setValue(message)
finishSendingMessage()
JSQSystemSoundPlayer.jsq_playMessageSentSound()
self.finishSendingMessage()
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item]
if message.senderId == senderId {
return outgoingBubbleImageView
}else {
return incomingBubbleImageView
}
}
}
Here is the code for the didSelectRow method in the class that comes before the conversation view controller:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let chatFunctions = ChatFunctions()
ref.child("users").child(uid!).observeSingleEvent(of: .value) { (snapshot) in
let userOne = User(snapshot: snapshot)
self.chatRoomIdentity = chatFunctions.startChat(user1: userOne , user2: self.matches[indexPath.row])
self.senderDisName = self.matches[indexPath.row].firstName
Variables.chatRoomID = self.chatRoomIdentity
self.present(ConvoVC(), animated: true, completion: nil)
}
}
Thanks in advance!
You are presenting it modally on this line which would present it full screen (so no navigation bar):
self.present(ConvoVC(), animated: true, completion: nil)
Push it onto the navigation stack instead like this:
self.navigationController?.pushViewController(ConvoVC(), animated: true)
If you don't have your first controller set as the root view controller of a navigation controller, make sure to do so beforehand.
Either that or set ConvoVC as a root view controller of a navigation controller and present that navigation controller
self.present(navigationController, animated: true, completion: nil).
The first solution will let you pop the ConvoVC and back to the previous view controller via the navigation bar, whereas the latter will not (you would have to dismiss it).
I highly recommend reading up on iOS navigation & segues as it's a core aspect of any iOS application.

Tab Bar Item hidden behind tableview / not being shown?

I have an empty view with a tab bar pictured below, when i load a routine a table appears containing the contents, however it seems to overlay the tab bar killing off app navigation. Its not sized in the storyboard to overlay it and its constraint locked to not do so, so im unsure why this is happening, pics of the issue and VC's code below:
VC Code:
import Foundation
import UIKit
import CoreData
class RoutineController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: - DECLARATIONS
#IBAction func unwindToRoutine(segue: UIStoryboardSegue) {}
#IBOutlet weak var daysRoutineTable: UITableView!
#IBOutlet weak var columnHeaderBanner: UIView!
#IBOutlet weak var todaysRoutineNavBar: UINavigationBar!
#IBOutlet weak var addTOdaysRoutineLabel: UILabel!
let date = Date()
let dateFormatter = DateFormatter()
let segueEditUserExerciseViewController = "editExerciseInRoutineSegue"
//This is the selected routine passed from the previous VC
var selectedroutine : UserRoutine?
// MARK: - VIEWDIDLOAD
override func viewDidLoad() {
super.viewDidLoad()
setupView()
daysRoutineTable.delegate = self
daysRoutineTable.dataSource = self
view.backgroundColor = (UIColor.customBackgroundGraphite())
dateFormatter.dateStyle = .short
dateFormatter.dateFormat = "dd/MM/yyyy"
let dateStr = dateFormatter.string(from: date)
todaysRoutineNavBar.topItem?.title = dateStr + " Routine"
}
// MARK: - VIEWDIDAPPEAR
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
}
// MARK: - TABLE UPDATE COMPONENTS
private func setupView() {
updateView()
}
// MARK: - TABLE SETUP
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let count = self.selectedroutine?.userexercises?.count
{
print("exercises: \(count)")
return count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? TodaysRoutineTableViewCell else {
fatalError("Unexpected Index Path")
}
cell.backgroundColor = UIColor.customBackgroundGraphite()
cell.textLabel?.textColor = UIColor.white
configure(cell, at: indexPath)
return cell
}
// MARK: - VIEW CONTROLER ELEMENTS VISIBILITY CONTROL
fileprivate func updateView() {
var hasUserExercises = false
if let UserExercise = self.selectedroutine?.userexercises {
hasUserExercises = UserExercise.count > 0
}
addTOdaysRoutineLabel.isHidden = hasUserExercises
columnHeaderBanner.isHidden = !hasUserExercises
daysRoutineTable.isHidden = !hasUserExercises
}
// MARK: - SETTING DATA FOR A TABLE CELL
func configure(_ cell: TodaysRoutineTableViewCell, at indexPath: IndexPath) {
if let userExercise = selectedroutine?.userexercises?.allObjects[indexPath.row]
{
print("\((userExercise as! UserExercise).name)")
cell.todaysExerciseNameLabel.text = (userExercise as! UserExercise).name
cell.todaysExerciseRepsLabel.text = String((userExercise as! UserExercise).reps)
cell.todaysExerciseSetsLabel.text = String((userExercise as! UserExercise).sets)
cell.todaysExerciseWeightLabel.text = String((userExercise as! UserExercise).weight)
}
}
}
requested table constraints
Debug hierarchy
The Segue that sends the user back to the view that looses its tab bar
if segue.identifier == "addToTodaySegue" {
let indexPath = workoutTemplateTable.indexPathForSelectedRow
let selectedRow = indexPath?.row
print("selected row\(selectedRow)")
if let selectedRoutine = self.fetchedResultsController.fetchedObjects?[selectedRow!]
{
if let todaysRoutineController = segue.destination as? RoutineController {
todaysRoutineController.selectedroutine = selectedRoutine
}
}
}
I also feel perhaps the viewDidAppear code may cause the issue, perhaps the super class?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
Updated storyboard image
I suspect you need to embed your viewController in a UINavigationController.
Consider the following setup:
I suspect your setup is like the upper one:
TapBar -> ViewController -show segue-> ViewController
Which results in a hidden tapbar, like in your description:
While the bottom setup:
TapBar -> NavigationCntroller -rootView-> ViewController -show segue-> ViewController
results in:
which is what you want, how I understood.
Update
It's hard to see. The screenshot of your Storyboard is in pretty low resulution, but the segues look wrong. Double check them. A Segue of type show (e.g push) looks like this:
Also clear project and derived data. Segue type changes sometime are ignored until doing so.
Try calling this self.view.bringSubviewToFront(YourTabControl).
The previous suggestion should work. But the content at the bottom part of tableview will not be visible as the tabbar comes over it. So set the bottom constraint of tableview as the height of tabbar.

UIView is always behind UITableView

I have a UIViewController (not a UITableViewController because I read that a view controller is best for this kind of behaviour) with a UITableView. In this view controller I want to add a floating UIView and place it above my tableview, to do so I wrote:
public override func viewDidLoad() {
super.viewDidLoad()
// add button
let fbv = liquidActionButtonInstance.addActionButton() // this is a UIView
self.view.addSubview(fbv)
liquidActionButtonInstance.delegate = self
// delegate
tableView.delegate = self
tableView.dataSource = self
}
However my floating view appears behind my UITableView, how can I add it as the first child of self.view? I've used
self.view.addSubview(fbv)
self.view.bringSubviewToFront(fbv)
Among others and none seems to work.
Edit:
I added some screenshots of my view's hierarchy.
Edit 2:
Here I put a little more code:
My ViewController without some unrelated code:
public class ActividadesTableViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var descripcionFiltrosLabel: UILabel!
#IBOutlet weak var filtrosLabelBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var filtrosLabelTopConstraint: NSLayoutConstraint!
#IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint!
private var liquidActionButtonInstance: FloatingActionButton = FloatingActionButton()
public var viewModel : ActividadesTableViewModeling?
public override func viewDidLoad() {
super.viewDidLoad()
// Agregar action button
self.view.insertSubview(liquidActionButtonInstance.addActionButton(),aboveSubview: tableView)
liquidActionButtonInstance.delegate = self
// set row's height
tableView.estimatedRowHeight = 70
tableView.rowHeight = UITableViewAutomaticDimension
// delegate
tableView.delegate = self
tableView.dataSource = self
// load tableview data
if let viewModel = viewModel {
viewModel.loadActividades(withFilters: nil)
}
}
}
// MARK: FloatingButton
extension ActividadesTableViewController: FloatingActionButtonDelegate {
public func performSegueFromFloatingActionButton(segueName name: String) {
performSegueWithIdentifier(name, sender: self)
}
}
// MARK: TableView
extension ActividadesTableViewController: UITableViewDataSource, UITableViewDelegate {
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Omitting this code, just mentioning the methods
}
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ActividadCell", forIndexPath: indexPath) as! ActividadTableViewCell
if let viewModel = viewModel {
cell.viewModel = viewModel.cellModels.value[indexPath.row]
} else {
cell.viewModel = nil
}
return cell
}
public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
And this is how I add the button (in a different class):
func addActionButton() -> LiquidFloatingActionButton {
let createButton: (CGRect, LiquidFloatingActionButtonAnimateStyle) -> LiquidFloatingActionButton = { (frame, style) in
let floatingActionButton = LiquidFloatingActionButton(frame: frame)
floatingActionButton.animateStyle = style
floatingActionButton.dataSource = self
floatingActionButton.delegate = self
floatingActionButton.color = ColoresKairos.principal2
return floatingActionButton
}
let cellFactory: (String) -> LiquidFloatingCell = { (iconName) in
return LiquidFloatingCell(icon: UIImage(named: iconName)!)
}
cells.append(cellFactory("iphone-action-button-group"))
cells.append(cellFactory("iphone-action-button-notepad"))
cells.append(cellFactory("iphone-action-button-check-box"))
let floatingFrame = CGRect(x: UIScreen.mainScreen().bounds.width - 56 - 16, y: UIScreen.mainScreen().bounds.height - 56 - 16, width: 56, height: 56)
let bottomRightButton = createButton(floatingFrame, .Up)
//view.addSubview(bottomRightButton)
//return view
return bottomRightButton
}
You need to add the view using addSubview(_:) AND bringToFront(_:). You can also try sending the tableView to the back using sendToBack(_:)
In your document outline menu in your storyboard, you can place your floating view below your TableView in view hierarchy. Then, you can always see your floating view placed above your tableview.
It's gonna be like this.
▼ Your ViewController
Top Layout Guide
Bottom Layout Guide
▼View
▶︎ TableView
▶︎ Floating View
Below is the code that is working along with its screenshot, I suspect that your call liquidActionButtonInstance.addActionButton() returns an empty button?
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
private var liquidButton: LiquidFloatingActionButton?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Setting up the liquid button
liquidButton = createLiquidButton()
view.addSubview(liquidButton!)
}
func createLiquidButton() -> LiquidFloatingActionButton {
let frame = CGRect(x: UIScreen.mainScreen().bounds.width - 56 - 16, y: UIScreen.mainScreen().bounds.height - 56 - 16, width: 56, height: 56)
let button = LiquidFloatingActionButton(frame: frame)
button.animateStyle = .Up
button.color = UIColor.redColor()
return button
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
// UITableView Implementation, not included not relevent for the example.
}
The error here, after debugging the view hierarchy was that my tableView wasn't being added directly to the UIViewController's hierarchy, so it was added above everything else, and adding my FloatingButton as a subview of UIViewController always resulted on it being hidden by my tableView.
My tableView is added via storyboard, and as far as I know this is not the expected behaviour, but in my case just adding the following lines:
self.view.addSubview(tableView)
self.view.addSubview(liquidActionButtonInstance.addActionButton())
Solved my problem.