Remove Top Bar of Collection View - uicollectionview

I have a small emoji collection view that is displayed when users tap an emoji button. I would like to get rid of the top bar space so that the background, for example, is all blue. I tried making top bar on storyboard None.. How can I remove this space?
import UIKit
class EmojiViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
let emojiImages = [...the pics...]
var selectedIndex: Int?
var estimateWidth = 100.0
var cellMarginSize = 10.0
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.emojiImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "emojiCell", for: indexPath) as! EmojiViewCell
let emoji = emojiImages[indexPath.row]
cell.emojiImage.image = UIImage(named: emojiImages[indexPath.row])
if selectedIndex == indexPath.row {
cell.backgroundColor = UIColor.red
self.dismiss(animated: true, completion: nil)
UserDefaults.standard.set(emoji, forKey: "emojiPicked")
}else{
cell.backgroundColor = UIColor.clear
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedIndex = selectedIndex == indexPath.row ? nil : indexPath.row
collectionView.reloadData()
}
}
extension EmojiViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 40, height: 40)
}
}

Related

index not being transferred from uicollectionviewcell to view controller

My code below is not working and is causing a runtime error. Stating Unexpectedly found nil while unwrapping an Optional value. I don't know what is causing this. I don't know how to fix the optional issue in this. The code for cellforitemat has also been added.
class antion : UICollectionViewCell {
#IBOutlet var sam : UILabel!
var deleagete : DataCollectionProtocoe?
var index : IndexPath?
#IBAction func press(){
deleagete?.passData(indx: (index?.row)!)
}
#IBAction func delete(){
deleagete?.deleteData(indx: (index?.row)!)
}
}
extension ViewController : DataCollectionProtocoe {
func passData(indx: Int) {
let vc = storyboard?.instantiateViewController(withIdentifier: "DetailVDC") as? DetailVDC
vc?.name = people[indx].name!
self.navigationController?.pushViewController(vc!, animated: true)
}
func deleteData(indx: Int) {
people.remove(at: indx)
cc.reloadData()
}
}
protocol DataCollectionProtocoe {
func passData(indx:Int)
func deleteData(indx:Int)
}
class DetailVDC: UIViewController {
var name = ""
#IBOutlet var lbl : UILabel!
override func viewDidLoad() {
lbl.text = name
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! antion
cell.index = indexPath
cell.deleagete = self
return cell
}
Based on what little i could understand from your code, it looks like you are creating the UICollectionViewCell instance but not setting any value to the delegate property of the cell.
When you create an instance of the collection view cell in the controller , assign the controller to the delegate property of the cell as follows:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = antion()
cell.delegate = self // assuming the controller is the data source of the collection view
}

How to detect that a different collection view cell has been selected?

I am developing a music app whereby selecting a collection view cell plays a track - I wish for the cell, when selected/tapped, to play when first selected and to pause if selected/tapped again. I can effectively play and pause when the same cell is selected however the problem arises when I select a different cell. How do I seperate the logic so that I can find out that a new cell has been selected? (and can therefore play and pause another track). I've tried didSelectItemAt delegate method but that gets called every time the cell is selected and I cannot figure out how to detect whether a different cell has been selected or not.
The behaviour I am looking for in other words: cell 1 is tapped - track 1 plays, cell 1 is tapped again - track 1 pauses OR cell 1 is tapped - track 1 plays, cell 2 is tapped - track 2 plays.
Any help would be greatly appreciated.
P.S. I'm using Swift
Visual representation of the App (a collection view where each cell is a seperate track)
EDIT
var currentTrack: Int!
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
currentTrack = indexPath.item
switch selected {
case true:
playAudio()
case false:
//Trying to match the current indexPath against the selected cell so I can play and pause that one
if currentTrack != indexPath.item {
playAudio()
} else {
pause()
}
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
pointerArray[keys[indexPath.item]] = false
print("Stop", keys[indexPath.item])
}
You can user the indexPath to check which item is being selected. Im gonna use print as an example but you can add the code for playing the same way.
var songArray = ["SongOne", "SongTwo", "SongThree"]
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(songArray[indexPath.item])
}
EDIT
In that case I would set a dictionary for each song and a pointer array to check whether the current track is playing or not. Also. if you want to stop the current track as the new one starts playing you can use the didDeselectItemAt function. Here is the code using both functions and print just as an example:
var songKeys = ["SongOne", "SongTwo", "SongThree"]
var songArray = ["SongOne" : false, "SongTwo" : false, "SongThree" : false]
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if songArray[songKeys[indexPath.item]] == false {
songArray[songKeys[indexPath.item]] = true
print("Playing", songKeys[indexPath.item])
return
}
songArray[songKeys[indexPath.item]] = false
print("Stop", songKeys[indexPath.item])
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
songArray[songKeys[indexPath.item]] = false
print("Stop", songKeys[indexPath.item])
}

