Line 28-29 is just a setup for another irrelevant collectionView. "collectionView0" is for "collectionViewEffects" "indexPath.row = 0", and "collectionView1" is for "collectionViewEffects" "indexPath.row = 1"class EffectsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
effectsView.addSubview(collectionViewEffects)
setupEffectsCollectionView()
collectionViewEffects.isUserInteractionEnabled = true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EffectsPhotoSegue" {
if let previousViewController = segue.destination as? PhotoViewController {
DispatchQueue.main.async {
previousViewController.photoImageView.image = self.effectsImageView!.image
previousViewController.filteredImage = self.effectsImage
previousViewController.pickedImage = self.pickedEffectsImage
previousViewController.effectsSegmentedControl()
(previousViewController.menuStackView).isHidden = true
resetConfirmCollectionView.isHidden = true
effectsMenuCollectionView.isHidden = false
}
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == collectionViewEffects {
if indexPath.row == 0 {
let name = Notification.Name(rawValue: collectionView0)
NotificationCenter.default.post(name: name, object: effectsMenuCollectionView)
effectsImageView!.image = pickedEffectsImage
self.performSegue(withIdentifier: "EffectsPhotoSegue", sender: self)
}
if indexPath.row == 1 {
let name = Notification.Name(rawValue: collectionView1)
NotificationCenter.default.post(name: name, object: effectsMenuCollectionView)
effectsImageView!.image = pickedEffectsImage
let imageViewHeight: CGFloat = effectsImageView!.image!.size.height
let imageViewWidth: CGFloat = effectsImageView!.image!.size.width
effectsImage = effects.cropToBounds(image: effectsImageView!.image!, width: Double(imageViewWidth), height: Double(imageViewHeight))
self.performSegue(withIdentifier: "EffectsPhotoSegue", sender: self)
}
}
}
Post
Replies
Boosts
Views
Activity
I have taken the Notification approach. "collectionViewEffects" triggering the "effectsMenuCollectionView". I'm having trouble with reaching (line 53) "effectsMenuImage". I'm not sure if I'm on the right track. Could you please give me any comments on that ?import Foundation
import UIKit
import Photos
let collectionView0 = "collectionView0"
let collectionView1 = "collectionView1"
class PhotoViewController: UIViewController, UIScrollViewDelegate {
let menuCollectionView0 = Notification.Name(rawValue: collectionView0)
let menuCollectionView1 = Notification.Name(rawValue: collectionView1)
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
photoImageView.isUserInteractionEnabled = true
imagePicker.delegate = self
view.addSubview(collectionViewPreview)
setupCollectionView()
collectionViewPreview.isHidden = true
view.addSubview(resetConfirmCollectionView)
setup
ResetConfirmCollectionView()
view.addSubview(effectsMenuCollectionView)
setupEffectsMenuCollectionView()
createObservers()
}
func createObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(updateCollectionView0(notification:)), name: menuCollectionView0, object: effectsMenuCollectionView)
}
@objc func updateCollectionView0(notification: NSNotification) {
if notification.name == menuCollectionView0 {
let cellCount = effectsMenuCollectionView.visibleCells.count
let item = cellCount - 1
let cellIndexPath = IndexPath(item: item, section: 0)
effectsMenuCollectionView.insertItems(at: [cellIndexPath])
let cell = effectsMenuCollectionView.cellForItem(at: cellIndexPath)
let config = UIImage.SymbolConfiguration(pointSize: 30, weight: .semibold)
guard cell == UIImage(systemName: "pencil", withConfiguration: config) else {
print("SystemImage not available")
}
EffectsMenuCell.effectsMenuImage = cell
}
}
fileprivate func setupEffectsMenuCollectionView() {
effectsMenuCollectionView.backgroundColor = .lightGray
effectsMenuCollectionView.leadingAnchor.constraint(equalTo: photoView!.leadingAnchor).isActive = true
effectsMenuCollectionView.trailingAnchor.constraint(equalTo: photoView!.trailingAnchor).isActive = true
effectsMenuCollectionView.bottomAnchor.constraint(equalTo: photoView!.bottomAnchor).isActive = true
effectsMenuCollectionView.heightAnchor.constraint(equalToConstant: 50).isActive = true
effectsMenuCollectionView.clipsToBounds = true
effectsMenuCollectionView.dataSource = self
effectsMenuCollectionView.delegate = self
effectsMenuCollectionView.isHidden = true
}
let effectsMenuCollectionView: UICollectionView = {
let spacing: CGFloat = 100
let effectsMenuLayout = UICollectionViewFlowLayout()
let effectsMenuCv = UICollectionView(frame: .zero, collectionViewLayout: effectsMenuLayout)
effectsMenuCv.translatesAutoresizingMaskIntoConstraints = false
effectsMenuLayout.sectionInset = UIEdgeInsets(top: spacing/5, left: spacing/2, bottom: spacing/5, right: spacing/2)
effectsMenuLayout.minimumInteritemSpacing = spacing
effectsMenuCv.register(EffectsMenuCell.self, forCellWithReuseIdentifier: "EffectsMenuCellID")
return effectsMenuCv
}()
class EffectsMenuCell: UICollectionViewCell {
let effectsMenuImageView: UIImageView = {
let iv = UIImageView()
iv.tintColor = .darkGray
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .top
iv.clipsToBounds = true
return iv
}()
var effectsMenuImage: UIImage? {
get {
effectsMenuImageView.image
}
set {
effectsMenuImageView.image = newValue
}
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(effectsMenuImageView)
effectsMenuImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: -10).isActive = true
effectsMenuImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
effectsMenuImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
effectsMenuImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}
import Foundation
import UIKit
import Photos
class EffectsViewController: UIViewController {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == collectionViewEffects {
if indexPath.row == 0 {
let name = Notification.Name(rawValue: collectionView0)
NotificationCenter.default.post(name: name, object: effectsMenuCollectionView)
effectsImageView!.image = pickedEffectsImage
self.performSegue(withIdentifier: "EffectsPhotoSegue", sender: self)
}
}
}
Hi Claude, the collectionViews are in different viewControllers. The 1st viewControllers' collectionView is triggered by the next (2nd) viewController. I guess your 2nd advice is the most feasible one. I will get back to you with my results.
Your guidance solved the problem, thank you very much Claude, have a nice day.
Hi Claude, thank you for your response. I actually don't even want to have a tracking thumb. What I'm trying to achieve is I want the slider to move in accordance with a finger swipe movement. Let's say when the finger moves from right to left in anywhere within the view, I would like the slider's value(the blue color filling the range) to move towards the negative end. And for vice versa, the slider's value should be moving towards the positive range. To achieve this I think I need to be able to assign the "effectsSlider" outlet on the "addPanGesture" method. When I do that the whole slider is moving instead of what I'm trying to achieve. I think I need an extra variable for that.
I tried with 1 setting for the cell and the app crashed 🙂 Thank you so much for your guidance, it works perfectly now.
Thank you for your comprehensive guidance. I've followed your steps, also cancelled out the constraints of the "effectsImageView" as they aren't relevant anymore. I'm not sure if "return UICollectionViewCell()" was also relevant in line 22. The values for "cellImage.size" I'm getting are (57.0, 44.6). I'm roughly aiming at (15.0, 15.0). I guess the reason you suggested me to use 2 different settings for the cell is to have a different size for the backgroundColor.
Hello OOPer, thank you for your response. I have the constraints of the UIImageView defined but I think I also need to define the size within the "override init" block. Here is the code you have requested;class CustomEffectsCell: UICollectionViewCell {
fileprivate let effectsImg: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFit
iv.clipsToBounds = true
return iv
}()
var effectsImage: UIImage? {
get {
effectsImg.image
}
set {
effectsImg.image = newValue
}
}
fileprivate let effectsLbl: UILabel = {
let il = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
il.translatesAutoresizingMaskIntoConstraints = false
il.contentMode = .scaleAspectFit
il.clipsToBounds = true
return il
}()
var effectsLabel: String? {
get {
effectsLbl.text
}
set {
effectsLbl.text = newValue
}
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(effectsImg)
contentView.addSubview(effectsLbl)
effectsImg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
effectsImg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
effectsImg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
effectsImg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
effectsLbl.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
It was conceptually helpful but considering almost all the code being deprecated and the errors I'm getting, is there a more feasible way to adjust the "cellImage" size within the indexPath.row block ? Regarding the code I have shared, I think I'm pretty close to the solution.
Hello Claude, thank you for your revert. I have created the collectionView programmatically, I'm not sure if I can define a xib for the cell in this case.
For future reference, the solution I came up with is;@objcfunc touchTapped(_ sender: UITapGestureRecognizer) {
sender.cancelsTouchesInView = false
if collectionView.isTracking == false {
if menuStackView.isHidden == false {
collectionView.isHidden = true
menuStackView.isHidden = true
} else {
menuStackView.isHidden = false
collectionView.isHidden = false
}
}
}
With "touchTapped()" and "assignTap()" methods being enabled, tap on the collectionView don't register as I added print("A") for indexPath.row == 0 at didSelectedItemAt.
When I tap outside the collectionView and the menuStackView, I want them to be hidden and then appear again. If I keep these methods, then the changes on the "photoImageView.image" don't take place with taps on the collectionView images. I tried adding "collectionView.reloadData()" at line 15 but nothing changes.
Now, it works with a charm. Thank you so much for your guidance. The only problem I'm having is if I keep the "assignTap()" and "touchTapped()" methods. The effect doesn't work on the "photoImageView.image". I tried this but it still doesn't work;@objc func touchTapped(_ sender: UITapGestureRecognizer) { if collectionView.isTracking == false { if menuStackView.isHidden == false { collectionView.isHidden = true menuStackView.isHidden = true } else { menuStackView.isHidden = false collectionView.isHidden = false } } else { collectionView.reloadData() } }
I think I'm going though a retain cycle on; (but "weak" or "unowned" references don't solve the situation.)var rawImage: UIImage? { get { photoImageView.image } set { photoImageView.image = newValue } }