UICollectionView not loading Image from SDWebImage - ios

I created a UICollectionView Inside a ViewController but the UICollectionView is not loading the data I appended to the array. I tried to print from the UIcollectionView datasource and delegate but it also not printing
import UIKit
import Alamofire
import SwiftyJSON
import SDWebImage
class SelectCarViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var selectedcarManufacturalLebel: UILabel!
#IBOutlet weak var selectedcarPlateNumber: UILabel!
#IBOutlet weak var selectCarCarouselCollectionView: UICollectionView!
var selecrCarsURL = "https://my.api.mockaroo.com/cars.json?key=86f86980"
var selectCarArray : [SelectCarDataModel] = [SelectCarDataModel]()
let selectCarFromJSON = SelectCarDataModel()
override func viewDidLoad() {
super.viewDidLoad()
selectCarCarouselCollectionView.delegate = self
selectCarCarouselCollectionView.dataSource = self
//register custom sell nib file
selectCarCarouselCollectionView.register(UINib.init(nibName: "SelectCarViewCell", bundle: nil), forCellWithReuseIdentifier: "selectIdentifier")
//Add flowyout function
addFlowlayOut()
getselectCarData(url: selecrCarsURL)
selectCarCarouselCollectionView.reloadData()
}
//MARK:- Add carousel flowlayout for viewcontroller collectionview
func addFlowlayOut() {
let flowlayout = UPCarouselFlowLayout()
flowlayout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 60, height: selectCarCarouselCollectionView.frame.size.height)
flowlayout.scrollDirection = .horizontal
flowlayout.sideItemScale = 0.8
flowlayout.sideItemAlpha = 1.0
flowlayout.spacingMode = .fixed(spacing: 5.0)
selectCarCarouselCollectionView.collectionViewLayout = flowlayout
}
//MARK:- Select Car Newtworking
func getselectCarData(url: String) {
Alamofire.request(url, method: .get).responseJSON {
response in
if response.result.isSuccess {
print("Sucess Got the Selected Cars Data")
let selelectCarJSON : JSON = JSON(response.result.value!)
print(selelectCarJSON)
self.updateSelectedCar(json: selelectCarJSON)
}else {
print("error)")
}
}
}
//MARK:- Select Car Update JSON Parsing
func updateSelectedCar(json : JSON) {
//for i in 0...json.count-1 {
selectCarFromJSON.image = json["car"][0]["img"].stringValue
selectCarFromJSON.carType = json["car"][0] ["manufacturer"].stringValue
selectCarFromJSON.carModel = json["car"][0]["model"].stringValue
print("this is it \(selectCarFromJSON.image)")
//}
}
//MARK: -- UICollection Delegate and Datasourse Manipulation
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return selectCarArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = selectCarCarouselCollectionView.dequeueReusableCell(withReuseIdentifier: "selectIdentifier", for: indexPath) as! SelectCarViewCell
let selectCar = SelectCarDataModel()
selectCar.image = selectCarFromJSON.image
selectCar.carType = selectCarFromJSON.carType
selectCar.carModel = selectCarFromJSON.carModel
selectCarArray.append(selectCar)
print(selectCarArray)
cell.selectCarImage.sd_setImage(with: URL(string: selectCarArray[indexPath.row].image))
selectedcarManufacturalLebel.text = selectCarArray[indexPath.row].carType
selectedcarPlateNumber.text = selectCarArray[indexPath.row].carModel
print("this is cell\(selectCarArray[indexPath.row].image)")
selectCarCarouselCollectionView.reloadData()
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath.row)
}
}
I expected the SDWebImage to get the URL from the JSON and populate the UICollectionView

SDWebImage show URL image in imageView not a local image.
your selectCarArray store an image not url. so it's not working.
try this:-
cell.selectCarImage.sd_setImage(with: URL(string: "https://image.shutterstock.com/image-photo/beautiful-abstract-grunge-decorative-navy-260nw-539880832.jpg"))

Related

How to show data in my application? Swift and Firebase