Index out of Range - 9223372036854775807 - Swift 3

I have an array of strings with locations that are displayed in a table, and when the user selects the table cell, that location gets added to another array. I want to display the selected locations in a label through that second array. But, when I select too many locations or one that is farther down the list, I get this error:
fatal error: Index out of range
The index number for all of the locations when I select each of them is 9223372036854775807. How do I get my code to recognize an index number for each location?
#IBOutlet weak var tableLocations: UITableView!
let itemsLocations: [String] = ["Pacific Northwest", "West Coast", "The West", "Midwest", "Great Lakes", "The South", "New England"]
var locationsPreviewtext = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemsLocations.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellLoco: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellLocations")!
cellLoco.textLabel?.text = itemsLocations[indexPath.row]
return cellLoco
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
locationsPreviewtext.append(itemsLocations[indexPath.row]) //I get the error here when I select
labelLocationsPreview.text = "\(locationsPreviewtext)"
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if locationsPreviewtext.isEmpty {
return
}
else {
let ind = index(ofAccessibilityElement: locationsPreviewtext[indexPath.row]) //I get the error here when I deselect
if ind == NSNotFound {
locationsPreviewtext.remove(at: ind)
}
labelLocationsPreview.text = "\(locationsPreviewtext)"
}
}
#IBOutlet weak var labelLocationsPreview: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destDetails: ViewController = segue.destination as! ViewController
destDetails.labelGifteeLocationsPreview.text = "\(locationsPreviewtext)"
}

How to populate array and view it's data at the same time - Swift - IOS9

