SWIFT UIPanGestureRecognizer failed only first time - swift

My test app have 4 ScrollView.
UIScrollView which can scroll up/down.
UIPageViewController inside 1, which can scroll left/right.
UITableView inside one of viewController 2, can scroll up/down.
UIScrollView inside UITableViewCell on tableView 3, can scroll left/right.
https://i.stack.imgur.com/BexX3.jpg
First swipe gesture by UIScrollView 4 causes PageViewController 2 scroll instead. Second and more swipes work correct.
PanGestureRecognizer of UIScrollView 4 has a state "failed" on the first swipe.
<UIScrollViewPanGestureRecognizer: 0x7f826881fd50; state = Failed; delaysTouchesEnded = NO; view = <Tests.MyCellScroll 0x7f826802f600>; target= <(action=handlePan:, target=<Tests.MyCellScroll 0x7f826802f600>)>>
Any ideas what’s the problem or how could it be debugged?
Example
class ViewController: UIViewController {
private let vcs: [UIViewController] = [
MyVC(),
UIViewController()
]
private lazy var scroll: UIScrollView = {
let scroll = UIScrollView()
scroll.backgroundColor = .systemPink
return scroll
}()
private lazy var pageVC: UIPageViewController = {
let page = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
page.view.backgroundColor = .white
page.delegate = self
page.dataSource = self
return page
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.scroll)
self.addChild(self.pageVC)
self.scroll.addSubview(self.pageVC.view)
self.pageVC.didMove(toParent: self)
self.pageVC.setViewControllers([self.vcs[0]], direction: .forward, animated: true, completion: nil)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.scroll.frame = self.view.frame
self.scroll.contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height + 50)
self.pageVC.view.frame = CGRect(x: self.scroll.bounds.minX, y: self.scroll.bounds.minY + 250, width: self.scroll.bounds.width, height: self.scroll.contentSize.height - 250)
}
}
extension ViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
self.vcs.firstIndex(of: viewController) == 1 ? self.vcs[0] : nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
self.vcs.firstIndex(of: viewController) == 0 ? self.vcs[1] : nil
}
}
final class MyVC: UIViewController {
private lazy var table: UITableView = {
let table = UITableView()
table.register(MyCell.self, forCellReuseIdentifier: String(describing: MyCell.self))
table.delegate = self
table.dataSource = self
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.table)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.table.frame = self.view.frame
}
}
extension MyVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 5 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { MyCell() }
}
final class MyCell: UITableViewCell {
private lazy var subview: UIView = {
let view = UIView()
view.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.7)
return view
}()
private lazy var scrollView: MyCellScroll = {
let view = MyCellScroll()
return view
}()
init(){
super.init(style: .default, reuseIdentifier: nil)
self.contentView.backgroundColor = UIColor.systemOrange.withAlphaComponent(0.7)
self.contentView.addSubview(self.scrollView)
self.scrollView.addSubview(self.subview)
}
override func layoutSubviews() {
super.layoutSubviews()
let frame = self.contentView.frame
self.scrollView.frame = frame
self.scrollView.contentSize = CGSize(width: 500, height: frame.height)
self.subview.frame = CGRect(x: 16, y: 8, width: 500 - 32, height: frame.height - 16)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
final class MyCellScroll: UIScrollView, UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
print(gestureRecognizer)
return false // 5
}
}

Related

TextField rejected resignFirstResponder when being removed from hierarchy

