Problem adding Values in Array in coolectionView - Swift - swift

I pull data from the database. I am separating the data I have taken according to the number of CATEGORIDAVTOPLAM.count. For example, there is 4 data in the first section and 3 data in the second section. However, while the data in 2.section should be 5.6.7 items in the new DavFile array, 1.2.7 in Array. attracts the next data. How can I add data by counting in the section in a single directory? When I do as follows, I have 7 data in total as follows. The ranking in the first section is 1.2.3.4 in Array, and the ranking in the second section is 1.2.7. values.
func getIndexForArray(with indexPath:IndexPath)->Int{
var itemIndex = 0
if indexPath.row != 0{
for _ in 0..<indexPath.section{
itemIndex += (sonsuzCollec.numberOfItems(inSection: indexPath.section) - 1)
}
return (itemIndex + indexPath.row)
}else{
return indexPath.row
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int(KATEGORIDAVTOPLAM[section]) ?? 0 }
func numberOfSections(in collectionView: UICollectionView) -> Int {
return yeniDavKATIsımNew.count }
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellSonsuz", for: indexPath) as! sonsuzCell
let currentIndex = getIndexForArray(with: indexPath)
if currentIndex < yeniDavFile.count{
let urlNew = URL(string: yeniDavFile[currentIndex])
cell.davetiyeFoto.sd_setImage(with: urlNew)
return cell
}else{
return UICollectionViewCell()
}
#objc func kategoriSaydırNew(){
...
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.yeniDavFile.append(s)
} }
DispatchQueue.main.async { self.sonsuzCollec.reloadData() }}
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["TOPLAM"] as? Int {
let s = String(describing: soru_baslik)
self.KATEGORIDAVTOPLAM.append(s)
} }
DispatchQueue.main.async {
self.sonsuzCollec.reloadData()
}

Related

swift different number of cell in each section

I'm trying to pull data from firebase and show it in a collectionView with sections. How can add a different number of cells per section as each firebase data node will not have the same number of posts.
var users = [User]()
var posts = [Post]()
Updated collection view methods:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FollowingCell
let user = self.users[indexPath.section]
let post = self.dataSource[user]?[indexPath.row]
cell.post = post
return cell
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! FollowingHeader
let user = self.users[indexPath.section]
header.user = user
return header
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let user = self.users[section]
return self.dataSource[user]?.count ?? 0
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return self.dataSource.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 120, height: 80)
}
How I'm adding the posts and user. As you can see I'm adding the post to the dataSource but for some reason, only 1 post per use is added when one of the users has two posts.
func fetchFollowedEvents() {
self.collectionView.refreshControl?.endRefreshing()
guard let currentUid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference().child("followed-posts").child(currentUid)
ref.observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? [String: Any] else { return }
dictionary.forEach { (key, value) in
Database.database().reference().child("posts").child(key).observeSingleEvent(of: .value) { (postSnapshot) in
guard let postDictionary = postSnapshot.value as? [String: Any] else { return }
guard let uid = postDictionary["uid"] as? String else { return }
Database.fetchUserWithUID(uid: uid) { (user) in
let post = Post(postId: key, user: user, dictionary: postDictionary)
post.id = key
self.users.append(user)
self.dataSource[user] = [post]
self.collectionView.reloadData()
}
}
}
}
}
try creating data source like this
var users : [User] = []()
var dataSource : [User:[Post]] = [:]() //I Prefer this one
(or)
var dataSource :[Int: [Post]] = [:]()
a dictionary with Users as Key and Array of post as Value
So now for number of sections you can use
self.userser.count()
(or)
self.dataSource.count()
So for number of rows in sections, you can do as so
let user = self.users[section]
return self.dataSource[user].count() ?? 0
(or)
return self.dataSource[section].count() ?? 0
in cell for row at index you can get the data as
let user = self.users[indexPath.section]
let data = self.dataSource[user][indexPath.row]
(or)
let data = self.dataSource[indexPath.section][indexPath.row]
Hope this would help you.
Happy Codding!

Adding data as many as indexPath - Swift

