indexPath.row not getting data from the array - ios

I've created a PFQuery to get some strings from my parse server and the put this in a couple of arrays
var packsAvailable = [""]
var packsImage = [""]
var packsDescription = [""]
If I print the value of the array in the for loop of the query I get all the values in a proper array. However when I try and use this information to populate my collection view nothing happens. I can't figure this out because it works with the manually created arrays tableImages and tableData that I have commented out for testing.
import UIKit
import Parse
private let reuseIdentifier = "Cell"
class CollectionViewController: UICollectionViewController {
//var tableData: [String] = ["Tis is a description", "Test 22", "Test 33"]
//var tableImages: [String] = ["walk1bg", "2", "walk3bg"]
var packsAvailable = [""] // the total packs in the app
var packsImage = [""]
var packsDescription = [""]
override func viewDidLoad() {
super.viewDidLoad()
let packQuery = PFQuery(className: "Pack")
packQuery.findObjectsInBackground(block: { (objectsArray, error) in
if error != nil {
print(error!)
} else if let packs = objectsArray {
self.packsAvailable.removeAll() // remove them incase they double up
print(packs.count)
for object in packs {
/*
print(object["packName"])
print(object["packImage"])
print(object["packDesctription"])
*/
self.packsAvailable.append(object["packName"] as! String)
self.packsImage.append(object["packImage"] as! String)
self.packsDescription.append(object["packDesctription"] as! String)
/*
print(self.packsAvailable)
print(self.packsImage)
print(self.packsDescription)
*/
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return packsAvailable.count
}
func UIColorFromHEX(hexValue: UInt) -> UIColor {
return UIColor(
red: CGFloat((hexValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((hexValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(hexValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell
//cell.labelCell.text = tableData[indexPath.row]
//cell.imageCell.image = UIImage(named: tableImages[indexPath.row])
cell.labelCell.text = packsDescription[indexPath.row]
print(packsDescription[indexPath.row])
cell.imageCell.image = UIImage(named: packsImage[indexPath.row])
cell.imageCell.layer.masksToBounds = true
cell.imageCell.layer.cornerRadius = cell.imageCell.frame.height/2
cell.imageCell.layer.borderWidth = 3
cell.imageCell.layer.borderColor = UIColorFromHEX(hexValue: 0x62aca2).cgColor
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Selected \(indexPath.row)")
}
}

add collectionView.reloadData() after the for-in loop is completed inside your closure. This will tell your collectionView to fetch the current array values.

You forgot to reload the collectionView when the response comes from the server. just add collectionView.reloadData() after completion of for loop
override func viewDidLoad() {
super.viewDidLoad()
let packQuery = PFQuery(className: "Pack")
packQuery.findObjectsInBackground(block: { (objectsArray, error) in
if error != nil {
print(error!)
} else if let packs = objectsArray {
self.packsAvailable.removeAll() // remove them incase they double up
print(packs.count)
for object in packs {
/*
print(object["packName"])
print(object["packImage"])
print(object["packDesctription"])
*/
self.packsAvailable.append(object["packName"] as! String)
self.packsImage.append(object["packImage"] as! String)
self.packsDescription.append(object["packDesctription"] as! String)
/*
print(self.packsAvailable)
print(self.packsImage)
print(self.packsDescription)
*/
}
//swift 2.3
dispatch_async(dispatch_get_main_queue()) {
self.collectionView.reloadData()
}
//swift 3
/* DispatchQueue.main.async {
self.collectionView.reloadData()
}*/
}
})
}

Related

didSelectItem not being called

My didSelectItemAt method is not being called and nothing is being printed into the console. I have user interaction turned on and I still can not get it to print out anything. I am not sure if my custom PinterestStyle Layout is causing this or if I am missing something. The ultimate goal would be to segue into a detail view controller showing the profile page of the cell selected. I will do that using prepareForSegue however I still can't even get it to print out the name of the cell when tapped.
class PagesCollectionViewController: UICollectionViewController, firebaseHelperDelegate {
var storageRef: StorageReference!{
return Storage.storage().reference()
}
var usersList = [String]()
var authService : FirebaseHelper!
var userArray : [Users] = []
var images: [UIImage] = []
var names: [String] = []
override func viewWillAppear(_ animated: Bool) {
if Global.Location != "" && Global.Location != nil
{
usersList = Global.usersListSent
print(usersList)
self.authService.ListOfUserByLocation(locationName: Global.Location, type: .ListByLocation)
}
}
override func viewDidLoad() {
self.collectionView?.allowsSelection = true
self.collectionView?.isUserInteractionEnabled = true
super.viewDidLoad()
self.authService = FirebaseHelper(viewController: self)
self.authService.delegate = self
setupCollectionViewInsets()
setupLayout()
}
private func setupCollectionViewInsets() {
collectionView!.backgroundColor = .white
collectionView!.contentInset = UIEdgeInsets(
top: 20,
left: 5,
bottom: 49,
right: 5
)
}
private func setupLayout() {
let layout: PinterestLayout = {
if let layout = collectionViewLayout as? PinterestLayout {
return layout
}
let layout = PinterestLayout()
collectionView?.collectionViewLayout = layout
return layout
}()
layout.delegate = self
layout.cellPadding = 5
layout.numberOfColumns = 2
}
func firebaseCallCompleted(data: AnyObject?, isSuccess: Bool, error: Error?, type: FirebaseCallType) {
if(type == .ListByLocation) {
if(isSuccess) {
self.userArray.removeAll()
self.images.removeAll()
self.images.removeAll()
if(data != nil) {
let dataDict = data as! NSDictionary
let keyArray = dataDict.allKeys
for i in 0 ..< keyArray.count {
var dict = NSDictionary()
dict = dataDict.object(forKey: keyArray[i]) as! NSDictionary
self.userArray.append(Users.init(data: dict))
}
}
self.collectionView?.reloadData()
}
else {
print(error?.localizedDescription)
SVProgressHUD.dismiss()
}
}
}
}
extension PagesCollectionViewController {
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userArray.count
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(userArray[indexPath.row].name)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "PagesCollectionViewCell",
for: indexPath) as! PagesCollectionViewCell
cell.nameLabel.text = userArray[indexPath.row].name
if let imageOld = URL(string: userArray[indexPath.row].photoURL){
cell.photo.sd_setImage(
with: imageOld,
placeholderImage: nil,
options: [.continueInBackground, .progressiveDownload]
)
}
return cell
}
}
extension PagesCollectionViewController : PinterestLayoutDelegate {
func collectionView(collectionView: UICollectionView,
heightForImageAtIndexPath indexPath: IndexPath,
withWidth: CGFloat) -> CGFloat {
var image: UIImage?
let url = URL(string: userArray[indexPath.row].photoURL)
let data = try? Data(contentsOf: url!)
image = UIImage(data: data!)
return (image?.height(forWidth: withWidth))!
}
func collectionView(collectionView: UICollectionView,
heightForAnnotationAtIndexPath indexPath: IndexPath,
withWidth: CGFloat) -> CGFloat {
return 30
}
}
Check 2 conditions:-
Make sure you have set delegate to UICollectionView
Make sure Content in PageCollectionCell like image having no user interaction enabled. If image user interaction is enabled then didSelectItemAt will not call.
as Manish Mahajan said a quick fix would be:
in cellForItemAt func set contentView as not clickable
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.contentView.isUserInteractionEnabled = false
return cell
}

Select Multiple Collection View Cells and Store in Array

I'm working on an onboarding flow for my iOS App in Swift. I'd like to allow users to tap other users in a collection view and have it follow those users. I need the collection view to be able to allow multiple cells to be selected, store the cells in an array and run a function once the users taps the next button. Here's my controller code:
class FollowUsers: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var tableData: [SwiftyJSON.JSON] = []
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var loadingView: UIView!
private var selectedUsers: [SwiftyJSON.JSON] = []
override func viewDidLoad() {
super.viewDidLoad()
self.getCommunities()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getUsers() {
Alamofire.request(.GET, "url", parameters: parameters)
.responseJSON {response in
if let json = response.result.value {
let jsonObj = SwiftyJSON.JSON(json)
if let data = jsonObj.arrayValue as [SwiftyJSON.JSON]? {
self.tableData = data
self.collectionView.reloadData()
self.loadingView.hidden = true
}
}
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.tableData.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: UserViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("userCell", forIndexPath: indexPath) as! UserViewCell
let rowData = tableData[indexPath.row]
if let userName = rowData["name"].string {
cell.userName.text = userName
}
if let userAvatar = rowData["background"].string {
let url = NSURL(string: userAvatar)
cell.userAvatar.clipsToBounds = true
cell.userAvatar.contentMode = .ScaleAspectFill
cell.userAvatar.hnk_setImageFromURL(url!)
}
cell.backgroundColor = UIColor.whiteColor()
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell: UserViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("userCell", forIndexPath: indexPath) as! UserViewCell
let rowData = tableData[indexPath.row]
let userName = rowData["name"].string
let userId = rowData["id"].int
selectedUsers.append(rowData[indexPath.row])
print("Cell \(userId) \(userName) selected")
}
}
override func viewDidLoad() {
super.viewDidLoad()
collection.dataSource = self
collection.delegate = self
collection.allowsMultipleSelection = true
self.getCommunities()
}
You should be able to make multiple selections with this.

Can't reverse table view

I tried to reverse my table view in the view did load method by reversing the arrays but it's not working. I'm trying to make it so that it sorts the feed from the time it was created from top to bottom. Am I doing it wrong? If so what should I do?
class Feed: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var table: UITableView!
#IBOutlet var feedBar: UINavigationBar!
var titles = [String]()
var messages = [String]()
var usernames = [String]()
var types = [String]()
override func viewDidLoad() {
super.viewDidLoad()
table.dataSource = self
messages.reverse()
titles.reverse()
usernames.reverse()
types.reverse()
}
func UIColorFromRGB(rgbValue: UInt) -> UIColor {
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
override func viewDidAppear(animated: Bool) {
println("View appeared")
self.messages.removeAll(keepCapacity: true)
self.titles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
self.types.removeAll(keepCapacity: true)
var postQuery = PFQuery(className: "Post")
postQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"] as! String)
self.titles.append(object["title"] as! String)
self.usernames.append(object["username"] as! String)
self.types.append(object["type"] as! String)
self.table.reloadData()
}
}
})
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let postCell = tableView.dequeueReusableCellWithIdentifier("feedPost", forIndexPath: indexPath) as! PostCell
var post = PFObject(className: "Post")
if messages.isEmpty == false {
postCell.message.text = messages[indexPath.row]
}
if titles.isEmpty == false {
postCell.postTtitle.text = titles[indexPath.row]
}
if usernames.isEmpty == false {
postCell.posterName.setTitle(usernames[indexPath.row], forState: .Normal)
}
if self.types[indexPath.row] == "post1" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFCFFBD)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFCFFBD)
} else if self.types[indexPath.row] == "post2" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFFB4AC)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFFB4AC)
} else if self.types[indexPath.row] == "post3" {
postCell.sideLeft.backgroundColor = self.UIColorFromRGB(0xFFD5A4)
postCell.sideRight.backgroundColor = self.UIColorFromRGB(0xFFD5A4)
}
postCell.selectionStyle = .None
postCell.message.scrollRangeToVisible(NSMakeRange(0, 0))
return postCell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usernames.count
}
}
Observe that in the view's life cycle the viewDidAppear gets called after your viewDidLoad method. It appears that you try to reload the contents from within your viewDidAppear method, and there you are clearing those arrays which you had reversed earlier in viewDidLoad. This is the reason why you are not seeing any effect. You might want to reverse your arrays there.
You are reversing array in viewDidLoad, but you append something in viewDidAppear. viewDidAppear call after viewDidLoad. You should reverse array in the end of viewDidAppear before call self.table.reloadData()
override func viewDidAppear(animated: Bool) {
println("View appeared")
self.messages.removeAll(keepCapacity: true)
self.titles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
self.types.removeAll(keepCapacity: true)
var postQuery = PFQuery(className: "Post")
postQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"] as! String)
self.titles.append(object["title"] as! String)
self.usernames.append(object["username"] as! String)
self.types.append(object["type"] as! String)
}
messages.reverse()
titles.reverse()
usernames.reverse()
types.reverse()
self.table.reloadData()
}
})
}
I figured it out what I did was I did this instead of append...
self.messages.insert(object["message"] as! String, atIndex: 0)
What this basically does is appends the newest message to the beginning of the array.

