I created a soundboard and I would like when you long push on the tile (CollectionView Cell) that become a 3D Touch popup with the text of the tile.
I have a ViewCollection with the storyboard ID 'tilePreview'. And the below code, but the 3D touch doesn't.
What do I wrong? Can anybody help me?
import UIKit
import AVFoundation
class CollectionViewController: UICollectionViewController, UIViewControllerPreviewingDelegate {
#IBOutlet var soundBoard: UICollectionView!
var list = [String]()
var buttonOn: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
if traitCollection.forceTouchCapability == UIForceTouchCapability.available {
registerForPreviewing(with: self, sourceView: collectionView!)
}
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> MyCollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCollectionViewCell
let tileText = list[indexPath.row]
cell.cellTitle.text = tileText
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
Speak(currentTitle: list[indexPath.row])
}
// MARK: - Preview tile
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = collectionView?.indexPathForItem(at: location) else { return nil }
guard let cell = collectionView?.cellForItem(at: indexPath) else { return nil }
guard let detailVC = storyboard?.instantiateViewController(withIdentifier: "tilePreview") as? DetailViewController else { return nil }
previewingContext.sourceRect = cell.frame
return detailVC
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
show(viewControllerToCommit, sender: self)
}
}
1) in viewDidLoad check 3D Touch is available or not
override func viewDidLoad() {
super.viewDidLoad()
//3D touch
if(traitCollection.forceTouchCapability == .available){
registerForPreviewing(with: self, sourceView: view)
}
}
2) Delegate method for 3D touch
//3D Touch delegate method
extension PostViewController : UIViewControllerPreviewingDelegate {
#available(iOS 9.0, *)
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
self.navigationController?.show(viewControllerToCommit, sender: self)
}
#available(iOS 9.0, *)
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
let locationCell : CGPoint = self.collectionView.convert(location, from: self.view)
guard let indexPath = self.collectionView?.indexPathForItem(at: locationCell) else {
print(locationCell)
print("Cell Not found")
return nil
}
print("indexPath.row :: \(indexPath.row)")
guard let cell = self.collectionView?.cellForItem(at: indexPath) else { return nil }
let didSelectProduct : ProductDM = self.products[indexPath.row]
let destination: ProductDetailsViewController = UIStoryboard(storyboard: .main).instantiateViewController()
destination.selectedProduct = didSelectProduct
//destination.preferredContentSize = CGSize(width: 0.0, height: 300)
previewingContext.sourceRect = self.collectionView.convert(cell.frame, to: self.collectionView.superview)
return destination
}
}
Related
In my view collection I added a search bar and it filtered the cells but when I click the cell it self the path didn't change the path remain the same as it was before the search .
When I click the cell, it should take you to a specific page. Excuse my poor code but I just started to learn swift. And my problem might be super easy and obvious so bare with me please
This is my code I'm using swift storyboard
import UIKit
import Firebase
import FirebaseStorage
class resViewViewController: UIViewController, UISearchBarDelegate, UISearchDisplayDelegate
{
#IBOutlet weak var background: UIImageView!
#IBOutlet weak var icon: UIImageView!
#IBOutlet weak var resL: UILabel!
#IBOutlet weak var collection: UICollectionView!
var resources:[resFile] = []
let db = Firestore.firestore()
//dummy data
#IBOutlet weak var searchBar: UISearchBar!
var searchActive : Bool = false
var filtered:[resFile] = []
override func viewDidLoad() {
super.viewDidLoad()
let nipCell = UINib(nibName: "resourceCellCollectionViewCell", bundle: nil)
//
collection.delegate = self
collection.dataSource = self
searchBar.delegate = self
///
collection.register(nipCell, forCellWithReuseIdentifier: "cell")
loadResources()
}
func loadResources(){
db.collection("Resources").getDocuments { querySnapshot, error in
if let e = error {
print("There was an issue retrieving data from fireStore. \(e)")
}else {
if let snapshotDocuments = querySnapshot?.documents{
for doc in snapshotDocuments{
let data = doc.data()
if let rName = data["ResName"] as? String, let aName = data["authorName"] as? String, let pName = data["pubName"] as? String, let desc = data["desc"] as? String, let urlName = data["url"] as? String {
let newRes = resFile(name: rName, author: aName, publisher: pName, desc: desc, urlString: urlName)
self.resources.append(newRes)
DispatchQueue.main.async {
self.collection.reloadData()
}
}
}
// DispatchQueue.main.async {
// self.collection.reloadData()
// }
}
}
}
}//end loadResources
//search
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchActive = false;
self.searchBar.endEditing(true)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchActive = false;
self.searchBar.endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchActive = false;
self.searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filtered = resources.filter { $0.name.localizedCaseInsensitiveContains(searchText) }
if(filtered.count == 0){
searchActive = false;
} else {
searchActive = true;
}
self.collection.reloadData()
}
}//end of class
extension resViewViewController:UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let w = (UIScreen.main.bounds.size.width - 110)/2
return CGSize(width: w, height: 160) //154
}//end size
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if(searchActive) {
return filtered.count
} else {
return resources.count
}
}//end count
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collection.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! resourceCellCollectionViewCell
if(searchActive) {
cell.name.text = filtered[indexPath.row].name
} else {
cell.name.text = resources[indexPath.row].name
}
return cell
}//end cell
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "si_resourceListToDetail", sender: indexPath)
}//end
}//extention
extension resViewViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "si_viewResToPost", let vc = segue.destination as? resPostViewController {
vc.delegate = self
} else if segue.identifier == "si_resourceListToDetail",
let vc = segue.destination as? detailedResViewController, let indexPath = sender as? IndexPath {
vc.resource = resources[indexPath.row]
}
}
}//extension
extension resViewViewController: resPostViewControllerDelegate {
func resPost(_ vc: resPostViewController, resource: resFile?, added: Bool){
vc.dismiss(animated: true) {
if added, let r = resource {
self.resources.append(r)
self.collection.reloadData()
}
}
}
}//extension
The indexPath will always be the same if you select the first visible cell in the UICollectionView. You must check the underlying data set to get the difference..
Also: In Swift it's convention to have capital first letter of classes and structs.
You must do something like this to achieve what you want:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item: ResFile
if searchActive {
item = filtered[indexPath.item]
} else {
item = resources[indexPath.item]
}
performSegue(withIdentifier: "si_resourceListToDetail", sender: item)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let item = sender as? ResFile else { return }
// Send item to destination view controller
}
I have an iPad application where you can drag images from Safari into a collection view. I also want to to drag and drop within the collection view to rearrange the collection View cells.
The drag and drop from safari is working. Dragging a cell within the collection view is also possible, but dropping is not possible. I took a look at the UICollectionViewDropDelegate methods "canLoadObjects", "sessionDidUpdate" and "performDrop" which get called in this order. I made another simple collection view app with drag and drop, so I know what to do.
I recognized that in the simple app, when I drag the cell onto another place "canLoadObjects" get called. I confirmed that with a breakpoint. In the other app this does not happen. Instead only "performDrop" gets called, but not "canLoadObjects" and "sessionDidUpdate". I set the delegate correctly (otherwise "performDrop would not get called either).
Does anybody know why some delegate methods doesn't get called? Thanks!
import UIKit
class ImageGalleryViewController: UIViewController {
var cellWidthScale: CGFloat = 1.0
var currentCellSize = CGSize()
var imageFetcher : ImageFetcher!
var loadAllImages = false
var tappedCellIndex = 0
#IBOutlet weak var collectionView: UICollectionView!{
didSet{
collectionView.delegate = self
collectionView.dataSource = self
collectionView.dragInteractionEnabled = true
collectionView.dragDelegate = self
collectionView.dropDelegate = self
collectionView.addGestureRecognizer(UIPinchGestureRecognizer(target: self, action: #selector(adjustCellWidth(with:))))
}
}
var userIsPinching = false
var imageDataTuple : [(NSURL?, CGSize)]? {
didSet{
if loadAllImages == true{
collectionView?.reloadData()
loadAllImages = false
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib(nibName: "ImageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ImageCell")
}
#objc func adjustCellWidth(with recognizer: UIPinchGestureRecognizer){
switch recognizer.state {
case .changed:
userIsPinching = true
cellWidthScale *= recognizer.scale
recognizer.scale = 1.0
collectionView.collectionViewLayout.invalidateLayout()
default: break
}
}
}
//MARK: UICollectionViewDelegate
extension ImageGalleryViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageDataTuple?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath)
if let imageCell = cell as? ImageCollectionViewCell{
imageCell.imageView.image = nil
imageCell.spinner.startAnimating()
if let url = imageDataTuple?[indexPath.row].0{
imageCell.imageUrl = url
//never fetch data on the main queue
DispatchQueue.global(qos: .userInitiated).async {
let urlContent = try? Data(contentsOf: (url as URL).imageURL)
//update the UI always on the main queue
DispatchQueue.main.async {
//check if the url is really the one we want to show
if let imageData = urlContent, url == imageCell.imageUrl, let image = UIImage(data: imageData){
imageCell.spinner.stopAnimating()
imageCell.imageView.image = image
}
else{
imageCell.spinner.stopAnimating()
imageCell.imageView.image = UIImage(systemName: "xmark.octagon.fill")
imageCell.imageView.tintColor = UIColor.red
imageCell.imageView.sizeToFit()
}
}
}
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if let checkedImageData = imageDataTuple{
let imageHeightToWidth = checkedImageData[indexPath.row].1.height/checkedImageData[indexPath.row].1.width
let calculatedWidth = (self.view.frame.width/4) * cellWidthScale
currentCellSize = CGSize(width: calculatedWidth, height: calculatedWidth * imageHeightToWidth)
return currentCellSize
}
return CGSize.zero
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
tappedCellIndex = indexPath.item
performSegue(withIdentifier: "ShowImage", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowImage"{
if let destVC = segue.destination as? DetailImageViewController{
destVC.imageUrl = imageDataTuple![tappedCellIndex].0
}
}
}
}
//MARK: UICollectionViewDropDelegate
extension ImageGalleryViewController: UICollectionViewDropDelegate{
//1. Can the dropDelegate handle the object?
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
//requirement: only drop with image and url should be handled
return session.canLoadObjects(ofClass: NSURL.self)
}
//2. update the session. Return a propsal in which manner the object schould be dropped (.copy; .move...)
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
//Es wird überprüft, ob der collectionView auf dem gedroppt werden soll der ist, von dem das DragItem stammt
let isSelf = (session.localDragSession?.localContext as? UICollectionView) == collectionView
let dropOperation: UIDropOperation = isSelf ? .move : .copy
//intent: Soll eine neue Cell erstellt werden oder in die eingefügt werden, über der man sich gerde befindet?
return UICollectionViewDropProposal(operation: dropOperation, intent: .insertAtDestinationIndexPath)
}
//3. perform the actual drop. update UI and the model
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
let destinationIntexPath = coordinator.destinationIndexPath ?? IndexPath(row: 0, section: 0)
for item in coordinator.items{
//Is the drop from the same collectionView or external? internal --> != nil
if let sourceIndexPath = item.sourceIndexPath{
if let url = item.dragItem.localObject as? NSURL{
collectionView.performBatchUpdates {
imageDataTuple?.remove(at: sourceIndexPath.item)
imageDataTuple?.insert((url, currentCellSize), at: destinationIntexPath.item)
collectionView.deleteItems(at: [sourceIndexPath])
collectionView.insertItems(at: [destinationIntexPath])
}
coordinator.drop(item.dragItem, toItemAt: destinationIntexPath)
}
}
//external --> nil
else{
var dataTupel: (NSURL?, CGSize?) {
didSet{
DispatchQueue.main.async {
if let controllerTitel = self.title, let presentImageSize = dataTupel.1, let presentURL = dataTupel.0{
if ImageGalleryModel.imageURLs[controllerTitel] != nil {
ImageGalleryModel.imageURLs[controllerTitel]!.append((presentURL, presentImageSize))
print(ImageGalleryModel.imageURLs)
self.imageDataTuple = ImageGalleryModel.imageURLs[controllerTitel]!
self.collectionView.insertItems(at: [IndexPath(item: ImageGalleryModel.imageURLs[controllerTitel]!.count - 1, section: 0)])
}
}
}
}
}
item.dragItem.itemProvider.loadObject(ofClass: NSURL.self) { provider, error in
dataTupel.0 = provider as? NSURL
}
item.dragItem.itemProvider.loadObject(ofClass: UIImage.self) { provider, error in
if let receivedImage = provider as? UIImage{
dataTupel.1 = receivedImage.size
}
}
}
}
}
}
//MARK: UICollectionViewDragDelegate
extension ImageGalleryViewController: UICollectionViewDragDelegate{
//Proveide inital drag items
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
return dragItem(at: indexPath)
}
//Provide drag items which were added while dragging
func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
session.localContext = collectionView
return dragItem(at: indexPath)
}
private func dragItem(at indexPath: IndexPath) -> [UIDragItem]{
if let image = (collectionView.cellForItem(at: indexPath) as? ImageCollectionViewCell)?.imageView.image{
let dragItem = UIDragItem(itemProvider: NSItemProvider(object: image))
dragItem.localObject = image
return [dragItem]
}
return []
}
}
//MARK: New selected Gallery
extension ImageGalleryViewController: GalleryListViewControllerDelegate{
func gallerySelected(name: String) {
loadAllImages = true
imageDataTuple = ImageGalleryModel.imageURLs[name]
self.title = name
}
}
The problem was that the auto correction chose delegate methods of the UIDropInteraction-delegate and not from the UICollectionViewDropDelegate. Just picked the correct methods and everything works as intended.
In my app using UIPageViewController to display full size images, and at the bottom of screen have thumbnail CollectionView each thumbnail is representing UIPageViewController full size image.My question is how to achieve paging of UIpageViewController when user select different thumbnail collection view cell?
if anyone know how to achieve this functionality , please help me with code or advice or links. Thanks
I believe I have to work with UICollectionView’s didSelectItemAtIndexPath method ,but not too sure how best to do it and would really appreciate help, please.
My Collection View File
protocol ThumbnailViewDelegate: class {
func didSelectThumbnail(at index: Int)
}
class ThumbnailView: UIView, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout, PhotoCollectionViewModelPresenter{
weak var delegate: ThumbnailViewDelegate?
var assets: [PHAsset] = []
private let viewModel = PhotoCollectionViewModel()
//private var myViewModel: DetailViewModel!
private let imageDownloader = ImageDownloader(targetSize: CGSize(width: 80, height: 80 ))
//var selectedImage: UIImage?
lazy var thumbnailCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
view.translatesAutoresizingMaskIntoConstraints = false
view.isPagingEnabled = true
view.delegate = self
view.dataSource = self
view.isPrefetchingEnabled = false
view.register(ThumbnailCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
let cellImageView = ThumbnailCollectionViewCell()
view.addSubview(cellImageView.imageView)
view.backgroundColor = UIColor.white
return view
}()
let imageView: ThumbnailCollectionViewCell = {
let view = ThumbnailCollectionViewCell()
view.contentMode = .scaleAspectFit
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(thumbnailCollectionView)
thumbnailCollectionView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
thumbnailCollectionView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
thumbnailCollectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
thumbnailCollectionView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func propagateReload() {
thumbnailCollectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return assets.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! ThumbnailCollectionViewCell
cell.layer.masksToBounds = true
cell.layer.cornerRadius = 8
let image = assets[indexPath.item]
imageDownloader.download(asset: image) { [weak self] (image) in
self?.configureCell(indexPath: indexPath, image: image)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: 80.0, height: 80.0)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.didSelectThumbnail(at: indexPath.item)
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
}
func configureCell(indexPath: IndexPath, image: UIImage) {
guard let cell = thumbnailCollectionView.cellForItem(at: indexPath) as? ThumbnailCollectionViewCell else {
return
}
cell.configure(image: image)
}
}
PageViewController File
class MainPageViewController: UIPageViewController {
var mainImageIndex: Int?
var pageViewModels: [DetailPageViewModel]!
var viewModel: DetailViewModel!
var collectionAssets: [PHAsset] = []
var selectedAsset: UIImage?
private var pendingIndex: Int?
// Collection View
lazy var collectionView: ThumbnailView = {
let view = ThumbnailView()
view.delegate = self
view.assets = self.collectionAssets
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
//MARK: - Create VC
lazy var pageViewControllersArray: [PageViewController] = {
return pageViewModels.map {
return PageViewController(viewModel: $0)
}
}()
var currentIndex:Int {
get {
return pageViewControllersArray.index(of: self.viewControllers!.first! as! PageViewController)!
}
set {
guard newValue >= 0,
newValue < pageViewControllersArray.count else {
return
}
let vc = pageViewControllersArray[newValue]
let direction:UIPageViewController.NavigationDirection = newValue > currentIndex ? .forward : .reverse
self.setViewControllers([vc], direction: direction, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
delegate = self
view.backgroundColor = UIColor.white
setViewControllers([pageViewControllersArray[mainImageIndex ?? 0]], direction: .forward, animated: true, completion: nil)
self.view.addSubview(collectionView)
setupCollectioViewAutoLayout()
}
func setupCollectioViewAutoLayout(){
collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
collectionView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
collectionView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
func viewWillAppear() {
super.viewWillAppear(true)
}
}
extension MainPageViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource, ThumbnailViewDelegate {
func didSelectThumbnail(at index: Int) {
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewController = viewController as? PageViewController else {return nil}
if let index = pageViewControllersArray.index(of: viewController){
if index > 0{
return pageViewControllersArray[index - 1]
}
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewController = viewController as? PageViewController else {return nil}
if let index = pageViewControllersArray.index(of: viewController){
if index < pageViewControllersArray.count - 1{
return pageViewControllersArray[index + 1]
}
}
return nil
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return pageViewControllersArray.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return currentIndex
}
}
When the select method is called, show another page view or page view controller on the whole screen.
when i write the function touchphoto, the post.postID is nil .I want to pass the postID to another view controller. I add the code for the profilecell and profileviewcontroller
protocol profilecellDelegate {
func goToPhotoDetail(postid: String)}
class profilecell: UICollectionViewCell {
var delegate: profilecellDelegate?
#IBOutlet weak var image: UIImageView!
var post: Post? {
didSet {
updateView()
}
}
func updateView() {
if let photoUrlString = post?.photoUrl {
let photoUrl = URL(string: photoUrlString)
image.sd_setImage(with: photoUrl)
}
}
#IBAction func touchphoto(_ sender: Any) {
if let id = post?.postID {
delegate?.goToPhotoDetail(postid: id)
}
}
}
//profileviewcontroller
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "profilecell", for: indexPath) as! profilecell
let post = posts[indexPath.row]
cell.post = post
cell.delegate = self
return cell
}
extension ProfileViewController: profilecellDelegate {
func goToPhotoDetail(postid: String) {
performSegue(withIdentifier: "Photo_ProfileSegue", sender: postid)
}}
Received an error
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
when trying to peek and pop from a collection view. I've checked my data struct and index path but everything seems to be fine.
Here's my code for the collections view
class thisSeaonViewController: UICollectionViewController, UIViewControllerPreviewingDelegate {
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var URLArrayStringThisSeason = [String]()
var currentURL = String()
override func viewDidLoad() {
generateData()
if( traitCollection.forceTouchCapability == .available){
registerForPreviewing(with: self as! UIViewControllerPreviewingDelegate, sourceView: view)
}
}
override func viewDidAppear(_ animated: Bool) {
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
let url = NSURL(string: URLArrayStringThisSeason[indexPath.row])
let placeholderImage = UIImage(named: "Rectangle")!
let filter = AspectScaledToFillSizeWithRoundedCornersFilter(
size: imageView.frame.size,
radius: 0
)
imageView.af_setImage(withURL: url as! URL, placeholderImage: placeholderImage, filter: filter, imageTransition: .crossDissolve(0.2)
)
cell.backgroundColor = UIColor.init(hexString: "#F3F3F3")
cell.layer.cornerRadius = 3.0
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return URLArrayStringThisSeason.count
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "gridDetailedView") as! gridDetailedViewController
vc.imageURL = URLArrayStringThisSeason[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
func generateData() {
if URLArrayStringThisSeason.count == 0 {
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
}
let queryThisSeason = FIRDatabase.database().reference().child("thisSeason")
queryThisSeason.keepSynced(true)
queryThisSeason.observeSingleEvent(of: .value, with: {(snapshot) in
if snapshot.childrenCount != 0 {
let urlArray = snapshot.value as! [String]
let urlLimitedArray = Array(urlArray.reversed())
self.URLArrayStringThisSeason = urlLimitedArray
self.collectionView?.reloadData()
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
})
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = collectionView?.indexPathForItem(at: location) else { return nil }
guard let cell = collectionView?.cellForItem(at: indexPath) else { return nil }
guard let detailVC = storyboard?.instantiateViewController(withIdentifier: "gridDetailedView") as? gridDetailedViewController else { return nil }
//let photo = UIImage(named: "Rectangle")
detailVC.imageURL = URLArrayStringThisSeason[indexPath.row]
print(URLArrayStringThisSeason[indexPath.row])
detailVC.preferredContentSize = CGSize(width: 300, height: 300)
previewingContext.sourceRect = cell.frame
print("peek")
return detailVC
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
self.navigationController?.show(viewControllerToCommit, sender: Any?.self)
print("pop")
}
}
when peeking and popping, the function is supposed to send the imageURL to the detailed view controller and AlamofireImage will handle the image download and loading.
However, I've been getting misalignment issues with the collections view as the source rect will appear slightly above the cells and preventing peek and pop at certain parts of the cell. I think that this could be the cause of the peek and pop crash too.
edit:
here's what happens when I try to do peek and pop, you can see the focus of the cell is slightly shifted on top.
Ok I fixed the misalignment problem by changing this registerForPreviewingWithDelegate(self, sourceView: view)
to this
registerForPreviewingWithDelegate(self, sourceView: self.collectionView!)
however, the app is still crashes everytime I try to peek and pop.
Edit:
Ok the other problem is pretty much just some errors in the code. Just follow the above to fix the misalignment problem.