I have this Main Page which is PhotoStreamViewController that has a CollectionView, what I want to happen is when I click one picture of the collectionView from the PhotoStreamController, it will automatically go to the DetailStreamController's page collectionView then I can swipe left and right the same photos from the PhotoStreamViewController, my problem is the segue from PhotoStreamViewController to, DetailStreamController.
import UIKit
class Photo {
class func allPhotos() -> [Photo] {
var photos = [Photo]()
if let URL = Bundle.main.url(forResource: "Photos 2", withExtension: "plist") {
print(URL)
if let photosFromPlist = NSArray(contentsOf: URL) {
print(photosFromPlist)
for dictionary in photosFromPlist {
let photo = Photo(dictionary: dictionary as! NSDictionary)
photos.append(photo)
}
}
}
return photos
}
var image: UIImage
init(image: UIImage) {
self.image = image
}
convenience init(dictionary: NSDictionary) {
let photo = dictionary["imageName"] as? String
let image = UIImage(named: photo!)?.decompressedImage
self.init(image: image!)
}
}
here's my code of PhotoStreamController
import UIKit
class PhotoStreamViewController: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate {
var parentController: UIViewController?
#IBOutlet var photoStream: UICollectionView!
var photos = Photo.allPhotos()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let cell = sender as? UICollectionViewCell {
if let indexPath = self.photoStream?.indexPath(for: cell) {
if segue.identifier == "StreamToStreamDeatilController" {
let photoViewController : StreamDetailController = segue.destination as! StreamDetailController
photoViewController. " I dont know what to put here" this is the missing code. cause I cant access the Class Photo
}
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return photos.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellA = collectionView.dequeueReusableCell(withReuseIdentifier: "Celler", for: indexPath) as! AnnotatedPhotoCell
cellA.box = Box(fImage: photos[indexPath.row].image)
return cellA
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let paper = photoDataSource.photoForItemAtIndexPath(indexPath) {
performSegue(withIdentifier: "StreamToStreamDeatilController", sender: paper)
}
}
}
ExtraViewCell
StreamDetailController
Related
I'm trying to pass data from a news Api to a tableView, but I'm having an issue, the data is returning nil when it get's pass to the SectorNewsVC, And by the time it gets to the infoVC it's still nil, however when I print the data before it gets pass it there. Can someone explain what I am doing wrong and, how I can go about fixing it? Thank You!!
This is where I'm creating the URLSession and fetching the data, and attempting to pass the data over to the Viewcontroller which is calling the fetchSectorNews() to retrive the data from an API.
struct FetchCategoryResponse {
let sectorUrl = "https://stocknewsapi.com/api/v1/category?section=alltickers&items=50&type=article&token=\(Key.api_key)"
func fetchSectorNews(sector: String) {
let urlString = "\(sectorUrl)§or=\(sector)"
performRequest(urlString: urlString)
print(urlString)
}
func performRequest(urlString: String) {
// create url
if let url = URL(string: urlString) {
// create url session
let session = URLSession(configuration: .default)
// give session a task
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
if let news = self.parseJson(sectorData: safeData) {
DispatchQueue.main.async {
let vc = SectorNewsVC()
vc.dataToPass = news
}
}
}
}
task.resume()
}
}
// parse the jason data
func parseJson(sectorData: Data) -> SectorModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(CatergoryData.self, from: sectorData)
let newsUrl = decodedData.data[1].title
let imageUrl = decodedData.data[1].news_url
let title = decodedData.data[1].title
let source = decodedData.data[1].source_name
let sectorPayload = SectorModel(url: newsUrl, image: imageUrl, title: title, source: source)
// this sectorpayload gets saved to the news var in the performrequest() bc its being return
return sectorPayload
}
catch {
print(error)
return nil
}
}
} // END Struct
so in this ViewController I'm setting up the collectionViewController and calling the fetchSectorNews() and passing in the title of the label as the argunemt for the function, while trying to pass the data over to the detialViewController
var titleArr = ["Technology", "Materials", "HealthCare"]
var dataToPass: SectorModel?
var fetchNews = FetchCategoryResponse()
extension SectorNewsVC: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titleArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! SectorCollectionCell
cell.listLabel.text = titleArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
if curentIndex == 0 {
fetchNews.fetchSectorNews(sector: "technology")
}
else if curentIndex == 1 {
fetchNews.fetchSectorNews(sector: "materials")
}
else if curentIndex == 2 {
fetchNews.fetchSectorNews(sector: "healthcare")
}
performSegue(withIdentifier: "segue", sender: nil)
} // end cv()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
if let indexPath = self.collectionView.indexPathsForSelectedItems {
let detailVC = segue.destination as! infoVC
detailVC.newData = dataToPass
print(indexPath)
}
}
}
}
Here is where I want to display the data
class infoVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var newData: SectorModel?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
tableView.backgroundColor = #colorLiteral(red: 0.1926331222, green: 0.2233074605, blue: 0.3540094197, alpha: 1)
tableView.register(UINib(nibName: "DifferentSectorCell", bundle: nil), forCellReuseIdentifier: "cellId")
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.clear
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tap")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! DifferentSectorCell
cell.titleLabel.text = "hey"
cell.sourceLabel.text = "hello"
return cell
}
}
I would suggest a different approach. Sending the section to the child controller, and do the request on the child. Here is what has worked for me before
on the parent controller:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
var sector = ""
if curentIndex == 0 {
sector = "technology"
}
else if curentIndex == 1 {
sector = "materials"
}
else if curentIndex == 2 {
sector = "healthcare"
}
performSegue(withIdentifier: "segue", sender: sector)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let detailVC = segue.destination as! infoVC
detailVC.sector = sender as! String
}
}
}
on the child controller:
var sector = ""
override func viewWillAppear() {
super.viewWillAppear()
fetchNews.fetchSectorNews(sector: self.sector)
}
When I click on any UICollectionView item, I got this error on PerformSegue line:
Thread 1: Fatal error: Index out of range
However, the compiler don't read the function and simply jumps straight to the PerformSegue, so I end up out of index. How can I fix that? When the user clicks on any UICollectionView index, I gotta replace the Indexpath in the function parameter and repeat the process.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
DispatchQueue.main.async {
self.dataCategoriaID = data
}
}
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}
Complete ViewController file:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UITableViewDataSource, UITableViewDelegate, UICollectionViewDelegate {
#IBOutlet weak var tableViewTopSell: UITableView!
#IBOutlet var collectionView: UICollectionView!
#IBOutlet weak var collectionViewBanner: UICollectionView!
var indexPathId = Int()
var dataSource: [Content] = [Content]()
var dataBanner: [Banner] = [Banner]()
var dataTopSold: [Top10] = [Top10]()
var dataCategoriaID: [CategoriaIDItems] = [CategoriaIDItems]()
override func viewDidLoad() {
super.viewDidLoad()
//Delegate TableView
self.tableViewTopSell.delegate = self
//SetupNavBarCustom
self.navigationController?.navigationBar.CustomNavigationBar()
let logo = UIImage(named: "tag.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
//CallAPIData
getTopSold { (data) in
DispatchQueue.main.async {
self.dataTopSold = data
self.tableViewTopSell.reloadData()
}
}
getBanner { (data) in
DispatchQueue.main.async {
self.dataBanner = data
self.collectionViewBanner.reloadData()
}
}
getAudiobooksAPI { (data) in
DispatchQueue.main.async {
self.dataSource = data
self.collectionView.reloadData()
}
}
}
//CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (collectionView == self.collectionView) {
return self.dataSource.count
}else{
return self.dataBanner.count
}}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if (collectionView == self.collectionView) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
let content = self.dataSource[indexPath.item]
cell.bookLabel.text = content.descricao
cell.bookImage.setImage(url: content.urlImagem, placeholder: "")
return cell
}else if (collectionView == self.collectionViewBanner) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCellBanner", for: indexPath) as! CollectionViewCell
let content = self.dataBanner[indexPath.item]
cell.bannerImage.setImage(url: content.urlImagem, placeholder: "")
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
DispatchQueue.main.async {
self.dataCategoriaID = data
}
}
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}
//TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataTopSold.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "topSoldCell", for: indexPath) as! TableViewCell
let content = self.dataTopSold[indexPath.row]
cell.labelNomeTopSell.text = content.nome
cell.imageViewTopSell.setImage(url: content.urlImagem, placeholder: "")
cell.labelPrecoDe.text = "R$ \(content.precoDe)"
//Colocar strike em cima do Preco Antigo
let oldPrice = "R$ \(content.precoDe)"
let promotionString = oldPrice + ""
let attributedStr = NSMutableAttributedString(string: promotionString)
let crossAttr = [NSAttributedStringKey.strikethroughStyle: NSUnderlineStyle.styleSingle.rawValue]
attributedStr.addAttributes(crossAttr, range: NSMakeRange(0, oldPrice.count))
cell.labelPrecoDe.attributedText = attributedStr
//
cell.labelPrecoPor.text = "R$ 119.99"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segueId", sender:self.dataTopSold[indexPath.row])
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueId" {
let des = segue.destination as? TelaDetalheProdutos
//.item possui uma propriedade instanciada na TelaDetalheProdutos
des?.item = (sender as? Top10)
//Segue para CollectionView Categorias
} else if segue.identifier == "segueCategorias" {
let desc = segue.destination as? TelaCategorias
desc?.item = (sender as? CategoriaIDItems)
}
}
}
//Cast UIImage Extension
extension UIImageView{
func setImage(url : String, placeholder: String, callback : (() -> Void)? = nil){
self.image = UIImage(named: "no-photo")
URLSession.shared.dataTask(with: NSURL(string: url)! as URL, completionHandler: { (data, response, error) -> Void in
guard error == nil else{
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
if let callback = callback{
callback()
}
})
}).resume()
}
}
Use main thread only to update UI. The problem is you are setting dataCategoriaID on main thread I assume which is inside asynchronous network call function. So you are trying to perform segue before setting dataCategoriaID and that is the reason it is empty and throwing index out of range error.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
self.dataCategoriaID = data
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}
}
I have a headerView in which I am having a float button. Since all the subitems in the float button are programmatically generated and it is a subview of headerView I am not able to call a performSegue. I tried creating a delegate method, But I totally messed it up. I know that protocols might be the fix, But i am quite unsure about how to exactly work it out.
I am attaching the image of the headerView below
headerView code :
class ProfileHeader: UICollectionReusableView, FloatyDelegate {
#IBOutlet weak var pname: UILabel!
#IBOutlet weak var pusername: UILabel!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var userDesc: UILabel!
#IBOutlet weak var allviews: UILabel!
#IBOutlet weak var allphotos: UILabel!
var user : User!
var userposts = [String]()
var currentViewUser: String!
var floaty = Floaty()
let uid = KeychainWrapper.standard.string(forKey: KEY_UID)
override func awakeFromNib() {
super.awakeFromNib()
user = User()
fetchCurrentUser()
profilePic.addBlackGradientLayer(frame: profilePic.bounds)
layoutFAB()
}
func layoutFAB() {
floaty.openAnimationType = .slideDown
floaty.hasShadow = false
floaty.addItem("Edit Profile", icon: UIImage(named: "")) { item in
// here is where the segue is to be performed.
}
floaty.paddingY = (frame.height - 50) - floaty.frame.height/2
floaty.fabDelegate = self
floaty.buttonColor = UIColor.white
floaty.hasShadow = true
floaty.size = 45
addSubview(floaty)
}
func fetchCurrentUser(){
if uid != nil {
FBDataservice.ds.REF_CURR_USER.observeSingleEvent(of: .value, with: { (snapshot) in
if let allData = snapshot.value as? Dictionary<String, Any> {
if let cred = allData["credentials"] as? Dictionary<String, Any> {
let user = User(userid: snapshot.key, userData: cred)
self.pusername.text = user.username
self.pname.text = user.name
self.userDesc.text = user.aboutme
self.allphotos.text = String(user.photos)
self.allviews.text = String(user.views)
if user.userPic != nil {
let request = URL(string: user.userPic)
Nuke.loadImage(with: request!, into: self.profilePic)
} else {
return
}
}
}
})
}
}
}
CollectionViewController code:
class ProfileVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
var user : User!
var userposts = [String]()
var post = [Posts]()
var currentViewUser: String!
var imagePicker: UIImagePickerController!
var fetcher: Fetcher!
var imageFromImagePicker = UIImage()
let uid = KeychainWrapper.standard.string(forKey: KEY_UID)
override func viewDidLoad() {
super.viewDidLoad()
user = User()
fetcher = Fetcher()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
collectionView.delegate = self
collectionView.dataSource = self
initializeUserPost()
let nib = UINib(nibName: "ProfileCell", bundle: nil)
collectionView.register(nib, forCellWithReuseIdentifier: "ProfileCell")
}
func editProfileTapped() {
performSegue(withIdentifier: "manageconnections", sender: nil)
}
#IBAction func manageConnections(_ sender: Any) {
performSegue(withIdentifier: "manageconnections", sender: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
collectionView.reloadData()
}
#IBAction func gotoSettings(_ sender: Any) {
performSegue(withIdentifier: "openSettings", sender: nil)
}
#IBAction func newPost(_ sender: Any) {
uploadNewPost()
}
#IBAction func backToFeed(_ sender: Any) {
performSegue(withIdentifier: "feedroute", sender: nil)
}
#IBAction func searchUsers(_ sender: Any) {
performSegue(withIdentifier: "searchNow", sender: nil)
}
func initializeUserPost() {
FBDataservice.ds.REF_POSTS.observe(.value, with: { (snapshot) in
if let snap = snapshot.value as? Dictionary<String, Any> {
for snapy in snap {
if let userimages = snapy.value as? Dictionary<String, Any> {
let author = userimages["author"] as? String
if author! == self.uid! {
let images = userimages["imageurl"] as? String
self.userposts.append(images!)
}
}
}
}
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let userImages = userposts[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.fillCells(uid: uid!, userPost: userImages)
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userposts.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selecteditem : String!
selecteditem = userposts[indexPath.row]
performSegue(withIdentifier: "lol", sender: selecteditem)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "lol" {
if let detailvc = segue.destination as? PhotoDetailVC {
if let bro = sender as? String {
detailvc.image = bro
}
}
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
return view
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (collectionView.bounds.size.width/3) - 1
print(width)
let size = CGSize(width: width, height: width)
return size
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
To solve your problem, you should use a pattern called delegate.
Delegate means that you need something to do the work of perform a segue for your HeaderView instead, something that can do it, in this case your ProfileVC.
1 - Create a protocol inside your HeaderView or another file, it's your call.
2 - Add a protocol variable type in your HeaderView as well and pass it from your viewController.
class ProfileHeader: UICollectionReusableView, FloatyDelegate {
#IBOutlet weak var pname: UILabel!
#IBOutlet weak var pusername: UILabel!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var userDesc: UILabel!
#IBOutlet weak var allviews: UILabel!
#IBOutlet weak var allphotos: UILabel!
var user : User!
var userposts = [String]()
var currentViewUser: String!
var floaty = Floaty()
var delegate: HeaderViewDelegate!
let uid = KeychainWrapper.standard.string(forKey: KEY_UID)
override func awakeFromNib() {
super.awakeFromNib()
user = User()
fetchCurrentUser()
profilePic.addBlackGradientLayer(frame: profilePic.bounds)
layoutFAB()
}
func setDelegate(delegate: HeaderViewDelegate) {
self.delegate = delegate
}
func layoutFAB() {
floaty.openAnimationType = .slideDown
floaty.hasShadow = false
floaty.addItem("Edit Profile", icon: UIImage(named: "")) { item in
delegate.fabItemClicked()
}
floaty.paddingY = (frame.height - 50) - floaty.frame.height/2
floaty.fabDelegate = self
floaty.buttonColor = UIColor.white
floaty.hasShadow = true
floaty.size = 45
addSubview(floaty)
}
func fetchCurrentUser(){
if uid != nil {
FBDataservice.ds.REF_CURR_USER.observeSingleEvent(of: .value, with: { (snapshot) in
if let allData = snapshot.value as? Dictionary<String, Any> {
if let cred = allData["credentials"] as? Dictionary<String, Any> {
let user = User(userid: snapshot.key, userData: cred)
self.pusername.text = user.username
self.pname.text = user.name
self.userDesc.text = user.aboutme
self.allphotos.text = String(user.photos)
self.allviews.text = String(user.views)
if user.userPic != nil {
let request = URL(string: user.userPic)
Nuke.loadImage(with: request!, into: self.profilePic)
} else {
return
}
}
}
})
}
}
public protocol HeaderViewDelegate {
func fabItemClicked()
}
}
3 - Finally, edit your ProfileVC to implement the HeaderViewDelegate protocol and pass it to your HeaderView
class ProfileVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, HeaderViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
var user : User!
var userposts = [String]()
var post = [Posts]()
var currentViewUser: String!
var imagePicker: UIImagePickerController!
var fetcher: Fetcher!
var imageFromImagePicker = UIImage()
let uid = KeychainWrapper.standard.string(forKey: KEY_UID)
override func viewDidLoad() {
super.viewDidLoad()
user = User()
fetcher = Fetcher()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
collectionView.delegate = self
collectionView.dataSource = self
initializeUserPost()
let nib = UINib(nibName: "ProfileCell", bundle: nil)
collectionView.register(nib, forCellWithReuseIdentifier: "ProfileCell")
}
//Method from the new protocol
func fabItemClicked(){
//Perform your segue here.
}
func editProfileTapped() {
performSegue(withIdentifier: "manageconnections", sender: nil)
}
#IBAction func manageConnections(_ sender: Any) {
performSegue(withIdentifier: "manageconnections", sender: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
collectionView.reloadData()
}
#IBAction func gotoSettings(_ sender: Any) {
performSegue(withIdentifier: "openSettings", sender: nil)
}
#IBAction func newPost(_ sender: Any) {
uploadNewPost()
}
#IBAction func backToFeed(_ sender: Any) {
performSegue(withIdentifier: "feedroute", sender: nil)
}
#IBAction func searchUsers(_ sender: Any) {
performSegue(withIdentifier: "searchNow", sender: nil)
}
func initializeUserPost() {
FBDataservice.ds.REF_POSTS.observe(.value, with: { (snapshot) in
if let snap = snapshot.value as? Dictionary<String, Any> {
for snapy in snap {
if let userimages = snapy.value as? Dictionary<String, Any> {
let author = userimages["author"] as? String
if author! == self.uid! {
let images = userimages["imageurl"] as? String
self.userposts.append(images!)
}
}
}
}
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let userImages = userposts[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.fillCells(uid: uid!, userPost: userImages)
return cell
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userposts.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selecteditem : String!
selecteditem = userposts[indexPath.row]
performSegue(withIdentifier: "lol", sender: selecteditem)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "lol" {
if let detailvc = segue.destination as? PhotoDetailVC {
if let bro = sender as? String {
detailvc.image = bro
}
}
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
view.delegate = self
return view
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (collectionView.bounds.size.width/3) - 1
print(width)
let size = CGSize(width: width, height: width)
return size
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
Don't forget to edit this method and pass self to your HeaderView:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "ProfileHeader", for: indexPath) as! ProfileHeader
view.delegate = self
return view
}
I'am using a UICollectionView to download and display Images from Backendless Database , How can I display these Images again in a ViewController that contain ImageView when I tap on any row of My CollectionView using Swift3 .
This is My CollectionView.
import UIKit
import SDWebImage
class GallaryCollectionViewController: UICollectionViewController {
var GallaryArray = [TestTable]()
let backendless = Backendless()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
loaddatawithquery()
}
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return GallaryArray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? GallaryCell {
let ImgURL = URL(string : self.GallaryArray[(indexPath as NSIndexPath).row].ImgURL!)
cell.GallImag.sd_setImage(with: ImgURL)
cell.ShowImg = {
if let myimage = (cell.GallImag.image) {
// Error here How to complete the code ?
}
}
return cell
}
else {
let cell = GallaryCell()
let ImgURL = URL(string : self.GallaryArray [(indexPath as NSIndexPath).row].ImgURL)
cell.GallImag.sd_setImage(with: ImgURL)
cell.ShowImg = {
if let myimage = (cell.GallImag.image) {
}
}
return cell
}
}
func loaddatawithquery() {
let dataQuery = BackendlessDataQuery()
dataQuery.queryOptions.pageSize = 50
backendless.data.of(TestTable.ofClass()).find(dataQuery,response: {( result: BackendlessCollection?) -> Void in
let data = result?.getCurrentPage()
for obj in data! as! [TestTable] {
self.GallaryArray.append(obj)
self.collectionView?.reloadData()
}
}, error: { (fault: Fault?) -> Void in
let alert = UIAlertController(title: "انتباه", message:"يرجى الاتصال بالانترنيت", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in })
self.present(alert, animated: true){}
})
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {}
}
And this is My Cell.
import UIKit
class GallaryCell: UICollectionViewCell {
#IBOutlet weak var GallImag: UIImageView!
var ShowImg : (() ->Void)?
func setSelected(_ selected: Bool, animated: Bool) {
setSelected(selected, animated: animated)
self.ShowImg!()
}
}
I'm going to assume you have your images loading correctly in the collection view.
there is a delegate method you can use called didSelectRow...
func collectionView(_ collectionView: UICollectionView, didSelectRowAt indexPath: IndexPath) {
self.passingTestTable = self.GallaryArray[indexPath.row]
self.performSegue(withIdentifier: "segue for new view controller", sender: nil)
}
self.passingTestTable is another property you create globally at the top of TestTable() (this is how I do it, some may choose to create the instance inside the didSelectRow
the other thing you'll need to do is create an instance of TestTable on the receiving viewController (i.e self.receivedTestTable )
in prepare for segue you can select the item selected and send it over to the new viewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "yourSegueName" {
if let controller = segue.destination as? PassedImageDetailViewController {
controller.receivedTestTable = self.passingTestTable
}
else {
print("Your segue identifier is incorrect")
}
}
}
once you've done that, the detail View Controller has access to the image data and you can display in in an image view on that screen.
I used SDWEBIMAGE to display images in a UICollectionView from an API. Now, When the user taps on the image in a collectionview, i want to open the image in the next viewcontroller. I am able to display the title in the next View, but couldn't display the image because i want not able to assign it at UIImage. I am using swift.
can anyone please suggest me a way on how to do it.
import UIKit
import SDWebImage
private let reuseIdentifier = "Celll"
var titles = [String]()
var imagecollection = [String]()
class CollectionViewController: UICollectionViewController,
UICollectionViewDelegateFlowLayout {
let sectioninserts = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
var titles = [String]()
var imagecollection = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "https://api.myjson.com/bins/537mf")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
print("error")
}else {
if let urlcontent = data {
do {
let jsoncontent = try NSJSONSerialization.JSONObjectWithData(urlcontent, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
// print(jsoncontent)
if jsoncontent.count > 0 {
let items = jsoncontent["items"] as! NSArray
for item in items as! [[String:String]]{
self.imagecollection.append(item["media"]!)
print(self.imagecollection)
self.titles.append(item["title"]!)
print(self.titles)
}
dispatch_async(dispatch_get_main_queue(), {
self.collectionView?.reloadData()
})
}
} catch {}
}
}
}
task.resume()
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return imagecollection.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell
cell.titleee.text = self.titles[indexPath.row]
let imagestring = imagecollection[indexPath.row]
let imageurl = NSURL(string: imagestring)
cell.disp.sd_setImageWithURL(imageurl, placeholderImage: UIImage(named: "loading.gif"), options: SDWebImageOptions.ProgressiveDownload, completed: nil)
return cell
}
func collectionView(collectionView: UICollectionView!,
layout collectionViewLayout: UICollectionViewLayout!,
sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize {
return CGSize(width: 170, height: 300)
}
func collectionView(collectionView: UICollectionView!,
layout collectionViewLayout: UICollectionViewLayout!,
insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return sectioninserts
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detail" {
let cell = sender as! CollectionViewCell
let indexPath = collectionView?.indexPathForCell(cell)
let vc = segue.destinationViewController as! DetailViewController
vc.label = self.titles[indexPath!.row]
enter code here**
Step-1
on that DetailViewController create the another one String like MediaStr
class DetailViewController: UIViewController {
var MediaStr: String
var label: String
override func viewDidLoad() {
super.viewDidLoad()
print (MediaStr)
}
}
Step-2
on your first VC Call Direclt like
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detail" {
let cell = sender as! CollectionViewCell
let indexPath = collectionView?.indexPathForCell(cell)
let vc = segue.destinationViewController as! DetailViewController
vc.label = self.titles[indexPath!.row]
// add the folloing line
vc.MediaStr = self. imagecollection[indexPath!.row]
}
Step-3
for image loading purpose
import SDWebImage
class DetailViewController: UIViewController {
var MediaStr: String
var label: String
override func viewDidLoad() {
super.viewDidLoad()
print (MediaStr)
if let imagestring = MediaStr
{
yourImageViewName_setImageWithURL(NSURL(string: imagestring), placeholderImage: UIImage(named: "loading.gif"), options: SDWebImageOptions.ProgressiveDownload, completed: nil)
}
}
}