how to add element under collection reusable view in collection view

i have a problem and confusing i want to ask how can i make a new object ( i want to make date ) under the icons, and under the date there's icon again.. like gallery on iPhone,
in example:
august
(photos)
september
(photos)
and so on..thx
will be looks like this, but how
there is my code in this view
import UIKit
let reuseIdentifier = "Cell"
class SummaryViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var collectionview: UICollectionView!
var photos:NSArray?
var items = NSMutableArray()
var TableData:Array< String > = Array < String >()
var json:String = ""
var arrayOfMenu: [ImageList] = [ImageList]()
override func viewDidLoad() {
super.viewDidLoad()
self.setUpMenu()
collectionview.dataSource = self
collectionview.delegate = self
NSLog("%d", items.count)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayOfMenu.count //hitung banyak data pada array
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
let image = UIImage(named: items.objectAtIndex(indexPath.row) as! String)
let imageView = cell.viewWithTag(100) as! UIImageView
imageView.image = image
return cell
}
func setUpMenu() //membaca json pada setiap arraynya
{
var json: JSON = JSON (data: NSData())
DataManager.getactivityDataFromFileWithSuccess{ (data) -> Void in
json = JSON(data: data)
let results = json["results"]
for (index: String, subJson: JSON) in results {
}
for (var i = 0; i < json["Activity"].count; i++) {
if let icon: AnyObject = json["Activity"][i]["icon"].string {
self.items.addObject(icon)
dispatch_async(dispatch_get_main_queue(), {self.collectionView!.reloadData()})
var menu = ImageList(image: icon as! String)
self.arrayOfMenu.append(menu)
self.TableData.append(icon as! String)
}
}
}
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
{
let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "headersection", forIndexPath: indexPath) as! UICollectionReusableView
return header
}
}
You can set number of sections to required number of months.
Like this :
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 3
}
And for the menu, you need to give it according to section(month).
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
if section == 0
{
return arrayOfFirstMenu.count
}
else if section == 1
{
return arrayOfSecondMenu.count
}
else
{
return arrayOfThirdMenu.count
}
}
Hope this helps!