I draw data from the database, assign the data I have taken to LINKSTRING. The data I have assigned is the link and I am viewing the photos using this link. For example, there are 5 data I have assigned to LINKSTRING how can I assign these 5 data to photos variable. I want to add up to x photos in LINKSTRING.
Example:
self.photos = [CustomPhotoModel (imageURL: URL (string: "\ (self.LINKSTRING [0])"), thumbnailImageURL: URL (string: "\ (self.LINKSTRING [0]))"))] self.photos = [CustomPhotoModel (imageURL: URL (string: "\ (self.LINKSTRING [1])"), thumbnailImageURL: URL (string: "\ (self.LINKSTRING [1]))"))]
How do I assign variables in the form?
import UIKit
import INSPhotoGallery
class CustomModelViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
lazy var photos = [CustomPhotoModel]()
var LINKSTRING : [String] = []
override func viewDidLoad() {
super.viewDidLoad()
fillWithYORUM()
collectionView.delegate = self
collectionView.dataSource = self
}
func fillWithYORUM() {
let client = SQLClient.sharedInstance()!
client.connect("...", username: "...", password: "...", database: "...") { success in
client.execute("SELECT ... FROM ...", completion: { (_ results: ([Any]?)) in
var gifsa: [String] = []
for table in results as! [[[String:AnyObject]]] {
for row in table {
for (_, value) in row {
if let intVal = value as? String {
gifsa.append(String(intVal)) }} }}
DispatchQueue.main.async {
self.photos = [CustomPhotoModel(imageURL: URL(string: "\(LINKSTRING)"), thumbnailImageURL: URL(string: "\(LINKSTRING)"))]
self.collectionView.reloadData()
}
client.disconnect()
}) } }
}
extension CustomModelViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ExampleCollectionViewCell", for: indexPath) as! ExampleCollectionViewCell
cell.populateWithPhoto(photos[(indexPath as NSIndexPath).row])
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return photos.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! ExampleCollectionViewCell
let currentPhoto = photos[(indexPath as NSIndexPath).row]
let galleryPreview = INSPhotosViewController(photos: photos, initialPhoto: currentPhoto, referenceView: cell)
galleryPreview.referenceViewForPhotoWhenDismissingHandler = { [weak self] photo in
if let index = self?.photos.firstIndex(where: {$0 === photo}) {
let indexPath = IndexPath(item: index, section: 0)
let cell = collectionView.cellForItem(at: indexPath) as? ExampleCollectionViewCell
return cell
}
return nil
}
present(galleryPreview, animated: true, completion: nil)
}
}
you just need to append the data to your photos array like this:
if LINKSTRING.count > 0 {
for photoUrl in LINKSTRING {
let data = CustomPhotoModel (imageURL: URL (string: photoUrl), thumbnailImageURL: URL (string: photoUrl)]
self.photos.append(data)
}
}

CollectionViewCell is no displayed receiving data from Firebase

I have to fill the cells with data from the firebase. But they are not displayed. Help and explain where I made a mistake.
How to fill cell data ?
class TrainingProgramViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
//var trainingPrograms = TrainingProgram.fetchTrainingProgram()
var trainingPrograms = [TrainingProgram]()
let cellScale: CGFloat = 0.7
override func viewDidLoad() {
super.viewDidLoad()
fetchPrograms()
}
func fetchPrograms() {
Database.database().reference().child("programs").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
print(dict)
let newTitle = dict["title"] as! String
print("Новый тайтл:" + newTitle)
let newDescription = dict["description"] as! String
let trainingCell = TrainingProgram(description: newDescription, title: newTitle)
self.trainingPrograms.append(trainingCell)
print(self.trainingPrograms)
}
}
}
}
extension TrainingProgramViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return trainingPrograms.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
let trainingProgram = trainingPrograms[indexPath.item]
cell.trainingPrograms = trainingProgram
return cell
}
This is a model:
class TrainingProgram
{
var description = ""
var title = ""
init(description: String, title: String) {
self.description = description
self.title = title
}
}
This is my structure of Database :
You forget to reload your collectionView
func fetchPrograms() {
Database.database().reference().child("programs").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
print(dict)
let newTitle = dict["title"] as! String
print("Новый тайтл:" + newTitle)
let newDescription = dict["description"] as! String
let trainingCell = TrainingProgram(description: newDescription, title: newTitle)
self.trainingPrograms.append(trainingCell)
print(self.trainingPrograms)
}
DispatchQueue.main.async {
self. collectionView.reloadData()
}
}
}
Also set
collectionView.delegate = self
collectionView.dataSource = self
In your collectionView Method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
cell.titleLabel.text = trainingPrograms[indexPath.item].title
return cell
}
After you fetch the data and append it to your array which is shown in your tableView/collectionView you always have to reloadData() like collectionView.reloadData() or tableView.reloadData()