I am facing a problem in my application. When I run my application in the emulator, I don't get any data and just a white screen.
I decided to use Firestore as a backend. Below I provide the code and hope you can help me.
ViewController
class ViewController: UIViewController {
#IBOutlet weak var cv: UICollectionView!
var channel = [Channel]()
override func viewDidLoad() {
super.viewDidLoad()
self.cv.delegate = self
self.cv.dataSource = self
let db = Firestore.firestore()
db.collection("content").getDocuments() {( quarySnapshot, err) in
if let err = err {
print("error")
} else {
for document in quarySnapshot!.documents {
if let name = document.data()["title"] as? Channel {
self.channel.append(name)
}
}
self.cv.reloadData()
}
}
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return channel.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ContentCell
let indexChannel = channel[indexPath.row]
cell.setup(channel: indexChannel)
return cell
}
}
This is my cell
class ContentCell: UICollectionViewCell {
#IBOutlet weak var channelText: UILabel!
#IBOutlet weak var subtitle: UITextView!
func setup(channel: Channel) {
channelText.text = channel.title
subtitle.text = channel.subtitle
}
}
If you need additional information - write
Your problem is here
if let name = document.data()["title"] as? Channel {
self.channel.append(name)
}
you can't cast a String to a Custom data type (Channel) , so according to your data you can try this
if let title = document.data()["title"] as? String , let subtitle = document.data()["subtitle"] as? String {
let res = Channel(title:title,subtitle:subtitle)
self.channel.append(res)
}

Pass data from CollectionView to TabBarController, than to his childs in Swift

I am new to Swift. Unable to find solution for below problem.
Below is a ViewController with CollectionView and When you click on Cell in CollectionView, data from cell(even this who isn't in label and image view, but are in Book array row) must be send to TabBarCollection, than from TabBarCollection I need to send this data to all of child's, like in this image.
Later in childs of TabBar I will set value of Labels in View Controllers from data from choosed Cell.
Book.swift
import UIKit
struct Book {
let title: String
let image: UIImage?
//Here soon will be more "let", and this data will also have to be send to TabBar but it don't will be show I CollectionViewCell
}
extension Book {
static let books: [Book] = [
Book(title: "Antygona", image: UIImage(named: "imgantygona")!),
//etc
]
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var bookImageView: UIImageView!
#IBOutlet weak var bookTitle: UILabel!
func setup(with book: Book) {
bookTitle.text = book.title
bookImageView.image = book.image
}
}
ViewController
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let books = Book.books
override func viewDidLoad() {
super.viewDidLoad()
let fontAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16.0)]
UITabBarItem.appearance().setTitleTextAttributes(fontAttributes, for: .normal)
collectionView.dataSource = self
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return books.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "bookCell", for: indexPath) as! CollectionViewCell
let book = books[indexPath.item]
cell.setup(with: book)
return cell
}
}
I saw many solutions but I can't perfectly adapt it to my problem. :(
Thanks for help !
BookInsideViewController.swift
import UIKit
class BookInsideViewController: UIViewController {
#IBOutlet weak var testImageView: UIImageView!
#IBOutlet weak var testLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
You can use collection view DidSelectItemAt function
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourtabbarIdentifier") as! UITabBarController
// You should access the `imageController` through your `tabBarController`,
// not instantiate it from storyboard.
if let viewControllers = tabBarController.viewControllers,
let imageController = viewControllers.first as? ImageController {
BookInsideViewController.recivedData1 = Books[indexPath.row]
}
navigationController?.pushViewController(tabBarController, animated: true)
}

Why I need to scroll up and down first before the collection view cell updated?

I am trying to make a category list using CollectionView, as we can see there is a brown circle that actually an UIView (Designable Background View).
I want to update that background colour from brown to random colour. but the random colour only show up after I scroll up and scroll down the CollectionView, like the .gif file in here : http://g.recordit.co/BxRf26Uw2t.gif
before scroll down the colour will be still in brown like this
after scroll up and down, the colour will be updated, but some of the item still in the brown colour like this :
here is the code of my ViewController
import UIKit
import ChameleonFramework
class FacilitiesVC: UIViewController {
#IBOutlet weak var collectionVIew: UICollectionView!
struct StoryBoard {
// Collection View
static let indoorFacilitiesCategoryCellIdentifier = "indoorFacilitiesCell"
static let numberOfColumnsPerRow : CGFloat = 3.0
static let inset: CGFloat = 10.0
static let spacing: CGFloat = 8.0
static let lineSpacing: CGFloat = 8.0
//segue Identifiers
}
var indoorFacilitiesCategoryData = [FacilitiesCategory]()
var outdoorFacilitiesCategoryData = [FacilitiesCategory]()
override func viewDidLoad() {
super.viewDidLoad()
getIndoorOutdoorFacilitiesData()
}
}
extension FacilitiesVC {
func getIndoorOutdoorFacilitiesData() {
let facilitiesData = FacilitiesCategoryLibrary.fetchFacilitiesCategory()
// distinguishing between indoor and outdoor data
for facData in facilitiesData {
if facData.type == "Indoor Facility" {
indoorFacilitiesCategoryData.append(facData)
} else {
outdoorFacilitiesCategoryData.append(facData)
}
}
}
}
extension FacilitiesVC : UICollectionViewDataSource {
// MARK: - UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return indoorFacilitiesCategoryData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryBoard.indoorFacilitiesCategoryCellIdentifier, for: indexPath) as! IndoorFacilitiesCell
cell.indoorFacilitiesCategoryData = indoorFacilitiesCategoryData[indexPath.item]
cell.designableBackgroundView.backgroundColor = RandomFlatColor()
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
return cell
}
}
and here is the code of CollectionViewCell
import UIKit
import ChameleonFramework
class IndoorFacilitiesCell: UICollectionViewCell {
#IBOutlet weak var designableBackgroundView: DesignableUIView!
#IBOutlet weak var iconImageView: UIImageView!
#IBOutlet weak var icontitleLabel: UILabel!
var indoorFacilitiesCategoryData : FacilitiesCategory? {
didSet {
updateUI()
}
}
}
extension IndoorFacilitiesCell {
func updateUI() {
guard let indoorData = indoorFacilitiesCategoryData else {return}
iconImageView.image = UIImage(named: indoorData.logo)
icontitleLabel.text = indoorData.categoryName
}
}
what went wrong in here? what should I do to fix that?

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.

