From f9ac3b25005dac7b2dfb15e9ce6ea3a12cc91b26 Mon Sep 17 00:00:00 2001 From: David FABREGUETTE Date: Fri, 1 Jun 2018 14:55:57 +0200 Subject: [PATCH 1/4] Add an optional item id to make keep track a item selections after tableview reload --- SwiftMultiSelect/CustomTableCell.swift | 3 ++- .../MultiSelectionCollectionView.swift | 18 +++++++------ .../MultiSelectionTableView.swift | 23 ++++++++++------- SwiftMultiSelect/SwiftMultiSelect.swift | 25 ++++++++++++------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/SwiftMultiSelect/CustomTableCell.swift b/SwiftMultiSelect/CustomTableCell.swift index e5c2f76..8f8406a 100644 --- a/SwiftMultiSelect/CustomTableCell.swift +++ b/SwiftMultiSelect/CustomTableCell.swift @@ -11,7 +11,8 @@ import Foundation /// Class to represent custom cell for tableview class CustomTableCell: UITableViewCell { - + var item:SwiftMultiSelectItem? + /// Lazy var for label title open fileprivate(set) lazy var labelTitle: UILabel = { diff --git a/SwiftMultiSelect/MultiSelectionCollectionView.swift b/SwiftMultiSelect/MultiSelectionCollectionView.swift index ab3e09b..b6950c3 100644 --- a/SwiftMultiSelect/MultiSelectionCollectionView.swift +++ b/SwiftMultiSelect/MultiSelectionCollectionView.swift @@ -154,9 +154,11 @@ extension MultiSelecetionViewController:UICollectionViewDelegate,UICollectionVie SwiftMultiSelect.delegate?.swiftMultiSelect(didUnselectItem: item!) //Reload cell state - reloadCellState(row: idp, selected: false) - - + if let item = item { + reloadCellState(row: idp, item: item, selected: false) + } + + if selectedItems.count <= 0{ //Toggle scrollview toggleSelectionScrollView(show: false) @@ -175,10 +177,12 @@ extension MultiSelecetionViewController:UICollectionViewDelegate,UICollectionVie //Scroll to selected item self.selectionScrollView.scrollToItem(at: lastItemIndex, at: .right, animated: true) - - reloadCellState(row: idp, selected: true) - - + + if let item = item { + reloadCellState(row: idp, item: item, selected: true) + } + + } diff --git a/SwiftMultiSelect/MultiSelectionTableView.swift b/SwiftMultiSelect/MultiSelectionTableView.swift index 1247f72..cdfd2b0 100644 --- a/SwiftMultiSelect/MultiSelectionTableView.swift +++ b/SwiftMultiSelect/MultiSelectionTableView.swift @@ -110,7 +110,7 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc //Set initial state if let itm_pre = self.selectedItems.index(where: { (itm) -> Bool in - itm == item + itm == item && item.id == itm.id }){ self.selectedItems[itm_pre].color = cell.initials.backgroundColor! cell.accessoryType = UITableViewCellAccessoryType.checkmark @@ -143,10 +143,16 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc /// - Parameters: /// - row: index of row /// - selected: true = chechmark, false = none - func reloadCellState(row:Int, selected:Bool){ - - if let cell = self.tableView.cellForRow(at: IndexPath(row: row, section: 0)) as? CustomTableCell{ - cell.accessoryType = (selected) ? .checkmark : .none + func reloadCellState(row:Int, item: SwiftMultiSelectItem, selected:Bool){ + print("row selected", row, selected, item) + + if let cell = self.tableView.cellForRow(at: IndexPath(row: row, section: 0)) as? CustomTableCell { + var selectedAndFoundInTable = selected + if let cellItem = cell.item, let cellItemId = cellItem.id, let itemId = item.id { + print("selected...", cellItemId, itemId) + selectedAndFoundInTable = selected && cellItemId == itemId + } + cell.accessoryType = selectedAndFoundInTable ? .checkmark : .none } } @@ -202,7 +208,7 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc if searchString != ""{ searchBar.text = "" searchString = "" - SwiftMultiSelect.delegate?.userDidSearch(searchString: "") + SwiftMultiSelect.delegate?.userDidSearch(searchString: "", tableView: self.tableView) self.tableView.reloadData() } @@ -223,9 +229,8 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc self.perform(#selector(self.hideKeyboardWithSearchBar(_:)), with: searchBar, afterDelay: 0) self.searchString = "" } - - SwiftMultiSelect.delegate?.userDidSearch(searchString: searchText) - + SwiftMultiSelect.delegate?.userDidSearch(searchString: searchText, tableView: self.tableView) + self.tableView.reloadData() } diff --git a/SwiftMultiSelect/SwiftMultiSelect.swift b/SwiftMultiSelect/SwiftMultiSelect.swift index 854c36a..9bae953 100644 --- a/SwiftMultiSelect/SwiftMultiSelect.swift +++ b/SwiftMultiSelect/SwiftMultiSelect.swift @@ -192,11 +192,13 @@ public struct SwiftMultiSelectItem{ public var row : Int? ///Unique identifier - fileprivate(set) var id : Int? - + fileprivate(set) var id : String? + /// String representation for struct public var string : String{ var describe = "\n+--------------------+" + + describe += "\n| id: \(id)" describe += "\n| title: \(title)" describe += "\n| description: \(String(describing: self.description))" describe += "\n| userInfo: \(String(describing: userInfo))" @@ -204,7 +206,7 @@ public struct SwiftMultiSelectItem{ describe += "\n+--------------------+" return describe } - + /// Constructor for item struct /// /// - Parameters: @@ -213,11 +215,14 @@ public struct SwiftMultiSelectItem{ /// - image: image asset /// - imageURL: image url /// - userInfo: optional information data - public init(row:Int,title:String,description:String? = nil,image:UIImage? = nil,imageURL:String? = nil,color:UIColor? = nil, userInfo:Any? = nil) { - + public init(row:Int,title:String, id:String? = nil, description:String? = nil,image:UIImage? = nil,imageURL:String? = nil,color:UIColor? = nil, userInfo:Any? = nil) { + self.title = title self.row = row - + + if let id = id{ + self.id = id + } if let desc = description{ self.description = desc } @@ -302,9 +307,11 @@ public protocol SwiftMultiSelectDelegate{ func didCloseSwiftMultiSelect() /// Tell to delegate user has closed without select - func userDidSearch(searchString:String) - - +// func userDidSearch(searchString:String) + + func userDidSearch(searchString:String, tableView: UITableView) + + } // MARK: - UIImageView From 55de81d3941a61a741faeaaa5b143d1e69201c5a Mon Sep 17 00:00:00 2001 From: David FABREGUETTE Date: Fri, 1 Jun 2018 15:01:02 +0200 Subject: [PATCH 2/4] removed prints --- .../MultiSelectionTableView.swift | 97 +++++++++---------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/SwiftMultiSelect/MultiSelectionTableView.swift b/SwiftMultiSelect/MultiSelectionTableView.swift index cdfd2b0..6436570 100644 --- a/SwiftMultiSelect/MultiSelectionTableView.swift +++ b/SwiftMultiSelect/MultiSelectionTableView.swift @@ -11,17 +11,17 @@ import Contacts // MARK: - UITableViewDelegate,UITableViewDataSource extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSource{ - + func numberOfSections(in tableView: UITableView) -> Int { return 1 } - + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return false } - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - + if SwiftMultiSelect.dataSourceType == .phone{ if searchString == "" { return SwiftMultiSelect.items!.count @@ -29,25 +29,25 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc return SwiftMultiSelect.items!.filter({$0.title.lowercased().contains(searchString.lowercased()) || ($0.description != nil && $0.description!.lowercased().contains(searchString.lowercased())) }).count } }else{ - + //Try to get rows from delegate guard let rows = SwiftMultiSelect.dataSource?.numberOfItemsInSwiftMultiSelect() else { return 0 } - + return rows } - + } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - + //Get Reference to Cell let cell : CustomTableCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableCell cell.selectionStyle = .none var item:SwiftMultiSelectItem! - + if SwiftMultiSelect.dataSourceType == .phone{ item = (searchString == "") ? SwiftMultiSelect.items![indexPath.row] : SwiftMultiSelect.items!.filter({$0.title.lowercased().contains(searchString.lowercased()) || ($0.description != nil && $0.description!.lowercased().contains(searchString.lowercased())) })[indexPath.row] }else{ @@ -60,11 +60,11 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc cell.labelSubTitle.text = item.description cell.initials.isHidden = true cell.imageAvatar.isHidden = true - + if let contact = item.userInfo as? CNContact{ DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async { - + if(contact.imageDataAvailable && contact.imageData!.count > 0){ let img = UIImage(data: contact.imageData!) DispatchQueue.main.async { @@ -80,9 +80,9 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc cell.imageAvatar.isHidden = true } } - + } - + }else{ if item.image == nil && item.imageURL == nil{ cell.initials.text = item.getInitials() @@ -100,14 +100,14 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc } } } - + if item.color != nil{ cell.initials.backgroundColor = item.color! }else{ cell.initials.backgroundColor = updateInitialsColorForIndexPath(indexPath) } - - + + //Set initial state if let itm_pre = self.selectedItems.index(where: { (itm) -> Bool in itm == item && item.id == itm.id @@ -117,48 +117,45 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc }else{ cell.accessoryType = UITableViewCellAccessoryType.none } - - + + return cell - + } - - + + /// Function that select a random color for passed indexpath /// /// - Parameter indexpath: /// - Returns: UIColor random, from Config.colorArray func updateInitialsColorForIndexPath(_ indexpath: IndexPath) -> UIColor{ - + //Applies color to Initial Label let randomValue = (indexpath.row + indexpath.section) % Config.colorArray.count - + return Config.colorArray[randomValue] - + } - - + + /// Function to change accessoryType for passed index /// /// - Parameters: /// - row: index of row /// - selected: true = chechmark, false = none func reloadCellState(row:Int, item: SwiftMultiSelectItem, selected:Bool){ - print("row selected", row, selected, item) - if let cell = self.tableView.cellForRow(at: IndexPath(row: row, section: 0)) as? CustomTableCell { var selectedAndFoundInTable = selected if let cellItem = cell.item, let cellItemId = cellItem.id, let itemId = item.id { - print("selected...", cellItemId, itemId) selectedAndFoundInTable = selected && cellItemId == itemId } cell.accessoryType = selectedAndFoundInTable ? .checkmark : .none } - + } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - + //Get selected cell let cell = tableView.cellForRow(at: indexPath) as! CustomTableCell @@ -170,38 +167,38 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc //Try to get item from delegate item = SwiftMultiSelect.dataSource?.swiftMultiSelect(itemAtRow: indexPath.row) } - - //Save item data + + //Save item data item.color = cell.initials.backgroundColor! //Check if cell is already selected or not if cell.accessoryType == UITableViewCellAccessoryType.checkmark { - + //Set accessory type cell.accessoryType = UITableViewCellAccessoryType.none //Comunicate deselection to delegate SwiftMultiSelect.delegate?.swiftMultiSelect(didUnselectItem: item) - + //Reload collectionview self.reloadAndPositionScroll(idp: item.row!, remove:true) - + } else{ - + //Set accessory type cell.accessoryType = UITableViewCellAccessoryType.checkmark - + //Add current item to selected selectedItems.append(item) - + //Comunicate selection to delegate SwiftMultiSelect.delegate?.swiftMultiSelect(didSelectItem: item) //Reload collectionview self.reloadAndPositionScroll(idp: item.row!, remove:false) - + } //Reset search @@ -213,15 +210,15 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc } } - + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - + return CGFloat(Config.tableStyle.tableRowHeight) - + } - + // MARK: - UISearchBarDelegate - + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { self.searchString = searchText @@ -233,13 +230,13 @@ extension MultiSelecetionViewController:UITableViewDelegate,UITableViewDataSourc self.tableView.reloadData() } - + @objc func hideKeyboardWithSearchBar(_ searchBar:UISearchBar){ searchBar.resignFirstResponder() } - + func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool{ return true } - + } From b96c7e3a8174ebfc0e702c439602917576c997e8 Mon Sep 17 00:00:00 2001 From: David FABREGUETTE Date: Fri, 1 Jun 2018 15:03:15 +0200 Subject: [PATCH 3/4] fixed format --- SwiftMultiSelect/SwiftMultiSelect.swift | 111 +++++++++++------------- 1 file changed, 53 insertions(+), 58 deletions(-) diff --git a/SwiftMultiSelect/SwiftMultiSelect.swift b/SwiftMultiSelect/SwiftMultiSelect.swift index 9bae953..9f7774d 100644 --- a/SwiftMultiSelect/SwiftMultiSelect.swift +++ b/SwiftMultiSelect/SwiftMultiSelect.swift @@ -10,32 +10,32 @@ import Foundation /// Define the type of datasource public enum SwiftMultiSelectSourceType : Int{ - + case phone = 0 case custom = 1 - + } /// Main static class public class SwiftMultiSelect{ public static var items : [SwiftMultiSelectItem]? - + public static var dataSourceType : SwiftMultiSelectSourceType? = .phone{ didSet{ - + if self.dataSourceType == .phone{ self.getContacts() }else{ self.items = nil } - + } } - + /// Delegate reference public static var delegate : SwiftMultiSelectDelegate?{ - + didSet{ if self.dataSourceType == .phone{ self.getContacts() @@ -43,15 +43,15 @@ public class SwiftMultiSelect{ self.items = nil } } - + } - + public static var dataSource : SwiftMultiSelectDataSource? - + /// Array of initial items selected public static var initialSelected : [SwiftMultiSelectItem] = [SwiftMultiSelectItem]() - - + + /// Function to present a selector in a UIViewContoller claass /// /// - Parameter to: UIViewController current visibile @@ -59,18 +59,18 @@ public class SwiftMultiSelect{ // Create instance of selector let selector = MultiSelecetionViewController() - + // Set initial items selector.selectedItems = initialSelected - + //Create navigation controller let navController = UINavigationController(rootViewController: selector) - + // Present selectora to.present(navController, animated: true, completion: nil) - + } - + private class func getContacts(){ //ATTENTION: You have to provide a info.plist string for access contacts //NSContactsUsageDescription @@ -78,17 +78,17 @@ public class SwiftMultiSelect{ // //Retrieve contacts from phone ContactsLibrary.getContacts { (success, data) in - + self.items = data! - + } } - + class func image(named name: String) -> UIImage? { let image = UIImage(named: name) ?? UIImage(named: name, in: Bundle(for: self), compatibleWith: nil) return image } - + } /// Public struct for configuration and customizations @@ -112,10 +112,10 @@ public struct Config { ThemeColors.pumpkinColor, ThemeColors.sunflowerColor ] - + /// Define the style of tableview public struct tableStyle{ - + //Background color of tableview public static var backgroundColor : UIColor = .white //Height of single row @@ -136,10 +136,10 @@ public struct Config { public static var initials_font : UIFont = UIFont.systemFont(ofSize: 18.0) } - + /// Define the style of scrollview public struct selectorStyle{ - + //Image asset for remove button public static var removeButtonImage : UIImage = SwiftMultiSelect.image(named: "remove")! //The height of selectorview, all subviews will be resized @@ -162,7 +162,7 @@ public struct Config { public static var initials_font : UIFont = UIFont.systemFont(ofSize: 18.0) //Background color of collectionviewcell public static var backgroundCellColor : UIColor = .clear - + } } @@ -182,7 +182,7 @@ public struct ThemeColors{ // Struct that represent single items of the tableView, and CollectionView public struct SwiftMultiSelectItem{ - + public var title : String public var description : String? public var image : UIImage? @@ -190,7 +190,7 @@ public struct SwiftMultiSelectItem{ public var userInfo : Any? public var color : UIColor? public var row : Int? - + ///Unique identifier fileprivate(set) var id : String? @@ -238,10 +238,10 @@ public struct SwiftMultiSelectItem{ if let col = color{ self.color = col } - - + + } - + /// Custom equal function to compare objects /// /// - Parameters: @@ -251,7 +251,7 @@ public struct SwiftMultiSelectItem{ public static func ==(lhs: SwiftMultiSelectItem, rhs: SwiftMultiSelectItem) -> Bool{ return lhs.row == rhs.row } - + /// Custom disequal function to compare objects /// /// - Parameters: @@ -261,54 +261,52 @@ public struct SwiftMultiSelectItem{ public static func != (lhs: SwiftMultiSelectItem, rhs: SwiftMultiSelectItem) -> Bool{ return lhs.row != rhs.row } - + /// Get initial letters /// /// - Returns: String 2 intials func getInitials() -> String { - + let tit = (title as NSString) var initials = String() if title != "" && tit.length >= 2 { initials.append(tit.substring(to: 2)) } - + return initials.uppercased() } - + } /// A data source public protocol SwiftMultiSelectDataSource{ - + /// Ask delegate for current item in row func swiftMultiSelect(itemAtRow row:Int) -> SwiftMultiSelectItem - + /// Asks for the number of items func numberOfItemsInSwiftMultiSelect() -> Int - + } /// A delegate to handle public protocol SwiftMultiSelectDelegate{ - + /// Tell to delegate that user did end selection func swiftMultiSelect(didSelectItems items:[SwiftMultiSelectItem]) - + /// Tell to delegate that item has been selected func swiftMultiSelect(didSelectItem item:SwiftMultiSelectItem) - + /// Tell to delegate that item has been unselected func swiftMultiSelect(didUnselectItem item:SwiftMultiSelectItem) - + /// Tell to delegate user has closed without select func didCloseSwiftMultiSelect() - - /// Tell to delegate user has closed without select -// func userDidSearch(searchString:String) + /// Tell to delegate user has closed without select func userDidSearch(searchString:String, tableView: UITableView) @@ -316,36 +314,33 @@ public protocol SwiftMultiSelectDelegate{ // MARK: - UIImageView extension UIImageView{ - - + + /// Set an image in UIImageView from remote URL /// /// - Parameter url: url of the image func setImageFromURL(stringImageUrl url: String){ - + //Placeholder image image = Config.placeholder_image - + //Download async image DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async { if let url = URL(string: url) { do{ - + let data = try Data.init(contentsOf: url) - + //Set image in the main thread DispatchQueue.main.async { self.image = UIImage(data: data) } - + }catch{ - + } } } - + } } - - - From 285ede2946fee4bdd137df7f62a7e5f451ed7d0f Mon Sep 17 00:00:00 2001 From: David FABREGUETTE Date: Mon, 4 Jun 2018 11:22:06 +0200 Subject: [PATCH 4/4] fixed : navbar is overlapping main stack view --- .../MultiSelectionViewController.swift | 109 ++++++++++-------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/SwiftMultiSelect/MultiSelectionViewController.swift b/SwiftMultiSelect/MultiSelectionViewController.swift index 14c7da0..4d99d63 100644 --- a/SwiftMultiSelect/MultiSelectionViewController.swift +++ b/SwiftMultiSelect/MultiSelectionViewController.swift @@ -10,21 +10,21 @@ import Foundation /// Class that represent the selection view class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegate,UISearchBarDelegate { - + /// Screen total with public var totalWidth:CGFloat{ get{ return UIScreen.main.bounds.width } } - + /// Screen total height public var totalHeight:CGFloat{ get{ return UIScreen.main.bounds.height } } - + /// Array of selected items open var selectedItems : [SwiftMultiSelectItem] = [SwiftMultiSelectItem](){ didSet{ @@ -33,57 +33,57 @@ class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegat self.navigationItem.rightBarButtonItem?.isEnabled = (self.selectedItems.count > 0) } } - + /// Lazy view that represent a selection scrollview open fileprivate(set) lazy var selectionScrollView: UICollectionView = { - + //Build layout let layout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) layout.scrollDirection = UICollectionViewScrollDirection.horizontal layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 - + //Build collectin view let selected = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) selected.backgroundColor = Config.selectorStyle.backgroundColor selected.isHidden = (SwiftMultiSelect.initialSelected.count <= 0) return selected - + }() - + /// Lazy view that represent a selection scrollview open fileprivate(set) lazy var separator: UIView = { - + //Build layout let sep = UIView() sep.autoresizingMask = [.flexibleWidth] sep.backgroundColor = Config.selectorStyle.separatorColor return sep - + }() - + /// Lazy var for table view open fileprivate(set) lazy var tableView: UITableView = { - + let tableView:UITableView = UITableView() tableView.backgroundColor = Config.tableStyle.backgroundColor return tableView - + }() - + /// Lazy var for table view open fileprivate(set) lazy var searchBar: UISearchBar = { - + let searchBar:UISearchBar = UISearchBar() searchBar.translatesAutoresizingMaskIntoConstraints = false return searchBar - + }() - + /// Lazy var for global stackview container open fileprivate(set) lazy var stackView: UIStackView = { - + let stackView = UIStackView(arrangedSubviews: [self.searchBar,self.selectionScrollView,self.tableView]) stackView.axis = .vertical stackView.distribution = .fill @@ -91,9 +91,9 @@ class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegat stackView.spacing = 0 stackView.translatesAutoresizingMaskIntoConstraints = false return stackView - + }() - + /// Calculate the nav bar height if present var navBarHeight:CGFloat{ get{ @@ -104,48 +104,48 @@ class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegat } } } - + //Nav bar buttons var leftButtonBar : UIBarButtonItem? var rightButtonBar : UIBarButtonItem = UIBarButtonItem() - + //Searched string var searchString = "" - + /// Function to build a views and set constraint func createViewsAndSetConstraints(){ //Add stack view to current view view.addSubview(stackView) - + selectionScrollView.addSubview(separator) separator.frame = CGRect(x: 0.0, y: Config.selectorStyle.selectionHeight-Config.selectorStyle.separatorHeight, width: Double(self.view.frame.size.width), height: Config.selectorStyle.separatorHeight) separator.layer.zPosition = CGFloat(separator.subviews.count+1) - + //Register tableview delegate tableView.delegate = self tableView.dataSource = self //Register cell class tableView.register(CustomTableCell.classForCoder(), forCellReuseIdentifier: "cell") - + //Register collectionvie delegate selectionScrollView.delegate = self selectionScrollView.dataSource = self //Register cell class selectionScrollView.register(CustomCollectionCell.classForCoder(), forCellWithReuseIdentifier: "cell") - + //register search delegate searchBar.delegate = self - + //Prevent adding top margin to collectionviewcell self.automaticallyAdjustsScrollViewInsets = false - + //autolayout the stack view and elements let viewsDictionary = [ "stackView" : stackView, "selected" : self.selectionScrollView ] as [String : Any] - + //constraint for stackview let stackView_H = NSLayoutConstraint.constraints( withVisualFormat: "H:|-0-[stackView]-0-|", @@ -160,7 +160,7 @@ class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegat metrics: nil, views: viewsDictionary ) - + searchBar.topAnchor.constraint(equalTo: stackView.topAnchor, constant: 0).isActive = true searchBar.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true searchBar.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true @@ -172,63 +172,70 @@ class MultiSelecetionViewController: UIViewController,UIGestureRecognizerDelegat //Add all constraints to view view.addConstraints(stackView_H) view.addConstraints(stackView_V) + + //Add a specific constraint to maitain top search bar fixed to parent view top anchor + stackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true } - - + + /// Toggle de selection view /// /// - Parameter show: true show scroller, false hide the scroller func toggleSelectionScrollView(show:Bool) { - + UIView.animate(withDuration: 0.2, animations: { self.selectionScrollView.isHidden = !show }) } - - + + /// Selector for right button @objc public func selectionDidEnd(){ - + SwiftMultiSelect.delegate?.swiftMultiSelect(didSelectItems: self.selectedItems) self.dismiss(animated: true, completion: nil) - + } - + /// Selector for left button @objc public func dismissSelector(){ - + self.dismiss(animated: true, completion: nil) SwiftMultiSelect.delegate?.didCloseSwiftMultiSelect() - + } - + //MARK: Life Cycle override func viewDidLoad() { - + super.viewDidLoad() - + + // Prevent from navbar to overlap main stack view + self.edgesForExtendedLayout = [] + self.automaticallyAdjustsScrollViewInsets = false + self.title = Config.viewTitle - + rightButtonBar.isEnabled = false leftButtonBar = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(MultiSelecetionViewController.dismissSelector)) leftButtonBar!.isEnabled = true self.navigationItem.leftBarButtonItem = leftButtonBar self.navigationItem.rightBarButtonItem = rightButtonBar - + rightButtonBar.action = #selector(MultiSelecetionViewController.selectionDidEnd) rightButtonBar.target = self - + self.view.backgroundColor = Config.mainBackground - + createViewsAndSetConstraints() - + self.tableView.reloadData() - + if(SwiftMultiSelect.initialSelected.count>0){ self.selectionScrollView.reloadData() rightButtonBar.isEnabled = true rightButtonBar.title = "\(Config.doneString) (\(SwiftMultiSelect.initialSelected.count))" } - + } }