dynamically load sections of UIController depending on data

I am trying to implement a UICollectionView for a "Add Friends" page in my application and I need the following functionality:
When the view first appears, display and friend requests that a user may have.
User inputs username into search bar, and then (if found) that username shows up in a cell ABOVE the cells for friend requests.
I have been trying to implement this by using sections in a UICollevtionViewController but it has been a headache...
import UIKit
import Firebase
class AddUserController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchBarDelegate {
var searchedUser: User?
var friendRequests = [User]()
let cellId = "cellId"
let headerId = "headerId"
var sectionCategories = ["Add Friends", "Friend Requests"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.delegate = self
collectionView?.dataSource = self
collectionView?.register(SearchedUserCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(SectionHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
getFriendRequests()
}
fileprivate func fetchSearchedUsers(username: String) {
let ref = Database.database().reference().child("usernames")
ref.child(username).observeSingleEvent(of: .value, with: { (snapshot) in
// populate user info
guard let uidOfSearchedUser = snapshot.value as? String else {return}
Database.database().reference().child("users").child(uidOfSearchedUser).observeSingleEvent(of: .value, with: { (snapshot) in
guard let userDictionary = snapshot.value as? [String: Any] else {return}
self.searchedUser = User(uid: uidOfSearchedUser, dictionary: userDictionary)
self.collectionView?.reloadData()
}, withCancel: { (err) in
print("error retrieving user", err)
})
}) { (err) in
print("unable to find user: ", err)
}
}
func getFriendRequests() {
guard let uid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(uid).child("requests").observe(.value) { (snapshot) in
guard let requestsDictionary = snapshot.value as? [String: Any] else {return}
for (key, value) in requestsDictionary {
print(key, value)
Database.database().reference().child("users").child(key).observeSingleEvent(of: .value, with: { (snapshot) in
guard let userDictionary = snapshot.value as? [String: Any] else {return}
let user = User(uid: key, dictionary: userDictionary)
print("friend request from: ", user.username)
self.friendRequests.append(user)
})
}
}
self.collectionView?.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 4
} else if section == 1 {
return 1
}
return 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let sendFriendRequestcell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
let dealWithFriendRequestCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
if indexPath.section == 0 {
//Cell for searched user
sendFriendRequestcell.user = searchedUser
return sendFriendRequestcell
} else if indexPath.section == 1 {
//Populate all the friend requests that exist
if friendRequests.count != 0 {
dealWithFriendRequestCell.user = friendRequests[indexPath.item]
}
return dealWithFriendRequestCell
}
return sendFriendRequestcell
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
//Change this to return only 2 only if friend requests exist.
return 2
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! SectionHeaderView
headerView.sectionName = sectionCategories[indexPath.section]
return headerView
default:
assert(false, "Unexpected element kind")
}
}
}
Im using firebase to store/fetch both my searched users and any friend requests. I can see users in the friend requests.
The issues I'm having are:
Dynamically showing sections (the "Add Friends" section and cells shouldn't be displayed unless user searches for a user.
This particular user (screenshot) has a friend request, but the cell isn't populated to show that. I can see that I am retrieving user correctly.
Is a collection view like this even the best way for me to handle this? Seems a bit complicated.
I say your problem is state. Here is an example how state can be modeled with an enum with associated values. Read more on enums here.
struct User {}
struct UserRequest {}
class Controller: NSObject {
var collectionView: NSCollectionView!
enum Sections: Int {
case searched = 0
case requests = 1
}
enum State {
case none
case requests(requests: [UserRequest])
case searched(user: User)
case searchedAndRequests(user: User, requests: [UserRequest])
}
var state: State = .none {
didSet {
collectionView.reloadData()
}
}
}
extension Controller: NSCollectionViewDataSource {
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
switch state {
case .requests(let requests):
return requests.count
case .searched(_):
return 1
case .searchedAndRequests(_, let requests):
switch Section(rawValue: section)! {
case .searched:
return 1
case .requests:
return requests.count
default:
fatalError("section not allowed.")
}
default:
fatalError("invalid state.")
}
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
// Create cell(s) here or later.
switch state {
case .searched(let user):
// Populate user cell and return it.
break
case .requests(let requests):
let request = requests[indexPath.item]
// Populate cell with request and return it.
case .searchedAndRequests(let user, let requests):
switch Section(rawValue: indexPath.section)! {
case .searched:
// Populate user cell and return it.
break
case .requests:
let request = requests[indexPath.item]
// Populate cell with request and return it.
default:
fatalError("section not allowed.")
}
default:
fatalError("invalid state")
}
}
func numberOfSections(in collectionView: NSCollectionView) -> Int {
switch state {
case .none:
return 0
case .requests(_), .searched(_):
return 1
case .searchedAndRequests(_, _):
return 2
}
}
}