UICollectionView- How to add object on every cells?

how to make this become looks like iPhone gallery (if the data meets the end, i want to add the label which is shows the month) and make it repeatable
it become looks like this
i've tried every objects and insert to uicollectionview, but it doesn't appear at all..is there any way to help?
here is my code
import UIKit
let reuseIdentifier = "Cell"
class SummaryViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var collectionview: UICollectionView!
var photos:NSArray?
var items = NSMutableArray()
var TableData:Array< String > = Array < String >()
var json:String = ""
var arrayOfMenu: [ImageList] = [ImageList]()
override func viewDidLoad() {
super.viewDidLoad()
self.setUpMenu()
collectionview.dataSource = self
collectionview.delegate = self
NSLog("%d", items.count)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayOfMenu.count //hitung banyak data pada array
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
let image = UIImage(named: items.objectAtIndex(indexPath.row) as! String)
let imageView = cell.viewWithTag(100) as! UIImageView
imageView.image = image
return cell
}
func setUpMenu() //membaca json pada setiap arraynya
{
var json: JSON = JSON (data: NSData())
DataManager.getactivityDataFromFileWithSuccess{ (data) -> Void in
json = JSON(data: data)
let results = json["results"]
for (index: String, subJson: JSON) in results {
}
for (var i = 0; i < json["Activity"].count; i++) {
if let icon: AnyObject = json["Activity"][i]["icon"].string {
self.items.addObject(icon)
dispatch_async(dispatch_get_main_queue(), {self.collectionView!.reloadData()})
var menu = ImageList(image: icon as! String)
self.arrayOfMenu.append(menu)
self.TableData.append(icon as! String)
}
}
}
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
{
let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "headersection", forIndexPath: indexPath) as! UICollectionReusableView
return header
}
}

Resources