UICollectionView with Custom Cell Breaking UICollectionViewDataSource Protocol

I am trying to use a UICollectionView with a custom cell. My ViewController inherits from UICollectionViewDataSource as below:
import UIKit
import Parse
class DressingRoomViewController: UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
That inheritance is causing me to break a protocol of UICollectionViewDataSource with my UICollectionView function that creates and returns the custom cell. This is the function:
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! CustomCell
let dressingRoomIcons: [DressingRoomIcon] =
dataSource.dressingRoomIcons
let dressingRoomIcon = dressingRoomIcons[indexPath.row]
var imageView: MMImageView =
createIconImageView(dressingRoomIcon.name!)
cell.setImageV(imageView)
return cell
}
So before compilation the error is shown in the IDE. How do I get around this error? Here are the two errors I am experiencing:
Type 'DressingRoomViewController' does not conform to protocol
'UICollectionViewDataSource'
Cannot assign a value of type 'DressingRoomViewController' to a value
of type 'UICollectionViewDataSource?'
Here is the whole ViewController:
import UIKit
import Parse
class DressingRoomViewController: UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
#IBOutlet weak var MirrorImageView: UIImageView!
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
let identifier = "cellIdentifier"
let dataSource = DataSource()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let cellSpacing: CGFloat = 5
let cellsPerRow: CGFloat = 6
let numberOfItems = 12
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
}
override func viewDidAppear(animated: Bool) {
let cellSize = (collectionView.collectionViewLayout
.collectionViewContentSize().width
/ cellsPerRow)
- (cellSpacing)
layout.itemSize = CGSize(width: cellSize, height: cellSize)
layout.minimumInteritemSpacing = cellSpacing
layout.minimumLineSpacing = cellSpacing
layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
collectionView.collectionViewLayout = layout
self.heightConstraint.constant = cellSize
self.view.layoutIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom2MyOutfits") {
let myOutfitsViewController = segue.destinationViewController
as! MyOutfitsViewController
} else if (segue.identifier == "dressingRoom2StickerPicker") {
let myStickerPickerController = segue.destinationViewController
as! StickerPickerViewController
}
}
func imageTapped(sender: UITapGestureRecognizer) {
var imageView = sender.view as! MMImageView
println(imageView.fname)
performSegueWithIdentifier( "dressingRoom2StickerPicker",
sender: imageView)
}
}
// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! CustomCell
let dressingRoomIcons: [DressingRoomIcon] =
dataSource.dressingRoomIcons
let dressingRoomIcon = dressingRoomIcons[indexPath.row]
var imageView: MMImageView =
createIconImageView(dressingRoomIcon.name!)
cell.setImageV(imageView)
return cell
}
func createIconImageView(name: String) -> MMImageView{
var imageView :MMImageView =
MMImageView(frame:CGRectMake( 0,
0,
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing),
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing)))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.image = UIImage(named: name)
imageView.setName(name)
imageView.backgroundColor = UIColor.clearColor()
imageView.userInteractionEnabled = true
var tapGestureRecognizer =
UITapGestureRecognizer(target: self, action: "imageTapped:")
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tapGestureRecognizer)
return imageView
}
}
EDIT: Here is my CustomCell:
import Foundation
import UIKit
class CustomCell: UICollectionViewCell {
var imageView = MMImageView()
func setImageV(IV: MMImageView) {
self.imageView = IV
}
}
Replace this Code
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> UICollectionViewCell {
Instead of below this :
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
You can return custom cell but you can't change return type of any DataSource or Delegate method.

Resources