I'm generally new to Swift. I have two images, which I want them act like checkbox, first image is unchecked box, second image is checked box, by using didSelectItemAt indexPath: in collection View, how am I gonna shift between two images when user tapped on that collectionviewcell. I'm kinda confused. Heres my code:
var buttonCounter = 0
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return faultyType.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "faulty_type_cell", for: indexPath) as! FaultyTypeCollectionViewCell
cell.faultyTypeLabel.text = faultyType[indexPath.row]
if buttonCounter == 0{
cell.checkboxImage.image = UIImage(named: "Checkboxunpicked")
}
else if buttonCounter == 1{
cell.checkboxImage.image = UIImage(named: "Checkboxpicked")
}
else if buttonCounter == 2{
cell.checkboxImage.image = UIImage(named: "Checkboxpicked")
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 1{
buttonCounter = 1
}
if indexPath.row == 2{
buttonCounter = 2
}
}
I've found a good solution after searching over the net. Heres my solution in which I refer to : [link]How to access buttons in a UICollectionView from a target function set (Swift 3) Happy coding hunting.
var BoxOn = UIImage(named: "Checkboxpicked")
var BoxOff = UIImage(named: "Checkboxunpicked")
var buttonCounter = [Int]()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "faulty_type_cell", for: indexPath) as! FaultyTypeCollectionViewCell
cell.faultyTypeLabel.text = faultyType[indexPath.row]
cell.checkboxImage.image = BoxOff
if buttonCounter.contains(indexPath.row){
cell.checkboxImage.image = BoxOn
}
else{
cell.checkboxImage.image = BoxOff
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if buttonCounter.contains(indexPath.row){
let index = buttonCounter.index(of: indexPath.row)
buttonCounter.remove(at: index!)
collectionView.reloadItems(at: [indexPath])
}
else{
buttonCounter.append(indexPath.row)
collectionView.reloadItems(at: [indexPath])
}
print(buttonCounter)
}
Related
I want to know how I can present a new view controller from "didSelectItemAt - Method "
Please note that UIViewController is not a subclass so I don't have access to the navigationController to present the view controller.
class FeedCell: UICollectionViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let cellId = "cellId"
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor.white
cv.alwaysBounceVertical = true // Making the collection view scrollable vertically
cv.dataSource = self
cv.delegate = self
return cv
}()
override func setupViews(){
super.setupViews()
addSubview(collectionView)
addConstraintWithFormat(format: "H:|[v0]|", views: collectionView)
addConstraintWithFormat(format: "V:|[v0]|", views: collectionView)
collectionView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
You have to implement custom delegate for this. When user select item from collection view, you have to call parent view method using delegate.
Here is reference for this : Access a UICollectionView's parent UIViewController
First give a storyboard id for the viewcontroller then
let destination = UIStoryboard(name: "Storyboard",bundle:nil).instantiateViewController(withIdentifier: "your_viewcontroller_id")
present(destination, animated: false, completion: nil)
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("gallery count : \(self.arrayGallerySingle.count)")
return self.arrayGallerySingle.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gallerycell", for: indexPath) as! GalleryViewCell
return cell
}
//API Fetching method
func galleryFetch(){
let prs = [
"id": dealIDGallery,
"deal_single_page": "1" as String
]
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in
let jsonResponseSingle = result as? NSDictionary
print(" jsonResponse\(String(describing: jsonResponseSingle))")
if let resultGallery = jsonResponseSingle?.value(forKey: "result") as? NSArray{
for keyValuesGallery in resultGallery {
let gallerySingle = (keyValuesGallery as AnyObject).value(forKey: "gallery_images") as? NSArray
print("Gallery Images Key: \(gallerySingle)")
self.arrayGallerySingle = gallerySingle as! [AnyObject]
DispatchQueue.main.async { () -> Void in
self.collectionView?.reloadData()
}
}
}
})
}
How will I show an array of images with key gallery_images on UICollectionViewCell?This line print("Gallery Images Key: \(gallerySingle)") prints the required array of images on console but I am unable to show on collectionView. My JSON response is http://www.jsoneditoronline.org/?id=8eccb63976d76be7d0b2d1b0e8f02306. I am using SDWebImage in my project also.I already checked datasource connection & collectionView IBoutlet as well as an image inside the cell. I am a beginner in Swift pls help and if required any further information pls ask
Swift 3.0 This is my updated Answer hope it will also help someone
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("gallery count : \(self.arrayGallerySingle.count)")
return self.arrayGallerySingle.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gallerycell", for: indexPath) as! GalleryViewCell
if let imgUrl = arrayGallerySingle[indexPath.row] as? String {
if let url = NSURL(string: imgUrl) {
cell.galleryImage?.sd_setImage(with: url as URL, placeholderImage: UIImage(named: "place holder image"), options: .lowPriority)
}
else{
let alertController = UIAlertController(title: "No Gallery Images", message: "test", preferredStyle: .alert)
let okButton = UIAlertAction(title: "Okay", style: .default, handler: nil)
alertController.addAction(okButton)
alertController.present(alertController, animated: true, completion: nil)
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: collectionView.frame.size.width/2, height: collectionView.frame.size.height/3)
}
func galleryFetch(){
let prs = [
"id": dealIDGallery,
"deal_single_page": "1" as String
]
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in
let jsonResponseSingle = result as? NSDictionary
print(" jsonResponse\(String(describing: jsonResponseSingle))")
if let resultGallery = jsonResponseSingle?.value(forKey: "result") as? NSArray{
for keyValuesGallery in resultGallery {
let gallerySingle = (keyValuesGallery as AnyObject).value(forKey: "gallery_images") as? NSArray
print("Gallery Images Key: \(gallerySingle)")
self.arrayGallerySingle = gallerySingle as! [AnyObject]
if self.arrayGallerySingle.count > 0 {
DispatchQueue.main.async { () -> Void in
self.collectionView?.reloadData()
}
} else {
let alertController = UIAlertController(title: "Message", message: "No images found.", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: self.doSomething))
self.present(alertController, animated: true, completion: nil)
}
}
}
})
}
Swift 3.0
you can implement this way with SDWebcache to load image in collectionView cell image.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gallerycell", for: indexPath) as! GalleryViewCell
if let imgUrl = arrayGallerySingle[indexPath.row] as? String {
if let url = URL(string: imgUrl) {
//Replace with your imageView outlet
cell.imageView.sd_setImageWithURL(url, placeholderImage: UIImage(named: "place holder image"), options: .lowPriority)
}
}
return cell
}
And If you want to display 6 cell in collectionView Then you have to set UICollectionViewLayout method to defined size of cell as below.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: collectionView.frame.size.width/2, height: collectionView.frame.size.height/3)
}
You can display alert when array count is not empty and why you reload Collection view inside for loop, Implement it like below.
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in
let jsonResponseSingle = result as? NSDictionary
print(" jsonResponse\(String(describing: jsonResponseSingle))")
if let resultGallery = jsonResponseSingle?.value(forKey: "result") as? NSArray{
for keyValuesGallery in resultGallery {
let gallerySingle = (keyValuesGallery as AnyObject).value(forKey: "gallery_images") as? NSArray
print("Gallery Images Key: \(gallerySingle)")
self.arrayGallerySingle = gallerySingle as! [AnyObject]
}
if self.arrayGallerySingle.count > 0 {
DispatchQueue.main.async { () -> Void in
self.collectionView?.reloadData()
}
} else {
let alertController = UIAlertController(title: "Your Title", message: "their is no images", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alertController, animated: tru, completion: nil)
}
}
})
I have got a collection view inside a table view (Netflix App Style). I followed this tutorial: https://www.thorntech.com/2016/01/scrolling-in-two-directions-like-netflix-part-2-making-api-calls/
Now I want to implement a function that whenever I click on a collection view, it will pass the employee's name to the next view controller.
Here is my code:
import UIKit
class CategoryRow: UITableViewCell, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var jobpost:JobPosition?
var employee: Employee?
var myname = ""
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return jobpost!.Employees.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! EmployeeCell
cell.employeephoto.image = UIImage(named: "spanner")
cell.employeename.text = jobpost?.Employees[indexPath.row].name
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let myname = jobpost?.Employees[indexPath.row].name
//print(myname)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let EmployeeDetailPage = segue.destination as? EmployeeDetailViewController
EmployeeDetailPage?.employeename = myname
print(myname)
}
Now my problem is, the whole PrepareForSegue function didn't actually run. The app runs normally without any error but the data just didn't pass through? (i.e. the print(myname) didn't actually print anything).
Is there something I missed out? Very much appreciated.
Step 1
Create a global variable in your CategoryRow
var myname: String!
Step 2
Change the didSelectItemAt func like below
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
myname = jobpost?.Employees[indexPath.row].name
performSegue(withIdentifier: "EmployeeDetailViewController", sender: myname)
}
Step 3
Create a variable in EmployeeDetailViewController
var employeename: String!
Step 4
Give a identifier to your segue. Here I give "EmployeeDetailViewController"
Then change the prepareForSegue func like below
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EmployeeDetailViewController" {
if let EmployeeDetailVC = segue.destination as? EmployeeDetailViewController {
EmployeeDetailVC.employeename = myname
}
}
}
It looks like your problem is that you are setting a local let constant called myname in your collectionView(_:didSelectItemAt:) method instead of setting your class's myname property.
let myname = jobpost?.Employees[indexPath.row].name
should be:
myname = jobpost?.Employees[indexPath.row].name
I have a collection view that should shows camera roll photos But It didn't show any thing!
I saw similar questions But Their code didn't work !
I added privacy for using album photos in Info.plist
here is my code
class ViewController: UICollectionViewController , UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
grabPhotos()
}
func grabPhotos() {
var imageArray = [UIImage]()
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
if let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i) , targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image , error in
imageArray.append(image!)
})
}
}
else {
print("No Photos")
self.collectionView?.reloadData()
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout:
UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let width = collectionView.frame.width / 3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
}
It Shows Nothing I read Similar questions But they didn't help me
i am working on swift 3.0.1 and xcode 8.2.1,
i want to select multiple images from gallery and show it in different collage in collectionView, when i select images from gallery and press done button collection view did not show anything but when i press Mobile Screen then images shown on the screen. tell me whats wrong in my code and how to get my task. I import these frameworks Photos, BSImagePicker, BSGridCollectionViewLayout. here is my code
#IBOutlet weak var collection: UICollectionView!
var imagePicker = UIImagePickerController()
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
imagePicker.delegate = self
collection.delegate = self
collection.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Camera(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(.camera){
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
imagePicker.cameraCaptureMode = .photo
imagePicker.cameraFlashMode = .auto
imagePicker.modalPresentationStyle = .fullScreen
self.present(imagePicker, animated: true, completion: nil)
}
else{
let alert = UIAlertController(title: "No Camera", message: "Your Device has No Camera", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .destructive, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
#IBAction func Library(_ sender: Any) {
let vc = BSImagePickerViewController()
vc.maxNumberOfSelections = 4
//vc.takePhotoIcon = UIImage(named: "Tick")
vc.albumButton.tintColor = UIColor.blue
vc.cancelButton.tintColor = UIColor.blue
vc.doneButton.tintColor = UIColor.blue
vc.selectionCharacter = "✓"
vc.selectionFillColor = UIColor.green
vc.selectionStrokeColor = UIColor.clear
vc.selectionShadowColor = UIColor.black
vc.selectionTextAttributes[NSForegroundColorAttributeName] = UIColor.lightGray
vc.cellsPerRow = {( verticalSize: UIUserInterfaceSizeClass, horizontalSize: UIUserInterfaceSizeClass) -> Int in
switch (verticalSize, horizontalSize){
case(.compact , .regular):
return 3
case (.compact, .compact): // iPhone5-6 landscape
return 3
case (.regular, .regular): // iPad portrait/landscape
return 3
default:
return 3
}
}
bs_presentImagePickerController(vc, animated: true, select: { (asset: PHAsset) -> Void in
print("Selected: \(asset)")
let imageManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
imageManager.requestImage(for: asset, targetSize: CGSize(width: 132, height: 114) ,contentMode: .aspectFill, options: requestOptions, resultHandler:
{
image, error in
self.imageArray.append(image!)
})
self.collection.reloadData()
},
deselect: { (asset: PHAsset) -> Void in
print("Deselected: \(asset)")
},
cancel: { (asset: [PHAsset]) -> Void in
print("Cancel: \(asset)")
},
finish: { (asset: [PHAsset]) -> Void in
print("Finish: \(asset)")
}, completion: nil)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let Cell : CellClass = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CellClass
Cell.imageView.image = self.imageArray[indexPath.row]
return Cell
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageArray.append(pickedImage)
}
else {
print("Image not Picked")
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.imagePicker = UIImagePickerController()
dismiss(animated: true, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width / 3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.backgroundColor = UIColor.red
}
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.backgroundColor = UIColor.green
}