How to pass image from url to another view contoller using sd webimage framework swift

I have a collection view cell in first view controller which has imageview fetched from url using sd webimage third party library.This image is a thumbnail image.I want to pass the actual image to another view controller in didselectitemat of first view controller.The code is as follows:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return subcategoryArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("inside cell for item at ")
let cell:SubCategoryCollectionViewCell = self.collectionview3.dequeueReusableCell(withReuseIdentifier: "Cell2", for: indexPath) as! SubCategoryCollectionViewCell
if defaultAnimalArray.count - 1 >= indexPath.row
{
let item = self.defaultAnimalArray[indexPath.row]
cell.subThumbImg?.image = UIImage(named: item as! String)
}
else
{
//If now defaultAnimalArray.count = 8, indexPath = 8 , But array = 0...4, then,
let item1 = self.subcategoryArray[indexPath.row - self.defaultAnimalArray.count]
self.subcatthumbimagelink = (item1 as AnyObject).object(forKey: "SubcategoryThumb") as! String
cell.subThumbImg.sd_setImage(with: URL(string: self.subcatthumbimagelink), placeholderImage: UIImage(named: "placeholder.png"),options: SDWebImageOptions(), completed: {(image, error, cacheType, imageURL) -> Void in
print("image loaded")
})
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("image selected for coloring")
if defaultAnimalArray.count - 1 >= indexPath.row
{
print("indexpath selected is \(indexPath.row)")
let item = self.animalcategoryImages[indexPath.row]
var drawVC = self.storyboard?.instantiateViewController(withIdentifier: "DrawingViewController") as! DrawingViewController
drawVC.selectedimage = UIImage(named:item)
self.navigationController?.pushViewController(drawVC, animated: true)
}
else
{
print("indexpath selected in else loop is \(indexPath.row)")
let item1 = self.subcategoryArray[indexPath.row - 10]
print("subcategory count after manipulation is \(self.subcategoryArray)")
print("count of item1 \((item1 as AnyObject).count)")
print("item1 is \(item1)")
self.subcategoryimagelink = (item1 as AnyObject).object(forKey: "SubcategoryImage") as! String
print("category image link is \(self.subcategoryimagelink)")
self.ImageviewMain.sd_setImage(with: URL(string: self.subcategoryimagelink))
var drawVC = self.storyboard?.instantiateViewController(withIdentifier: "DrawingViewController") as! DrawingViewController
drawVC.selectedimage = self.ImageviewMain.image
self.navigationController?.pushViewController(drawVC, animated: true)
}
The subcategory count is addition of array from url and a array which is default.Kindly help me how to pass the image from url which is in cell to another view controller.
You need to pass only image url string instead of UIImage object
var drawVC = self.storyboard?.instantiateViewController(withIdentifier: "DrawingViewController") as! DrawingViewController
drawVC.imageURL = self.subcatthumbimagelink // you can also pass string from array
self.navigationController?.pushViewController(drawVC, animated: true)
In DrawingViewController
var imageURL : String?
self.imageView.sd_setImage(with: URL(string:imageURL), placeholderImage: UIImage(named: "placeholder.png"),options: SDWebImageOptions(), completed: {(image, error, cacheType, imageURL) -> Void in
print("image loaded")
})