here is my stack view code where I had got this code from apple developer site in this rating control was manually giving but I am having the data coming from web services how to pass to the rating control to display the stars as got from the web services can anyone help me ?
var number = 0
private var ratingButtons = [UIButton]()
var rating = 0 {
didSet {
updateButtonSelectionStates()
}
}
#IBInspectable var starSize: CGSize = CGSize(width: 20.0, height: 10.0) {
didSet {
setupButtons()
}
}
#IBInspectable var starCount: Int = 5 {
didSet {
setupButtons()
}
}
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupButtons()
}
required init(coder: NSCoder) {
super.init(coder: coder)
setupButtons()
}
//MARK: Button Action
func ratingButtonTapped(button: UIButton) {
guard let index = ratingButtons.index(of: button) else {
fatalError("The button, \(button), is not in the ratingButtons array: \(ratingButtons)")
}
// Calculate the rating of the selected button
let selectedRating = index + 1
if selectedRating == rating {
// If the selected star represents the current rating, reset the rating to 0.
rating = 0
} else {
// Otherwise set the rating to the selected star
rating = selectedRating
}
}
//MARK: Private Methods
private func setupButtons() {
// Clear any existing buttons
for button in ratingButtons {
removeArrangedSubview(button)
button.removeFromSuperview()
}
ratingButtons.removeAll()
// Load Button Images
let bundle = Bundle(for: type(of: self))
let filledStar = UIImage(named: "filledStar", in: bundle, compatibleWith: self.traitCollection)
let emptyStar = UIImage(named:"emptyStar", in: bundle, compatibleWith: self.traitCollection)
for index in 0..<starCount {
// Create the button
let button = UIButton()
// Set the button images
button.setImage(emptyStar, for: .normal)
button.setImage(filledStar, for: .selected)
// Add constraints
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: starSize.height).isActive = true
button.widthAnchor.constraint(equalToConstant: starSize.width).isActive = true
// Set the accessibility label
button.accessibilityLabel = "Set \(index + 1) star rating"
button.isUserInteractionEnabled = true
// Setup the button action
button.addTarget(self, action: #selector(starRatingControl.ratingButtonTapped(button:)), for: .touchUpInside)
// Add the button to the stack
addArrangedSubview(button)
// Add the new button to the rating button array
ratingButtons.append(button)
}
updateButtonSelectionStates()
}
private func updateButtonSelectionStates() {
for (index, button) in ratingButtons.enumerated() {
// If the index of a button is less than the rating, that button should be selected.
button.isSelected = index < rating
// Set accessibility hint and value
let hintString: String?
if rating == index + 1 {
hintString = "Tap to reset the rating to zero."
} else {
hintString = nil
}
let valueString: String
switch (rating) {
case 0:
valueString = "No rating set."
case 1:
valueString = "1 star set."
default:
valueString = "\(rating) stars set."
}
button.accessibilityHint = hintString
button.accessibilityValue = valueString
}
}
this is my json response where I am getting the data from url in view controller
func downloadJsonWithURL() {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
if let detailsArray = jsonObj!.value(forKey: "Detail") as? NSArray {
for item in detailsArray {
if let detailDict = item as? NSDictionary {
if let name = detailDict.value(forKey: "productName") {
self.productName.append(name as! String)
}
if let image1 = detailDict.value(forKey: "image1"){
self.imageArray.append(image1 as! String)
}
if let image2 = detailDict.value(forKey: "image2"){
self.imageArray.append(image2 as! String)
}
if let image3 = detailDict.value(forKey: "image3"){
self.imageArray.append(image3 as! String)
}
if let image4 = detailDict.value(forKey: "image4"){
self.imageArray.append(image4 as! String)
}
if let image5 = detailDict.value(forKey: "image5"){
self.imageArray.append(image5 as! String)
}
if let image6 = detailDict.value(forKey: "image6"){
self.imageArray.append(image6 as! String)
}
if let image7 = detailDict.value(forKey: "image7"){
self.imageArray.append(image7 as! String)
}
if let image8 = detailDict.value(forKey: "image8"){
self.imageArray.append(image8 as! String)
}
if let image9 = detailDict.value(forKey: "image9"){
self.imageArray.append(image9 as! String)
}
if let image10 = detailDict.value(forKey: "image10"){
self.imageArray.append(image10 as! String)
}
if let price = detailDict.value(forKey: "productPrice") {
self.productprice.append(price as! String)
}
if let image = detailDict.value(forKey: "img"){
self.imagesArray.append(image as! String)
}
if let review = detailDict.value(forKey: "productReview"){
self.reviewArray.append(review as! Int)
}
}
}
}
OperationQueue.main.addOperation({
self.navigationBar.topItem?.title = self.productName[0]
self.priceLabel?.text = self.productprice[0]
self.nameLabel?.text = self.productName[0]
let x = self.reviewArray[0]
var mystring = String(x) + " Reviews"
self.reviewLabel.text = mystring
let star = starRatingControl()
star.isUserInteractionEnabled = false
star.rating = self.reviewArray[0]
print(star.rating)
self.view.addSubview(star)
let imgURL = NSURL(string:self.imageArray[0])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
self.collectionView.reloadData()
})
}
}).resume()
}
Related
There are users being downloaded from firebase and displayed on a UITableView where the cells are selectable and once selected will have a check mark. So from firebase is it is asynchronously downloaded so I think this could be the start of me solving the problem but not sure. When selecting lets say two cells when the view appears and then you begin scrolling through the list other cells will appear to be selected when the user did not select them. Below will be code and pictures of the occurrence.
Firebase Call
func getTableViewData() {
Database.database().reference().child("Businesses").queryOrdered(byChild: "businessName").observe(.childAdded, with: { (snapshot) in
let key = snapshot.key
if(key == self.loggedInUser?.uid) {
print("Same as logged in user, so don't show!")
} else {
if let locationValue = snapshot.value as? [String: AnyObject] {
let lat = Double(locationValue["businessLatitude"] as! String)
let long = Double(locationValue["businessLongitude"] as! String)
let businessLocation = CLLocation(latitude: lat!, longitude: long!)
let latitude = self.locationManager.location?.coordinate.latitude
let longitude = self.locationManager.location?.coordinate.longitude
let userLocation = CLLocation(latitude: latitude!, longitude: longitude!)
let distanceInMeters: Double = userLocation.distance(from: businessLocation)
let distanceInMiles: Double = distanceInMeters * 0.00062137
let distanceLabelText = String(format: "%.2f miles away", distanceInMiles)
var singleChildDictionary = locationValue
singleChildDictionary["distanceLabelText"] = distanceLabelText as AnyObject
singleChildDictionary["distanceInMiles"] = distanceInMiles as AnyObject
self.usersArray.append(singleChildDictionary as NSDictionary)
self.usersArray = self.usersArray.sorted {
!($0?["distanceInMiles"] as! Double > $1?["distanceInMiles"] as! Double)
}
}
//insert the rows
//self.followUsersTableView.insertRows(at: [IndexPath(row:self.usersArray.count-1,section:0)], with: UITableViewRowAnimation.automatic)
self.listedBusiness.reloadData()
}
}) { (error) in
print(error.localizedDescription)
}
}
TableView Setup
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != ""{
return filteredUsers.count
}
return self.usersArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomerAddSelectedBusinessesCell
var user : NSDictionary?
if searchController.isActive && searchController.searchBar.text != ""{
user = filteredUsers[indexPath.row]
} else {
user = self.usersArray[indexPath.row]
}
if cell.isSelected == true {
var user = self.usersArray[indexPath.row]
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
print("No access")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
//cell.selectedCell.image = UIImage(named: "cellSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
//cell.profileImage.image =
//cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
print("****Called")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
//cell.selectedCell.image = UIImage(named: "cellSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
print("Location services are not enabled")
}
} else if cell.isSelected == false {
var user = self.usersArray[indexPath.row]
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
print("No access")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
//cell.selectedCell.image = UIImage(named: "cellNotSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
//cell.profileImage.image =
//cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
print("%called")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
//cell.selectedCell.image = UIImage(named: "cellNotSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
print("Location services are not enabled")
}
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomerAddSelectedBusinessesCell
let user = usersArray[indexPath.row]
let name = user!["uid"] as? String
var NSdata = NSDictionary()
var realArray = [NSDictionary]()
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
if cell.accessoryType == .checkmark{
cell.accessoryType = .none
print("Deleted \(name!)")
if let idx = data.index(of:name!) {
data.remove(at: idx)
print(data)
}
} else {
cell.accessoryType = .checkmark
data.append(name!)
print(data)
}
}
print(data)
}
Selected Cells after view loads
Cells that appear to selected but are not
It's most common cell reusable issue. Cells which are visible to screen will be reused when you scroll.
Eg. You've 5 cells visible. when you select 2,3 and scroll down 7,8 will be selected.
To avoid this you've 2 options.
You can use external Bool array to manage this(Bool array count must be same as your array count).
You can put bool variable in your user dictionary to manage that.
So whenever your scroll, newly visible cell will not selected automatically.
Using Segmented control with firebase is not selecting the accurate document when performing the action using the table cell button.
I am using segmented control with tableview in Swift IOS and Firestore database,
I am able to load the documents from database as per the segment control requirement. but when I tap on the button of the table cell it is processing action only on one document, not the accurate one, how should I ensure that table cell button process the document related to that particular id of the document only, below is the code I am sharing
class IPViewController: UIViewController {
#IBOutlet var segmentControl:UISegmentedControl!
#IBOutlet var tableView: UITableView!
var pendingPost:[Pending] = []
var completedPost:[Completed] = []
var postKey:String = ""
var db: Firestore!
var postAuthorId:String = ""
var postAuthorname:String = ""
var PostTitle:String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
// Do any additional setup after loading the view.
retrieveAllPosts()
}
func retrieveAllPosts(){
let postsRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("Detaling2").limit(to: 50)
postsRef.addSnapshotListener { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let newSourse = Pending(_documentId: document.documentID, _username: username, _postTitle: postTitle, _postcategory: postcategory)
self.pendingPost.append(newSourse)
}
self.tableView.reloadData()
}
}
}
}
func retrieveAllPosts2(){
let postsRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("Detailing1").limit(to: 50)
postsRef.addSnapshotListener { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
//self.postKey = document.documentID
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let newSourse1 = Completed(_documentId: document.documentID, _username: username, _postTitle: postTitle)
self.completedPost.append(newSourse1)
}
self.tableView.reloadData()
}
}
}
}
#IBAction func indexChanged(_ sender: UISegmentedControl) {
switch segmentControl.selectedSegmentIndex
{
case 0:
self.pendingPost.removeAll()
retrieveAllPosts()
case 1:
self.completedPost.removeAll()
retrieveAllPosts2()
default:
break
}
//self.tableView.reloadData()
}
#objc func toComments(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! CommentListViewController
vc.postId = postKey
}
#objc func favupdate(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
//print(postKey + "hello777777")
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("marked_posts").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
self.postContent = document.get("postContent") as! String
self.postAuthorEmail = document.get("post_author_email") as! String
self.postCategory = document.get("postcategory") as! String
self.postAuthorfullname = document.get("post_author_fullname") as! String
self.postAuthorGender = document.get("post_author_gender") as! String
self.postAuthorPicUrl = document.get("post_user_profile_pic_url") as! String
// let l11:Bool = document.get("l1") as! Bool
// self.postTimeStamp = document.get("post_timeStamp") as! String
self.postAuthorSpinnerC = document.get("post_author_spinnerC") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
#objc func favupdate1(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = completedPost[commentbutton.tag]
postKey = post._documentId
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("details1").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
}
extension IPViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var value = 0
switch segmentControl.selectedSegmentIndex{
case 0:
value = pendingPost.count
break
case 1:
value = completedPost.count
break
default:
break
}
return value
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ipwcell", for: indexPath) as! IPWCELL
switch segmentControl.selectedSegmentIndex{
case 0:
cell.pending1 = pendingPost[indexPath.row]
cell.commentbuttonIp.tag = indexPath.row
cell.commentbuttonIp.addTarget(self, action: #selector(toComments(_:)), for: .touchUpInside)
cell.favoritebutton1.addTarget(self, action: #selector(favupdate(_:)), for: .touchUpInside)
break
case 1:
cell.completed1 = completedPost[indexPath.row]
cell.commentbuttonIp.tag = indexPath.row
cell.commentbuttonIp.addTarget(self, action: #selector(toComments(_:)), for: .touchUpInside)
cell.favoritebutton1.addTarget(self, action: #selector(favupdate1(_:)), for: .touchUpInside)
break
default:
break
}
return cell
}
}
#objc func favupdate(_ sender: AnyObject) {
if segmentView.selectedSegmentIndex == 0 {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
//print(postKey + "hello777777")
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("marked_posts").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
self.postContent = document.get("postContent") as! String
self.postAuthorEmail = document.get("post_author_email") as! String
self.postCategory = document.get("postcategory") as! String
self.postAuthorfullname = document.get("post_author_fullname") as! String
self.postAuthorGender = document.get("post_author_gender") as! String
self.postAuthorPicUrl = document.get("post_user_profile_pic_url") as! String
// let l11:Bool = document.get("l1") as! Bool
// self.postTimeStamp = document.get("post_timeStamp") as! String
self.postAuthorSpinnerC = document.get("post_author_spinnerC") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}else {
let commentbutton = sender as! UIButton
let post = completedPost[commentbutton.tag]
postKey = post._documentId
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("details1").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
}
let postObject = [
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"postTitle": self.PostTitle
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
}
#objc func toComments(_ sender: AnyObject) {
if segmentView.selectedSegmentIndex == 0 {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}else {
let commentbutton = sender as! UIButton
let post = pendingPost[commentbutton.tag]
postKey = post._documentId // or what key value it is
print("hello")
performSegue(withIdentifier: "IPtoComments", sender: self)
}
}
This question already has an answer here:
I am getting data from json web services but unable to display it on my ui
(1 answer)
Closed 5 years ago.
here I tried to implement the collection view but unable to do it and on scroll view I had placed the collection view is it correct to implement like this if not can u provide any solution for this to display on ui and
in this scroll view has implemented on view and all the elements are placed on it here is my code and how to zoom a selected particular image also can anyone help me ?
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var navigationBar: UINavigationBar!
#IBOutlet var imageView: UIImageView!
#IBOutlet var pageControl: UIPageControl!
#IBOutlet var nameLabel: UILabel!
#IBOutlet var priceLabel: UILabel!
#IBOutlet var textview: UITextView!
#IBOutlet var scrollView: UIScrollView!
var productName = [String]()
var productprice = [String]()
var productdescription :String?
var thumbnailimageArray = [String]()
var imageArray = [String]()
var pageIndex: Int = 0
var imagesArray = [String]()
let urlString = "http://www.json-generator.com/api/json/get/cjpberBhKa?indent=2"
override func viewDidLoad() {
super.viewDidLoad()
self.downloadJsonWithURL()
collectionView.delegate = self
collectionView.dataSource = self
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiped(gesture:)))
swipeLeft.direction = .left
self.imageView.addGestureRecognizer(swipeLeft)
swipeLeft.cancelsTouchesInView = false
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiped(gesture:)))
swipeRight.direction = .right
self.imageView.addGestureRecognizer(swipeRight)
swipeRight.cancelsTouchesInView = false
imageView.isUserInteractionEnabled = true
// Do any additional setup after loading the view.
}
func downloadJsonWithURL() {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
print(jsonObj!.value(forKey: "Detail")!)
if let detailsArray = jsonObj!.value(forKey: "Detail") as? NSArray {
if let detailDict = detailsArray[0] as? NSDictionary {
if let name = detailDict.value(forKey: "productName") {
self.productName.append(name as! String)
}
if let image1 = detailDict.value(forKey: "image1"){
self.imageArray.append(image1 as! String)
}
if let image2 = detailDict.value(forKey: "image2"){
self.imageArray.append(image2 as! String)
}
if let image3 = detailDict.value(forKey: "image3"){
self.imageArray.append(image3 as! String)
}
if let image4 = detailDict.value(forKey: "image4"){
self.imageArray.append(image4 as! String)
}
if let image5 = detailDict.value(forKey: "image5"){
self.imageArray.append(image5 as! String)
}
if let image6 = detailDict.value(forKey: "image6"){
self.imageArray.append(image6 as! String)
}
if let image7 = detailDict.value(forKey: "image7"){
self.imageArray.append(image7 as! String)
}
if let image8 = detailDict.value(forKey: "image8"){
self.imageArray.append(image8 as! String)
}
if let image9 = detailDict.value(forKey: "image9"){
self.imageArray.append(image9 as! String)
}
if let image10 = detailDict.value(forKey: "image10"){
self.imageArray.append(image10 as! String)
}
if let price = detailDict.value(forKey: "productPrice") {
self.productprice.append(price as! String)
}
if let description = detailDict.value(forKey: "productDes") {
self.productdescription = description as? String
}
if let image = detailDict.value(forKey: "img"){
self.imagesArray.append(image as! String)
}
}
}
OperationQueue.main.addOperation({
self.navigationBar.topItem?.title = self.productName[0]
self.textview.text = self.productdescription
self.priceLabel.text = self.productprice[0]
self.nameLabel.text = self.productName[0]
print(self.imageArray)
let imgURL = NSURL(string:self.imageArray[0])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
})
}
}).resume()
}
func swiped(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.right :
if pageIndex == 0 {
}else{
pageIndex -= 1
}
let imgURL = NSURL(string:self.imageArray[pageIndex])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
pageControl.numberOfPages = imageArray.count
pageControl.currentPage = pageIndex
case UISwipeGestureRecognizerDirection.left:
if pageIndex >= imageArray.count-1{
}else{
pageIndex += 1
}
let imgURL = NSURL(string:self.imageArray[pageIndex])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
pageControl.numberOfPages = imageArray.count
pageControl.currentPage = pageIndex
default:
break
}
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell",for:indexPath) as! DetailsCell
let arr = imagesArray[indexPath.row]
let urls = NSURL(string: arr)
let data = NSData (contentsOf: urls! as URL)
cell.imageView.image = UIImage(data: data! as Data)
cell.nameLabel.text = self.productName[indexPath.row]
cell.priceLabel.text = self.productprice[indexPath.row]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 0.7
return cell
}
reload your collection view after you fetch all the data from the web service response like below.
collectionView.reloadData()
You need reload data of collectionview after downloadJsonWithURL loaded.
here I am having problem that I am able to get the data from json web services but unable to display on my ui in the program I mentioned where I am getting error and what it is also mentioned there can anyone help me ?
class DetailsViewController: UIPageViewController{
#IBOutlet var navigationBar: UINavigationBar!
#IBOutlet var imageView: UIImageView!
#IBOutlet var pageControl: UIPageControl!
#IBOutlet var nameLabel: UILabel!
#IBOutlet var priceLabel: UILabel!
#IBOutlet var textview: UITextView!
var productName :String?
var productprice :String?
var productdescription :String?
var thumbnailimageArray = [String]()
var imageArray = [String]()
var pageIndex: Int = 0
let urlString = "http://www.json-generator.com/api/json/get/cjpberBhKa?indent=2"
override func viewDidLoad() {
super.viewDidLoad()
self.downloadJsonWithURL()
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiped))
swipeLeft.direction = .left
self.imageView.addGestureRecognizer(swipeLeft) //unexpectely found nil while unwrapping an optional value
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiped))
swipeRight.direction = .right
self.imageView.addGestureRecognizer(swipeRight)
imageView.isUserInteractionEnabled = true
pageControl.numberOfPages = imageArray.count
pageControl.currentPage = pageIndex
// Do any additional setup after loading the view.
}
func downloadJsonWithURL() {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
print(jsonObj!.value(forKey: "Detail")!)
if let detailsArray = jsonObj!.value(forKey: "Detail") as? NSArray {
if let detailDict = detailsArray[0] as? NSDictionary {
if let name = detailDict.value(forKey: "productName") {
self.productName = name as? String
}
if let image1 = detailDict.value(forKey: "image1"){
self.imageArray.append(image1 as! String)
}
if let image2 = detailDict.value(forKey: "image2"){
self.imageArray.append(image2 as! String)
}
if let image3 = detailDict.value(forKey: "image3"){
self.imageArray.append(image3 as! String)
}
if let image4 = detailDict.value(forKey: "image4"){
self.imageArray.append(image4 as! String)
}
if let image5 = detailDict.value(forKey: "image5"){
self.imageArray.append(image5 as! String)
}
if let image6 = detailDict.value(forKey: "image6"){
self.imageArray.append(image6 as! String)
}
if let image7 = detailDict.value(forKey: "image7"){
self.imageArray.append(image7 as! String)
}
if let image8 = detailDict.value(forKey: "image8"){
self.imageArray.append(image8 as! String)
}
if let image9 = detailDict.value(forKey: "image9"){
self.imageArray.append(image9 as! String)
}
if let image10 = detailDict.value(forKey: "image10"){
self.imageArray.append(image10 as! String)
}
if let price = detailDict.value(forKey: "productPrice") {
self.productprice = price as? String
}
if let description = detailDict.value(forKey: "productDes") {
self.productdescription = description as? String
}
}
}
OperationQueue.main.addOperation({
self.navigationBar.topItem?.title = self.productName
self.textview.text = self.productdescription
self.priceLabel.text = self.productprice
print(self.imageArray)
let imgURL = NSURL(string:self.imageArray[0])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
})
}
}).resume()
}
func swiped(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.right :
if pageIndex == 0 {
}else{
pageIndex -= 1
}
imageView.image = UIImage(named: imageArray[pageIndex])
case UISwipeGestureRecognizerDirection.left:
if pageIndex >= imageArray.count-1{
}else{
pageIndex += 1
}
imageView.image = UIImage(named: imageArray[pageIndex])
default:
break
}
}
}
what you are using to display image in func swiped(gesture: UIGestureRecognizer) method execution is as below
imageView.image = UIImage(named: imageArray[pageIndex])
but your image is comping from the server so you just need to display all images of your product is as you displayed first in OperationQueue.main.addOperation so in place of displaying image using UIImage(named: imageArray[pageIndex]) you need to convert it to data and display it to imageview and your modified func swiped(gesture: UIGestureRecognizer) may look like as below
func swiped(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.right :
if pageIndex == 0 {
}else{
pageIndex -= 1
}
let imgURL = NSURL(string:self.imageArray[pageIndex])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
case UISwipeGestureRecognizerDirection.left:
if pageIndex >= imageArray.count-1{
}else{
pageIndex += 1
}
let imgURL = NSURL(string:self.imageArray[pageIndex])
let data = NSData(contentsOf: (imgURL as URL?)!)
self.imageView.image = UIImage(data: data! as Data)
default:
break
}
}
}
I'm working with a collectionView right now and when I activate the refresh control, it adds a duplicate picture to the data source set for every picture in the set, and then makes it disappear and things go back to normal by the time the refresh control is done. Here's a YouTube video I uploaded to clearly show you what is going on.
https://youtu.be/Q9ZFd-7tSRw
It would seem logical that the data source set would be getting the same data from the API I am using, then displaying it, the duplicate data then getting deleting from the array, and then the collection view being reloaded once more before the refresh control goes away. That's not how I want it to work obviously, but perhaps I have coded it wrong.
viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)
self.cellLoadingIndicator.backgroundColor = goldenWordsYellow
self.cellLoadingIndicator.hidesWhenStopped = true
if self.revealViewController() != nil {
revealViewControllerIndicator = 1
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.revealViewController().rearViewRevealWidth = 280
collectionView!.delegate = self
collectionView!.dataSource = self
goldenWordsRefreshControl = UIRefreshControl()
goldenWordsRefreshControl.backgroundColor = goldenWordsYellow
goldenWordsRefreshControl.tintColor = UIColor.whiteColor()
self.collectionView!.addSubview(goldenWordsRefreshControl)
navigationController?.setNavigationBarHidden(false, animated: true)
navigationItem.title = "Pictures"
setupView()
populatePhotos()
self.dateFormatter.dateFormat = "dd/MM/yy"
self.cellLoadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
self.cellLoadingIndicator.color = goldenWordsYellow
self.cellLoadingIndicator.center = (self.collectionView?.center)!
self.collectionView!.addSubview(cellLoadingIndicator)
self.collectionView!.bringSubviewToFront(cellLoadingIndicator)
/*
self.dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
self.dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
let currentDateAndTime = NSDate()
let updateString = "Last updated at " + self.dateFormatter.stringFromDate(currentDateAndTime)
self.goldenWordsRefreshControl.attributedTitle = NSAttributedString(string: updateString)
*/
}
populatePhotos:
func populatePhotos() {
if populatingPhotos {
return
}
populatingPhotos = true
self.cellLoadingIndicator.startAnimating()
self.temporaryPictureObjects.removeAllObjects()
Alamofire.request(GWNetworking.Router.Pictures(self.currentPage)).responseJSON() { response in
if let JSON = response.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)) {
var nodeIDArray : [Int]
if (JSON .isKindOfClass(NSDictionary)) {
for node in JSON as! Dictionary<String, AnyObject> {
let nodeIDValue = node.0
var lastItem : Int = 0
self.nodeIDArray.addObject(nodeIDValue)
if let pictureElement : PictureElement = PictureElement(title: "Picture", nodeID: 0, timeStamp: 0, imageURL: "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png", author: "Staff", issueNumber: "Issue # error", volumeNumber: "Volume # error") {
pictureElement.title = node.1["title"] as! String
pictureElement.nodeID = Int(nodeIDValue)!
let timeStampString = node.1["revision_timestamp"] as! String
pictureElement.timeStamp = Int(timeStampString)!
if let imageURL = node.1["image_url"] as? String {
pictureElement.imageURL = imageURL
}
if let author = node.1["author"] as? String {
pictureElement.author = author
}
if let issueNumber = node.1["issue_int"] as? String {
pictureElement.issueNumber = issueNumber
}
if let volumeNumber = node.1["volume_int"] as? String {
pictureElement.volumeNumber = volumeNumber
}
lastItem = self.temporaryPictureObjects.count // Using a temporary set to not handle the dataSource set directly (safer).
self.temporaryPictureObjects.addObject(pictureElement)
let indexPaths = (lastItem..<self.temporaryPictureObjects.count).map { NSIndexPath(forItem: $0, inSection: 0) }
}
}
/* Sorting the elements in order of newest to oldest (as the array index increases] */
let timeStampSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
self.pictureObjects.sortUsingDescriptors([timeStampSortDescriptor])
}
dispatch_async(dispatch_get_main_queue()) {
self.pictureObjects = self.temporaryPictureObjects
self.collectionView!.reloadData()
self.cellLoadingIndicator.stopAnimating()
self.currentPage++
self.populatingPhotos = false
}
}
}
}
}
handleRefresh:
func handleRefresh() {
goldenWordsRefreshControl.beginRefreshing()
self.pictureObjects.removeAllObjects()
self.currentPage = 0
self.cellLoadingIndicator.startAnimating()
self.picturesCollectionView.bringSubviewToFront(cellLoadingIndicator)
self.populatingPhotos = false
populatePhotos()
self.cellLoadingIndicator.stopAnimating()
goldenWordsRefreshControl.endRefreshing()
}
cellForItemAtIndexPath:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoBrowserCellIdentifier, forIndexPath: indexPath) as! PhotoBrowserCollectionViewCell
if let pictureObject = pictureObjects.objectAtIndex(indexPath.row) as? PictureElement {
let title = pictureObject.title ?? "" // if pictureObject.title == nil, then we return an empty string
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(pictureObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = pictureObject.author ?? ""
let issueNumber = pictureObject.issueNumber ?? ""
let volumeNumber = pictureObject.volumeNumber ?? ""
let nodeID = pictureObject.nodeID ?? 0
let imageURL = pictureObject.imageURL ?? "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png"
cell.request?.cancel()
if let image = self.imageCache.objectForKey(imageURL) as? UIImage {
cell.imageView.image = image
} else {
cell.imageView.image = nil
cell.request = Alamofire.request(.GET, imageURL).responseImage() { response in
if let image = response.result.value {
self.imageCache.setObject(response.result.value!, forKey: imageURL)
if cell.imageView.image == nil {
cell.imageView.image = image
}
}
}
}
}
return cell
}