I'm trying to make a custom textfield/sendbutton view that overrides inputAccessoryView, but I'm having 2 problems I can't seem to solve:
When the custom view becomes the first responder, I get this warning twice:
CustomKeyboardProject[5958:3107074] API error:
<_UIKBCompatInputView: 0x119e2bd70; frame = (0 0; 0 0);
layer = <CALayer: 0x283df9e00>> returned 0 width,
assuming UIViewNoIntrinsicMetric
Then when I try to resign the custom view as the first responder, Xcode throws this warning:
CustomKeyboardProject[5958:3107074] -[UIWindow
endDisablingInterfaceAutorotationAnimated:] called on <UITextEffectsWindow:
0x11a055400; frame = (0 0; 375 667); opaque = NO; autoresize = W+H; layer =
<UIWindowLayer: 0x283df78a0>> without matching
-beginDisablingInterfaceAutorotation. Ignoring.
Has anyone been able to silence these warnings?
Heres my code:
protocol CustomTextFieldDelegate: class {
func sendMessage()
}
class CustomTextField: UITextField {
override var canBecomeFirstResponder: Bool {
return true
}
override var canResignFirstResponder: Bool {
return true
}
}
class CustomKeyboardView: UIView {
let textField: CustomTextField = {
let textField = CustomTextField()
textField.backgroundColor = .green
textField.textColor = .white
return textField
}()
let attachButton: UIButton = {
let button = UIButton()
button.backgroundColor = .red
button.setTitle("Attach", for: .normal)
return button
}()
let sendButton: UIButton = {
let button = UIButton()
button.backgroundColor = .blue
button.setTitle("Send", for: .normal)
button.addTarget(self, action: #selector(sendMessage), for: .touchUpInside)
return button
}()
#objc func sendMessage() {
delegate?.sendMessage()
}
weak var delegate: CustomTextFieldDelegate?
init() {
super.init(frame: .zero)
isUserInteractionEnabled = true
setViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setViews() {
let subviews = [attachButton, sendButton, textField]
subviews.forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
addSubview($0)
}
autoresizingMask = .flexibleHeight
subviews.forEach {
NSLayoutConstraint.activate([
$0.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
layoutSubviews()
[attachButton, sendButton].forEach {
NSLayoutConstraint.activate([
$0.widthAnchor.constraint(equalTo: $0.heightAnchor),
$0.heightAnchor.constraint(equalTo: textField.heightAnchor)
])
}
NSLayoutConstraint.activate([
textField.topAnchor.constraint(equalTo: topAnchor),
attachButton.leftAnchor.constraint(equalTo: leftAnchor),
textField.leadingAnchor.constraint(equalTo: attachButton.trailingAnchor),
sendButton.leadingAnchor.constraint(equalTo: textField.trailingAnchor),
sendButton.trailingAnchor.constraint(equalTo: trailingAnchor),
])
}
override var intrinsicContentSize: CGSize {
return .zero
}
}
class CustomTableView: UITableView {
let keyboardView = CustomKeyboardView()
override init(frame: CGRect, style: UITableView.Style) {
super.init(frame: frame, style: style)
keyboardDismissMode = .interactive
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var canBecomeFirstResponder: Bool {
return true
}
override var canResignFirstResponder: Bool {
return true
}
override var inputAccessoryView: UIView? {
return keyboardView
}
}
private let reuseId = "MessageCellId"
class ExampleViewController: UITableViewController {
private let customTableView = CustomTableView()
var messages = [String]()
override func loadView() {
tableView = customTableView
view = tableView
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.becomeFirstResponder()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseId)
customTableView.keyboardView.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
DispatchQueue.main.async {
self.customTableView.keyboardView.textField.becomeFirstResponder()
}
}
// tableView delegate methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseId)
cell?.textLabel?.text = messages[indexPath.row]
return cell!
}
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
customTableView.keyboardView.textField.resignFirstResponder()
}
}
extension ExampleViewController: CustomTextFieldDelegate {
func sendMessage() {
// double check something is in textField
let textField = customTableView.keyboardView.textField
guard let body = textField.text, body != "" else { return }
messages.append(body)
tableView.reloadData()
view.endEditing(true)
customTableView.keyboardView.textField.text = ""
}
}

PageViewController transparent or no background

I have problem with PageViewController dots indicators. Actually with background. I tried UIColor.clear but this didn't help. Background still white. I can change the color but I don't know how to remove it or make it transparent.
Can't find a way how to make it transparent.
Screenshot attached.
How to make background color transparent or remove it?
ViewController.swift
import Foundation
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
// Hide status bar.
override var prefersStatusBarHidden : Bool {
return true
}
var pageViewController: UIPageViewController!
let pages = ["DomesticPageViewController", "SafariPageViewController", "ForestPageViewController"]
// Page View Controller Datasource
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let index = pages.index(of: viewController.restorationIdentifier!) {
if index > 0 {
return viewControllerAtIndex(index - 1)
}
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let index = pages.index(of: viewController.restorationIdentifier!) {
if index < pages.count - 1 {
return viewControllerAtIndex(index + 1)
}
}
return nil
}
func viewControllerAtIndex(_ index: Int) -> UIViewController? {
let vc = storyboard?.instantiateViewController(withIdentifier: pages[index])
return vc
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let vc = storyboard?.instantiateViewController(withIdentifier: "MyPageViewController") {
self.addChildViewController(vc)
self.view.addSubview(vc.view)
pageViewController = vc as! UIPageViewController
pageViewController.dataSource = self
pageViewController.delegate = self
pageViewController.setViewControllers([viewControllerAtIndex(0)!], direction: .forward, animated: true, completion: nil)
pageViewController.didMove(toParentViewController: self)
}
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.lightGray
appearance.currentPageIndicatorTintColor = UIColor.black
appearance.backgroundColor = UIColor.clear
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
setupPageControl()
return self.pages.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
DomesticViewController.swift
import Foundation
import UIKit
class DomesticPageViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImageView(frame: UIScreen.main.bounds)
backgroundImage.image = UIImage(named: "domestic_bg1")
backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
self.view.insertSubview(backgroundImage, at: 0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

How to set the preferredContentSize of a UIViewController to the height of a containing UITableView contentSize?

I call a popover like the following:
if let vc = CalendarDetailViewControllerContainer.storyboardInstance() {
vc.preferredContentSize = CGSize(width: ((self.view.frame.width / 5) * 2), height: vc.view.frame.height);
vc.modalPresentationStyle = UIModalPresentationStyle.popover;
vc.popoverPresentationController?.delegate = self;
vc.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.any;
vc.popoverPresentationController?.sourceView = sourceView;
vc.popoverPresentationController?.sourceRect = CGRect(x: 0, y: 0, width: sourceView.frame.size.width, height: sourceView.frame.size.height);
self.present(vc, animated: true, completion: nil);
}
As you can see for now I set the preferredContentSize height to vc.view.frame.height. But that should be different. For now, more code. In the following my CalendarDetailViewControllerContainer:
class CalendarDetailViewControllerContainer : UIViewController {
#IBOutlet weak var containerView: UIView!;
static func storyboardInstance() -> CalendarDetailViewControllerContainer? {
let storyboard = UIStoryboard(name: String(describing: NSStringFromClass(CalendarDetailViewControllerContainer.classForCoder()).components(separatedBy: ".").last!), bundle: nil);
return storyboard.instantiateInitialViewController() as? CalendarDetailViewControllerContainer;
}
override func viewDidLoad() {
super.viewDidLoad();
self.setupView();
self.setupDetailView();
}
func setupView() {
self.view.backgroundColor = UIColor.clear;
self.view.isOpaque = false;
}
func setupDetailView() {
if let vc = CalendarDetailViewController.storyboardInstance() {
let navigationController = UINavigationController(rootViewController: vc);
self.addChildViewController(navigationController);
navigationController.view.frame = self.containerView.frame;
self.containerView.addSubview(navigationController.view);
navigationController.didMove(toParentViewController: self);
}
}
}
I need this container because for later purposes and future segues I will need the navigation controller (and I wont build it in storyboard). So the last part of the code:
class CalendarDetailViewController : UITableViewController {
static func storyboardInstance() -> CalendarDetailViewController? {
let storyboard = UIStoryboard(name: String(describing: NSStringFromClass(CalendarDetailViewController.classForCoder()).components(separatedBy: ".").last!), bundle: nil);
return storyboard.instantiateInitialViewController() as? CalendarDetailViewController;
}
override func viewDidLoad() {
self.navigationController?.isNavigationBarHidden = true;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 120.0;
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude;
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude;
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension;
}
}
What I now try to do is to set the preferredContentSize height of the popover to be exactly the contentSize of the table view.
How can I do that?
You can override preferredContentSize for CalendarDetailViewControllerContainer, but make sure that you reloaded table and calling layoutIfNeeded() before calculating the size.
public override var preferredContentSize: CGSize {
get {
return CGSize(width: tableView.contentSize.width,
height: tableView.contentSize.height + tableView.layoutMargins.top + tableView.layoutMargins.bottom)
}
set { super.preferredContentSize = newValue }
}

UITableViewCell with Custom View

i am desperately trying to add a custom View to a UITableViewCell. I have a UITableViewController in Storyboard wich is linked to a TestTableViewController Class and the prototype cell has the identifier "Cell2".
So this is the code in UITableViewController:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return dataArray.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 190
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath)
let data = dataArray[indexPath.row]
let ticket = YellowTackleTicketComplete()
ticket.frame = CGRect(x: 20, y: 20, width: 335, height: 150)
cell.addSubview(ticket)
// cell.textLabel!.text = tackl!.valueForKey("title") as? String
cell.backgroundColor = UIColor.clearColor()
print(cell.subviews)
return cell
}
The dataArray is just for testing purposes and has one item in it. So what i get is a Table View with one empty cell. In the Xcode UI Debugger i can see the custom view. But its not shown in the simulator or on a device.
If anyone can help, thank you so much!
This is the code of the view:
class YellowTackleTicketComplete: UIView {
var containerView: UIView!
var ticket: TacklTicket!
var dropDownMenu: YellowDrawer!
var dropDownBackground: YellowDrawerBackground!
var ticketShadowLine: UIView!
var lowAlphaView: UIView!
var outbackButton: UIButton!
var arrowView: UIView!
var bounceHeight: CGFloat?
var dropdownHeight: CGFloat?
var topBorder: CGFloat?
var bottomBorder: CGFloat?
//let arrowLayer = CALayer()
//let layerDelegate = LayerDelegate()
var dropDownElements = [String]()
var dropped = false
var animating = false
var delegate: YellowTackleTicketCompleteDelegate?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addObserver(self, forKeyPath: "highlighted", options: NSKeyValueObservingOptions.New, context: nil)
}
override init(frame: CGRect) {
super.init(frame: frame)
self.addObserver(self, forKeyPath: "highlighted", options: NSKeyValueObservingOptions.New, context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
self.setNeedsDisplay()
if keyPath == "frame" {
// Set up DropdownMenu
self.dropDownBackground.frame.size.height = self.dropDownMenu.frame.maxY
}
}
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
if(!self.clipsToBounds && !self.hidden && self.alpha > 0.0){
let subviews = self.subviews.reverse()
for member in subviews {
let subPoint = member.convertPoint(point, fromView: self)
if let result:UIView = member.hitTest(subPoint, withEvent:event) {
return result;
}
}
}
return nil
}
func ticketTapped() {
//if !animating {
if !dropped {
showDropdown()
NSLog("#")
// NSLog("Scrolling to \((dropDownMenu.indexPathForSelectedRow?.row)!)(the index of the tableview selection)")
// dropDownMenu.scrollToRowAtIndexPath((dropDownMenu.indexPathForSelectedRow)!, atScrollPosition: .Middle, animated: false)
} else {
hideDropdown()
}
// }
}
func showDropdown() {
dropDownMenu.hidden = false
self.ticket.drawShadowBeneathTicket()
print("showing")
if !animating {
animating = true
UIView.animateWithDuration(
1.0,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: [],
animations: {
self.dropDownMenu.frame.origin.y = self.bottomBorder!
}, completion: { _ in
//self.delegate?.menuOpen?()
self.animating = false
print(self.dropDownBackground.frame.size.height)
print(self.dropDownMenu.frame.maxY)
}
)
}
self.setNeedsDisplay()
self.dropDownMenu!.setNeedsDisplay()
dropped = true
}
func hideDropdown() {
if !animating {
animating = true
UIView.animateWithDuration(
0.7,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: [],
animations: {
self.dropDownMenu.frame.origin.y = self.topBorder! + self.bounceHeight!
}, completion: nil
)
}
UIView.animateWithDuration(
0.5,
delay: 0,
options: UIViewAnimationOptions.TransitionNone,
animations: {
self.dropDownMenu.frame.origin.y = self.topBorder! - self.dropdownHeight!
}, completion: { _ in
//self.delegate?.menuClosed?()
self.animating = false
self.dropDownMenu.hidden = true
self.ticket.setNeedsDisplay()
self.setNeedsDisplay()
}
)
dropped = false
}
func initSubViews() {
self.topBorder = self.frame.height*6/150
self.bottomBorder = self.frame.height - self.topBorder!
self.bounceHeight = 250
self.dropdownHeight = 350
containerView = UIView()
containerView.frame = CGRect(x: 0, y: topBorder!, width: self.bounds.width, height: dropdownHeight!+bounceHeight!)
containerView.clipsToBounds = true
ticket = TacklTicket()
ticket.frame = self.bounds
ticket.addTarget(self, action: #selector(YellowTackleTicketComplete.ticketTapped), forControlEvents: .TouchDown)
dropDownMenu = YellowDrawer()
dropDownMenu.frame = CGRect(x: 0, y: topBorder! - dropdownHeight!, width: containerView.bounds.width, height: dropdownHeight!)
dropDownMenu.hidden = true
dropDownMenu.backgroundColor = UIColor.clearColor()
dropDownMenu.addObserver(self, forKeyPath: "frame", options: .New, context: nil)
dropDownBackground = YellowDrawerBackground()
dropDownBackground.frame = CGRectMake(0,0,self.bounds.width,self.dropDownMenu.frame.maxY)
self.addSubview(containerView)
containerView.addSubview(dropDownBackground)
containerView.addSubview(dropDownMenu)
self.addSubview(ticket)
}
}
You should use a designated initializer for your UIView subview. That is either init(frame:CGRect) or in add it in Interface Builder. You are also not passing let data = dataArray[indexPath.row] to your cell, not sure if you're aware of that. You also never call initSubViews() which seems to be a big part of your custom view.
instead of
cell.addSubview(ticket)
try
cell.contentView.addSubview(ticket)
and the best place to customize cell's content is its init function.
Couple of things you should try, set translatesAutoresizingMaskIntoConstraints to false on the view you created programmatically since you are inserting it into an auto layout controller.
View that should also try just setting,
dropDownMenu, dropDownBackground, containerView and ticket
or
In your cellForRowAtIndexPath also try setting the property
ticket.translatesAutoresizingMaskIntoConstraints = false

When adding a Search Bar and Search Display Controller to a complex tableHeaderView, The UISearchBar disappears when it gains focus

I am using a single ViewController and an associated NIB, no storyboard. I'm ready to pull my hair out.
The Issue
Notice in the video after focusing, a tiny bit of the field is visible in the top left corner, only to disappear completely after clicking on the shaded area over the UITableView. When going into the view hierarchy, it shows that the searchBar is being moved out of its original hierarchal position.
This video
The NIB
Screenshot of the NIB, showing the structure of the tableHeaderView
The Code
import UIKit
class ViewController: UIViewController, UITableViewDataSource,
UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate {
#IBOutlet weak var bigLabel: UILabel!
#IBOutlet weak var buttonGroupSegment: UISegmentedControl!
#IBOutlet var tableViewHeader: UIView!
#IBOutlet weak var tableView: UITableView!
#IBOutlet var searchBar: UISearchBar!
// MARK: VIEW CONTROLLER
override init() {
super.init(nibName: "ViewController", bundle: nil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.initTableView();
}
override func viewDidLoad() {
super.viewDidLoad();
self.initLabelStyling();
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: TABLE VIEW HEADER
func initTableViewHeader() -> Void{
self.tableView.tableHeaderView = self.tableViewHeader;
self.initSearchView();
self.initSegmentedControl();
}
// MARK: THE SEGMENTED CONTROL
func initSegmentedControl() -> Void{
let font = UIFont(name: "HelveticaNeue", size: 10);
let color = UIColor.whiteColor();
let lighterColor = color.colorWithAlphaComponent(0.5);
self.buttonGroupSegment.tintColor = UIColor.clearColor();
self.buttonGroupSegment.setTitleTextAttributes([NSForegroundColorAttributeName : lighterColor, NSFontAttributeName: font!, NSKernAttributeName: 0.7], forState: UIControlState.Normal)
self.buttonGroupSegment.setTitleTextAttributes([NSForegroundColorAttributeName : color, NSFontAttributeName: font!], forState: UIControlState.Selected);
// Change the case of all the titles
let c = self.buttonGroupSegment.subviews.count;
for i in 0..<c{
if let title = self.buttonGroupSegment.titleForSegmentAtIndex(i){
self.buttonGroupSegment.setTitle(title.uppercaseString, forSegmentAtIndex: i);
}
}
}
// MARK: SEARCH VIEW
func initSearchView() -> Void{
let searchBar = self.searchDisplayController!.searchBar;
searchBar.backgroundColor = UIColor.clearColor();
searchBar.backgroundImage = UIImage();
searchBar.barTintColor = UIColor.clearColor();
searchBar.tintColor = UIColor.whiteColor()
let numViews = searchBar.subviews[0].subviews.count;
var searchField: UITextField?
for i in 0..<numViews{
if searchBar.subviews[0].subviews[i].isKindOfClass(UITextField.self) {
searchField = searchBar.subviews[0].subviews[i] as? UITextField;
}
}
if searchField != nil{
// Fonts and colors
let font = UIFont(name: "HelveticaNeue", size: 12);
let textColor = UIColor.whiteColor();
searchField!.font = font;
searchField!.textColor = textColor;
if searchField!.respondsToSelector("setAttributedPlaceholder:"){
if let placeholder = searchField!.placeholder{
let placeHolderColor = UIColor(red: 100, green: 100, blue: 100, alpha: 0.5);
let attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSForegroundColorAttributeName : placeHolderColor, NSFontAttributeName: font!]);
searchField!.attributedPlaceholder = attributedPlaceholder;
}
}
searchField!.backgroundColor = UIColor(red: 100, green: 100, blue: 100, alpha: 0.2);
var searchIcon: UIImageView? = searchField?.leftView as? UIImageView;
searchIcon!.image = searchIcon!.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
searchIcon?.tintColor = UIColor.whiteColor();
var clearIcon: UIImageView? = searchField?.rightView as? UIImageView;
if clearIcon != nil{
clearIcon!.image = clearIcon!.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
clearIcon!.tintColor = UIColor.whiteColor();
}
}
}
// MARK: THE SEARCH VIEW DELEGATE METHODS
func searchDisplayControllerWillBeginSearch(controller: UISearchDisplayController) {
}
func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String!) -> Bool {
self.filterContentForSearchText(searchString, scope:"");
return true;
}
func filterContentForSearchText(searchText: NSString, scope: String) -> Void{
self.dataFiltered = self.data.filter({(pet: String) -> Bool in
let stringMatch = pet.rangeOfString(searchText)
return stringMatch != nil;
})
}
// MARK: TABLE VIEW
let data = ["Cat","Dog","Bird","Fish","Ferret","Rat","Hamster","Chicken","Goat","Pig","Donkey","Monkey", "Rabbit", "Fox", "Snake", "Frog", "Spider","Rooster","Aligator","Pocupine","Squirrel","Duck","Turtle","Lizard","Lama"];
var dataFiltered: [String] = [];
let cellClass: String = "Cell";
func initTableView() -> Void{
self.initTableViewHeader();
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.cellClass);
// MARK: TABLE VIEW DELEGATES AND DATA SOURCE METHODS
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
if tableView == self.searchDisplayController!.searchResultsTableView{
return self.dataFiltered.count
}else{
return self.data.count;
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell: UITableViewCell?
cell = self.tableView.dequeueReusableCellWithIdentifier(cellClass) as? UITableViewCell;
if (cell == nil){
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: self.cellClass)
}
if tableView == self.searchDisplayController!.searchResultsTableView{
cell?.textLabel?.text = self.dataFiltered[indexPath.row]
}else{
cell?.textLabel?.text = self.data[indexPath.row];
}
return cell!;
}
// MARK: STYLE THE LABEL (ADD A LINE)
func initLabelStyling()->Void{
let v = UIView(frame: CGRectMake(0, 0, self.bigLabel.frame.width, 1));
v.backgroundColor = UIColor(red: 100, green: 100, blue: 100, alpha: 0.2);
self.bigLabel.addSubview(v)
}
}
Has this been resolved? I know it has something to do with the nav bar in the Navigation Controller being over-layed on top of the search bar. If you run it in simulator for iPhone 6, then turn it to landscape you can see the search bar under the nav bar. Will report back if n when I have a solution!
Edit: There we go, got it!
I added the below (setNavigationBarHidden), there's probably a better place for it but since I am just prototyping that will do for now:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.searchDisplayController!.active {
self.navigationController?.setNavigationBarHidden(true, animated: true)
return self.filteredPlayers.count
} else {
return self.selectedPlayers.count
}
}
...
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if self.searchDisplayController!.active {
self.selectedPlayers.append(self.filteredPlayers[indexPath.row])
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.searchDisplayController!.setActive(false, animated: true)
self.tableView.reloadData()
}
}