I am trying to retrieve data from an online database, and I do that successfully; However, after retrieving the data from the database I would like to store it in an array and then populate a listview and a mapview with it's data, but there is a problem, I am able to load the data and store it and view it, however the problem is that everytime the app loads no information appears until I go to another scene and go back, because I am populating the array though the AppDelegate. However, if I populate it through the viewdidload I get duplicate items in my table view.
Here is my code:
Approach number 1, which leads to duplicates
StoreViewController.swift
class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, StoresModelProtocoal {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
drawForm()
setUpMap()
self.hideKeyboardWhenTappedAround()
getCurrentLocation()
let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
Map.addGestureRecognizer(hideStoreDetail)
//Create a nib for the custom cell and use it in the table
let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")
let storesModel = StoresModel()
storesModel.delegate = self
storesModel.downloadItems()
}
func itemsDownloaded(items: NSArray) {
print("Items downloaded")
for item in items
{
if let s = item as? Store
{
print(s.Address)
Globals.unsortedStoresList += [s]
Map.addAnnotation(s.Annotation)
do_table_refresh()
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Globals.unsortedStoresList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell
let s = Globals.unsortedStoresList[indexPath.row]
cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let s = Globals.unsortedStoresList[indexPath.row]
print(s.Name)
print(s.Address)
print(s.HoursOfOperation)
print(s.DistanceFromCurrentLocation)
//print("You selected cell #\(indexPath.row)!")
}
func do_table_refresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.StoresListTable.reloadData()
return
})
}
I know this one duplicates the items because everytime the view is loaded it re-downloads all the data again; therefore, I tried looking for a better way and then I thought about doing the downloading process in my AppDelegate and then just write couple functions that take data from the array and display it, but the problem here is that the data would be displayed on the TableView right away without duplicates but it won't be displayed on the mapview at first run, instead I have to go to another scene and go back in order for the data to be displayed on the map.
Approach number 2
StoreViewController.swift
class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
drawForm()
setUpMap()
self.hideKeyboardWhenTappedAround()
getCurrentLocation()
let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
Map.addGestureRecognizer(hideStoreDetail)
//Create a nib for the custom cell and use it in the table
let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")
loadMapAnnotations()
}
func loadMapAnnotations(){
for item in Globals.unsortedStoresList
{
Map.addAnnotation(item.Annotation)
do_table_refresh()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Globals.unsortedStoresList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell
let s = Globals.unsortedStoresList[indexPath.row]
cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let s = Globals.unsortedStoresList[indexPath.row]
print(s.Name)
print(s.Address)
print(s.HoursOfOperation)
print(s.DistanceFromCurrentLocation)
//print("You selected cell #\(indexPath.row)!")
}
func do_table_refresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.StoresListTable.reloadData()
return
})
}
AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate, StoresModelProtocoal {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let storesModel = StoresModel()
storesModel.delegate = self
storesModel.downloadItems()
return true
}
//////////////////////////////////////
//Delegates
//////////////////////////////////////
func itemsDownloaded(items: NSArray) {
print("Items downloaded")
for item in items
{
if let s = item as? Store
{
print(s.Address)
Globals.unsortedStoresList += [s]
//Map.addAnnotation(s.Annotation)
}
}
}
Any help would be appreciated, Thanks in advance.
I was able to find a temporarily solution to the problem
I modified StoreViewController.swift to this, if anyone is having a similar problem.
class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, StoresModelProtocoal {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
drawForm()
setUpMap()
self.hideKeyboardWhenTappedAround()
getCurrentLocation()
let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
Map.addGestureRecognizer(hideStoreDetail)
//Create a nib for the custom cell and use it in the table
let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")
Globals.unsortedStoresList.removeAll() //I added this line of code to remove the old list
let storesModel = StoresModel()
storesModel.delegate = self
storesModel.downloadItems()
}
func itemsDownloaded(items: NSArray) {
print("Items downloaded")
for item in items
{
if let s = item as? Store
{
print(s.Address)
Globals.unsortedStoresList += [s]
Map.addAnnotation(s.Annotation)
}
}
do_table_refresh()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Globals.unsortedStoresList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell
let s = Globals.unsortedStoresList[indexPath.row]
cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//tableView.deselectRowAtIndexPath(indexPath, animated: true)
let s = Globals.unsortedStoresList[indexPath.row]
print(s.Name)
print(s.Address)
print(s.HoursOfOperation)
print(s.DistanceFromCurrentLocation)
//print("You selected cell #\(indexPath.row)!")
}
func do_table_refresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.StoresListTable.reloadData()
return
})
}

SWIFT TableView not loading text

I am making a tableView programatically. For some reason the table view is always empty. Please help me find the bug. Here is my code
// Set all view we will need
func setupTableView() {
self.tableView = UITableView(frame: CGRectMake(0, 20, 320, self.heighTableView))
self.tableView!.tableHeaderView = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, CGFloat(self.heighTableViewHeader)))
self.tableView!.backgroundColor = UIColor.clearColor()
self.tapMapViewGesture = UITapGestureRecognizer(target: self, action: "handleTapMapView:")
self.tapTableViewGesture = UITapGestureRecognizer(target: self, action: "handleTapTableView:")
self.tapTableViewGesture!.delegate = self
self.tableView!.tableHeaderView?.addGestureRecognizer(self.tapMapViewGesture!)
self.tableView!.addGestureRecognizer(self.tapTableViewGesture!)
// Init selt as default tableview's delegate & datasource
//self.tableView!.dataSource = self
self.tableView!.delegate = self
self.view.addSubview(self.tableView!)
}
// UITableViewDataSource Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView:UITableView!, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat {
return 80
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var identifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifier) as UITableViewCell?
cell!.textLabel!.text = "Hello World !"
// }
return cell!
}
Try this :
class ViewController: UIViewController, UITableViewDelegate, MKMapViewDelegate, UIGestureRecognizerDelegate,UITableViewDataSource
then replace your function by copying this two functions by command + click on UITableViewDataSource:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
}
and other one is :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
}
and put all the code into this two function and try again becouse in your code this two functions are not getting called but by doing this your function will called and you have put all the required code into this function.
and also remove comment from
self.tableView!.dataSource = self
May be this can help you.
Edit For this Answer:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var identifier : NSString = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? UITableViewCell
if !(cell != nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: identifier)
}
cell?.textLabel?.text = "Hello World"
return cell!
}