How to add a UICollectionView to a SpriteKit GameViewController - uiviewcontroller

I am trying to create a menu for my game that requires a number of effects that are part of the UICollectionView, so instead of reinventing the wheel, I am using a collection view which I got from YouTube video since it's close to what I want to achieve. My game begins with a posterScene which I load in the GameViewController, how can I replace my posterScene with my collectionView in MenuViewContoller?
Please checkout my code below:
MenuViewController:
class MenuViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .red
cv.dataSource = self
cv.delegate = self
cv.isPagingEnabled = true
return cv
}()
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
//use autolayout instead
collectionView.anchorToTop(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor)
collectionView.register(PageCell.self, forCellWithReuseIdentifier: cellId)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath as IndexPath)
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView {
func anchorToTop(top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil) {
anchorWithConstantsToTop(top: top, left: left, bottom: bottom, right: right, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0)
}
func anchorWithConstantsToTop(top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leftConstant: CGFloat = 0, bottomConstant: CGFloat = 0, rightConstant: CGFloat = 0) {
translatesAutoresizingMaskIntoConstraints = false
if let top = top {
topAnchor.constraint(equalTo: top, constant: topConstant).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant).isActive = true
}
if let left = left {
leftAnchor.constraint(equalTo: left, constant: leftConstant).isActive = true
}
if let right = right {
rightAnchor.constraint(equalTo: right, constant: -rightConstant).isActive = true
}
}
}
GameViewController:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let skView = self.view as? SKView
if skView?.scene == nil {
skView?.showsFPS = true
skView?.showsNodeCount = true
skView?.showsPhysics = false
skView?.ignoresSiblingOrder = false
//starting the game with the Poster Scene
let posterScene = PosterScene(size: skView!.bounds.size)
posterScene.scaleMode = .aspectFill
skView?.presentScene(posterScene)
}
override var shouldAutorotate : Bool {
return true
}
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return UIInterfaceOrientationMask.allButUpsideDown
} else {
return UIInterfaceOrientationMask.all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override var prefersStatusBarHidden : Bool {
return true
}
}
PosterScene
class PosterScene: SKScene {
override init(size: CGSize){
super.init(size: size)
//self.anchorPoint = CGPoint(x:0.5, y:0.5) //let's put 0,0 at the center of the screen
let posterImage = SKSpriteNode(imageNamed: "poster")
posterImage.position = CGPoint(x: self.frame.midX, y: self.frame.midY) //CGPoint(x:736/2, y:414/2)//CGPoint.zero
self.addChild(posterImage)
let sequence = SKAction.sequence([ SKAction.wait(forDuration: 3.0), SKAction.run({ self.changeToCollectionView() }) ])
self.run(sequence)
}
func changeToCollectionView () {
//code for changing to collection view goes here
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

Related

Tableview Pagination not working in swift

I have added tableview bottom pagination with json data
json response in postman:
"result": {
"page_count": 3,
"per_page": 10,
"post_count": 27,
"Payments": [
{
"id": 132,
"payment_response": null,
code: if i run this code then without scrolling the paymentsServiceCall() calling 4 times but table data showing only first 10 records, why? where am i wrong.
i need initially 10 cells to show on tableview then if i scroll then 10 more cells to load and so on. please guide me
class MyPaymentsViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
private var currentPage = 1
private var totalPages = 1
private var paymentsData = PaymentsHistoryModel(dictionary: NSDictionary()) {
didSet {
totalPages = paymentsData?.result?.page_count ?? 0
tableView.reloadData()
}
}
override func viewWillAppear(_ animated: Bool) {
currentPage = 1
paymentsServiceCall()
}
func paymentsServiceCall() {
let param = ["page_no": currentPage]
serviceCall(param: param, method: .post, url: CommonUrl.student_my_payments) { [weak self] (resp) in
if let _ = resp.dict?["result"] as? NSDictionary {
self?.paymentsData = PaymentsHistoryModel(dictionary: resp.dict as NSDictionary? ?? NSDictionary())
}
}
}
}
extension MyPaymentsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let totalPostCount = paymentsData?.result?.payments?.count
if indexPath.row == totalPostCount - 1, currentPage <= totalPages {
print("in refresh")
currentPage += 1
paymentsServiceCall()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
paymentsData?.result?.payments?.count ?? 0
}
}
Try Using This
class PaginationManager {
var isLoading = false
static let shared = PaginationManager()
private init() { } //Singleton
}
extension PaginationManager {
func isPaging(_ scrollView: UIScrollView) -> Bool {
let offset = scrollView.contentOffset
let bounds = scrollView.bounds
let size = scrollView.contentSize
let inset = scrollView.contentInset
let y = offset.y + bounds.size.height - inset.bottom
let h = size.height
let reload_distance: CGFloat = 100.0
if y > h - reload_distance && !isLoading {
return true
}
return false
}
func isPagingForTopScroll(_ scrollView: UIScrollView) -> Bool {
let offset = scrollView.contentOffset
_ = scrollView.bounds
let size = scrollView.contentSize
_ = scrollView.contentInset
let y = offset.y
_ = size.height
let reload_distance: CGFloat = 100.0
if y < reload_distance && !isLoading {
return true
}
return false
}
}
And for using it in Controller
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if PaginationManager.shared.isPaging(scrollView) {
if !(paymentsData?.result?.payments?.isEmpty ?? true), totalPages > paymentsData?.result?.payments?.count ?? 0 {
guard PaginationManager.shared.isLoading else { return }
track("######Loading: \(viewModel.isLoading)")
//Call your service to fetch new data with an updated page number below
}
}
}
After calling the service again check for appending the data in payments or if it is the first page then replace it with new data and inside the service response update the current page count by 1
You can also create isLoading var in your class if multiple service calls are there.

Open pdf in tableview from a json file

I am in a bind.
My regular developer has secured a full time gig, and I am trying to finish a project.
Literally stuck on the last line of code.....
I have a tableview that parses a json file to populate and open a pdf file when a row is selected.
I reworked the tableview in order to add a searchbar and associated code, which works when running the bundle.
I am, however, stuck with connecting the didSelectRow with the appropriate pdf file.
Can someone please lend a hand? Thanks
import UIKit
import WebKit
// Model
struct Section {
var section: String
var pdfs: [PDF]
}
struct PDF {
var code: String
var name: String
var airport: String
}
class PdfVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var tableViewLeft: NSLayoutConstraint!
#IBOutlet weak var btnMenuLeft: NSLayoutConstraint!
#IBOutlet weak var btnMenu: UIButton!
#IBOutlet weak var searchBar: UISearchBar!
//json
var jsonData: [Section] = []
var filtedJsonData: [Section] = []
//WebView
var fileName: String?
var isVideo: Bool = false
var btnMenuClose:UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
// Setup TableView
tableView.delegate = self
tableView.dataSource = self
setupData()
tableView.reloadData()
// Setup SearchBar
searchBar.delegate = self
// Setup WebView
if let fileName = fileName {
isVideo = fileName.contains(".mp4")
if let range = fileName.range(of: isVideo ? ".mp4" : ".pdf") {
self.fileName!.removeSubrange(range)
}
}
if let file = Bundle.main.url(forResource: fileName ?? "", withExtension: isVideo ? ".mp4" : ".pdf", subdirectory: nil, localization: nil) {
let request = URLRequest(url: file)
webView.load(request)
}
if let image = UIImage(named: "ico_close") {
navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(onWebTap))
//self.navigationItem.leftItemsSupplementBackButton = true
btnMenuClose = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(onWebTap))
self.navigationItem.rightBarButtonItems = [btnMenuClose!];
}
//navigationItem.title = "Airport Maps"
}
private func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc private func dismissKeyboard() {
view.endEditing(true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
// title color to white
let titleTextAttributed: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white, .font: UIFont(name: "HelveticaNeue-Light", size: 20) as Any]
self.navigationController?.navigationBar.titleTextAttributes = titleTextAttributed
// back arrow white
self.navigationController?.navigationBar.tintColor = UIColor.white
// blueish navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0.00, green: 0.54, blue: 0.92, alpha: 1.00)
self.navigationController?.navigationBar.isTranslucent = false
showMenu(false, animated: false)
}
private func setupData() {
// Parse data from local json file
if let path = Bundle.main.path(forResource: "airports", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? [Dictionary<String, String>] {
for result in jsonResult {
if !jsonData.contains(where: { $0.section == result["Section"] }) {
let section = Section(section: result["Section"] ?? "", pdfs: [])
jsonData.append(section)
}
let pdf = PDF(code: result["Code"] ?? "", name: result["Filename"] ?? "", airport: result["Name"] ?? "")
let index = jsonData.firstIndex(where: { $0.section == result["Section"] })
if let index = index {
jsonData[index].pdfs.append(pdf)
}
}
}
} catch {
// Handle error
print("error parsing json")
}
}
// Sort data before use
jsonData.sort(by: { $0.section < $1.section })
for index in 0..<jsonData.count {
jsonData[index].pdfs.sort(by: { $0.airport < $1.airport } )
}
filtedJsonData = jsonData
}
#objc func onWebTap() {
var left:CGFloat = 0
if tableViewLeft.constant == 0 {
left = -320
}
tableViewLeft.constant = left
showMenu(left != 0, animated: true)
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
func showMenu(_ show:Bool, animated:Bool) {
if let image = UIImage(named: show ? "ico_open" : "ico_close") {
btnMenuClose?.image = image
//navigationItem.rightBarButtonItem?.image = image
//}
//var left:CGFloat = 20
//if show == false {
// left = -64
}
//btnMenuLeft.constant = left
UIView.animate(withDuration: animated ? 0.3 : 0.0, delay: 0, options: .curveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}
// TableView
extension PdfVC: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return filtedJsonData.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if filtedJsonData[section].pdfs.count == 0 {
return nil
}
return filtedJsonData[section].section
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filtedJsonData[section].pdfs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PdfCell", for: indexPath) as! PdfCell
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
cell.setupCell(pdf: pdf)
return cell
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
dismissKeyboard()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
//THIS IS WHERE I'M STUCK<<<<<<<<<
self.title = pdf.airport
}
}
// SearchBar
extension PdfVC: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
for (index, data) in jsonData.enumerated() {
// Filter pdfs by code and name
let filtedPdf = data.pdfs.filter { $0.code.lowercased().prefix(searchText.count) == searchText.lowercased() || $0.airport.lowercased().prefix(searchText.count) == searchText.lowercased() }
filtedJsonData[index].pdfs = filtedPdf
}
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = ""
tableView.reloadData()
}
}
Got it figured out. Thanks for all who spent some time reading my issue. I changed as follows
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
self.fileName = pdf.name
self.title = pdf.airport
DispatchQueue.main.async {
self.reloadWebView()
}
}
and added
private func reloadWebView() {
// Setup WebView
if let fileName = fileName {
isVideo = fileName.contains(".mp4")
if let range = fileName.range(of: isVideo ? ".mp4" : ".pdf") {
self.fileName!.removeSubrange(range)
}
}
if let file = Bundle.main.url(forResource: fileName ?? "", withExtension: isVideo ? ".mp4" : ".pdf", subdirectory: nil, localization: nil) {
let request = URLRequest(url: file)
webView.load(request)
}
}

Passing ImageArray from Json File to ImageView Controller

I'm Trying to have tableview with a search controller pass image Array from Json file to a new viewcontroller based on what option the user picks in search bar tableview. I have created a search bar for my App that displays will display all of the information in the app so the user can easily pick the pictures they want to see. That works normally by using a tableview, and when the user pick a row, it sends a variable with the associated pictures to an image view on the other screen.
Because of the amount of options I have, I created a Json file. I have it coded where it will return options based on what the user types into the search bar. My problem is that I am unable to pass the Image Array from the .json file to the image view controller. It will display the viewcontroller, but the "array" imageview is blank as no picture array is being passed. Below is my code and am wondering if anyone has any ideas that could point me in the right direction, or tell me what I am doing wrong.
Search Bar code:
import UIKit
class ProtocolCell: UITableViewCell {
#IBOutlet weak var pNameLabel: UILabel!
}
extension String {
func trimmed() -> String {
return self.trimmingCharacters(in: .whitespaces)
}
}
class SearchController: UIViewController, UISearchBarDelegate {
/// Search Bar
#IBOutlet weak var pSearchBar: UISearchBar!
/// Proto Array
fileprivate var myProtocols:[Protocols]?
/// Searhed Array
fileprivate var searchedProtocols:[Protocols]?
/// TableView
#IBOutlet weak var protocolsTV: UITableView!
/// Is Searching
fileprivate var isSearching:Bool=false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
protocolsTV.tableFooterView=UIView()
pSearchBar.delegate=self
myProtocols=[Protocols]()
searchedProtocols=[Protocols]()
myProtocols?.removeAll()
searchedProtocols?.removeAll()
myProtocols=Functions.getAllProtocolsFromJson()
if protocolsTV.delegate == nil {
protocolsTV.delegate=self
protocolsTV.dataSource=self
}
protocolsTV.reloadData()
}
}
extension SearchController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearching == false ? (myProtocols?.count ?? 0) : (searchedProtocols?.count ?? 0)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProtocolCell") as! ProtocolCell
cell.pNameLabel.text=isSearching == false ? (myProtocols![indexPath.row].pName ?? "") : (searchedProtocols![indexPath.row].pName ?? "")
return cell
}
//EDIT TABLE FUNCTION HERE!!!!!//
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Is Searching: \(isSearching) ImagesArray: \(isSearching==true ? (searchedProtocols?[indexPath.row].imagesName ?? []) : (myProtocols?[indexPath.row].imagesName ?? []))")
let Vc = self.storyboard?.instantiateViewController(withIdentifier: "imageViewController") as! imageViewController
let home = self.storyboard?.instantiateViewController(withIdentifier: "FIRST") as! ViewController
//switch indexPath.section
// {
// case 0:
if searchedProtocols?[indexPath.row].pName == "test" {
let arrayStorage = myProtocols?[indexPath.row].imagesName ?? []
Vc.passedArray = arrayStorage
print(arrayStorage)
print(myProtocols?[indexPath.row].imagesName ?? [])
self.navigationController?.pushViewController(Vc, animated: true)
}
else {
self.navigationController?.pushViewController(home, animated: true)
}
// break;
// default:
// self.navigationController?.pushViewController(home, animated: true)
// }
}
func updateSearchData(With searchText: String, In searchBar: UISearchBar) {
if searchText.trimmed().count == 0 {
isSearching=false
searchBar.setShowsCancelButton(false, animated: true)
} else {
isSearching=true
searchBar.setShowsCancelButton(true, animated: true)
}
if isSearching {
/// We Are Searching Sort Array
if searchedProtocols == nil { searchedProtocols=[Protocols]() }
searchedProtocols?.removeAll()
searchedProtocols=myProtocols!.filter({($0.pName ?? "").lowercased().contains(searchText.lowercased())})
/// Make Set So, Data isn't Repeated
searchedProtocols=Array(Set(searchedProtocols ?? []))
} else {
/// Searching is Stopped
searchedProtocols?.removeAll()
}
protocolsTV.reloadData()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateSearchData(With: searchText, In: searchBar)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.view.endEditing(true)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.setShowsCancelButton(false, animated: true)
searchBar.text=nil
isSearching=false
searchedProtocols?.removeAll()
protocolsTV.reloadData()
self.view.endEditing(true)
}
}
Other Used Code:
class Protocols: NSObject {
var pName:String?
var imagesName:[UIImage]!
override init() {}
init(With Dict: [String:Any]) {
pName=Dict["name"] as? String ?? ""
imagesName=Dict["imagesArray"] as? [UIImage] ?? []
}
ImageViewController:
class imageViewController: UIViewController,GADBannerViewDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate {
#IBOutlet weak var pageControl: UIPageControl!
var bannerView: GADBannerView!
var index = 0
var mySelectedProtocol:Protocols?
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var myImageView: UIImageView!
#IBAction func pictureSwipe(_ sender: Any) {
let pictureString = self.passedArray[index]
self.myImageView.image = pictureString
index = (index < passedArray.count-1) ? index+1 : 0
self.pageControl.numberOfPages = passedArray.count
self.pageControl.currentPage = index
}
#IBAction func pictureswipeback(_ sender: Any) {
let pictureString = self.passedArray[index]
self.myImageView.image = pictureString
index = (passedArray.count-1)
self.pageControl.numberOfPages = passedArray.count
self.pageControl.currentPage = index
}
func configurePageControl() {
self.pageControl.numberOfPages = passedArray.count
self.pageControl.currentPage = 0
self.pageControl.pageIndicatorTintColor = UIColor.white
self.pageControl.currentPageIndicatorTintColor = UIColor.red
self.view.addSubview(pageControl)
if index == 1 {
self.pageControl.currentPage = 1
}
func updateCurrentPageDisplay(){
self.pageControl.numberOfPages = passedArray.count
}
}
var passedImage : UIImage! = nil
var passedArray : [UIImage]!
override func viewDidLoad(){
super.viewDidLoad()
self.myImageView.image = passedArray.first
configurePageControl()
scrollView.delegate = self
self.navigationController?.navigationBar.isHidden = false
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 5.0
In Destination Controller
class DestinationVC: UIViewController {
var mySelectedProtocol:Protocols?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if mySelectedProtocol == nil { self.navigationController?.popViewController(animated: true) }
/// We have Data
print("Img Array with Name ==> \(mySelectedProtocol?.imagesName ?? [])")
}
}
In Source Controller TableView Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Is Searching: \(isSearching) ImagesArray: \(isSearching==true ? (searchedProtocols?[indexPath.row].imagesName ?? []) : (myProtocols?[indexPath.row].imagesName ?? []))")
let vc:DestinationVC=mainStoryBoard.instantiateViewController(withIdentifier: "DestinationVC") as! DestinationVC
vc.mySelectedProtocol=isSearching==true ? (searchedProtocols?[indexPath.row]) : (myProtocols?[indexPath.row])
self.navigationController?.pushViewController(vc, animated: true)
}
Update 2 - Show Images as PageViewController
private func addPageView() {
myScrollView.backgroundColor=UIColor.clear
myScrollView.isUserInteractionEnabled=true
myScrollView.showsHorizontalScrollIndicator=false
myScrollView.isPagingEnabled=true
myScrollView.delegate=self
myScrollView.bounces=false
self.count=mySelectedProtocol!.imagesName!.count
for i in 0..<self.count {
///Get Origin
let xOrigin : CGFloat = CGFloat(i) * myScrollView.frame.size.width
///Create a imageView
let imageView = UIImageView()
imageView.frame = CGRect(x: xOrigin, y: 0, width: myScrollView.frame.size.width, height: myScrollView.frame.size.height)
imageView.contentMode = .scaleAspectFit
imageView.image=UIImage(named: mySelectedProtocol!.imagesName![i])
myScrollView.addSubview(imageView)
}
setUpPageControl()
///Set Content Size to Show
myScrollView.contentSize = CGSize(width: myScrollView.frame.size.width * CGFloat(self.count), height: myScrollView.frame.size.height)
}

swift activityIndicater is not remove after completing data loading

I have a infinite-scrolling in tableView like facebook, it works very well but the problem is activityIndicator does not hide when complete data loading.
NetworkRequestAPI Request
import Foundation
class NetworkRequestAPI {
static func getPropductListByCategory(productId : Int, pageNo : Int , completion: #escaping ([Product]? , Error?) -> ()){
let url = URL(string: Configuration.BASE_URL+"/product-by/type?product_type_id="+String(productId)+"&page="+String(pageNo))
var categoryObject = [Product]()
URLSession.shared.dataTask(with:url!) { (urlContent, response, error) in
if error != nil {
}
else {
do {
let json = try JSONSerialization.jsonObject(with: urlContent!) as! [String:Any]
let products = json["products"] as? [String: Any]
// productCount = (json["product_count"] as? Int)!
let items = products?["data"] as? [[String:Any]]
items?.forEach { item in
let oProduct = Product()
oProduct.product_id = item["product_id"] as? Int
oProduct.product_name = item["product_name"] as? String
oProduct.product_image = item["product_image"] as? String
let ratingItem = item["rating_info"] as? [String: AnyObject]
let rating = RatingInfo()
rating.final_rating = ratingItem?["final_rating"] as? String
oProduct.rating_info = rating
categoryObject.append(oProduct)
}
completion(categoryObject, nil)
} catch let error as NSError {
print(error)
completion(nil, error)
}
}
}.resume()
}
}
ListTableView Class
class ListTableView: UITableViewController {
var isInitUILoad = true
var arrProduct = [[Product]]()
var product_id:Int = 0
var pageNo = 1
override func viewDidLoad() {
super.viewDidLoad()
self.initUILoad()
}
func initUILoad(){
ActivityIndicator.customActivityIndicatory(self.view, startAnimate: true)
NetworkRequestAPI.getPropductListByCategory(productId: product_id, pageNo: pageNo) { (products, error) in
DispatchQueue.main.async(execute: {
if products != nil {
self.pageNo += 1
self.arrProduct.append(products!)
print(self.arrProduct.count)
}else{
print(error.debugDescription)
}
ActivityIndicator.customActivityIndicatory(self.view, startAnimate: false)
self.tableView?.reloadData()
self.isInitUILoad = false
})
}
}
func loadMore(complition:#escaping (Bool) -> ()) {
NetworkRequestAPI.getPropductListByCategory(productId: product_id, pageNo: pageNo) { (products, error) in
DispatchQueue.main.async(execute: {
if error != nil{
print(error.debugDescription)
}
if products != nil && products?.count ?? 0 > 0{
self.pageNo += 1
self.arrProduct.append(products!) self.tableView?.insertSections([self.arrProduct.count - 1], with: .fade)
}else{
print("no product left")
}
complition(true)
})
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: categoryCellid, for: indexPath) as! ListTableCell
var categoryObject = arrProduct[indexPath.section]
cell.product = categoryObject[indexPath.item]
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 115.0
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerCellid) as! HeadFooterCell
if !isInitUILoad {
tableView.tableFooterView?.isHidden = true
loadMore(complition: { (isDone) in
footerView.activityIndicatorView.stopAnimating()
})
}
return footerView
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.01
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let lastSectionIndex = tableView.numberOfSections - 1
let lastRowIndex = tableView.numberOfRows(inSection: lastSectionIndex) - 1
if indexPath.section == lastSectionIndex && indexPath.row == lastRowIndex {
// print("this is the last cell")
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
spinner.startAnimating()
spinner.backgroundColor = .green
spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
self.tableView.tableFooterView = spinner
self.tableView.tableFooterView?.isHidden = false
}
}
HeadFooterCell
class HeadFooterCell: UITableViewHeaderFooterView {
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
setupViews()
}
var activityIndicatorView : UIActivityIndicatorView = {
var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
activityIndicatorView.backgroundColor = UIColor.cyan
return activityIndicatorView
}()
func setupViews() {
addSubview(activityIndicatorView)
addConstraintsWithFormat("H:|[v0]|", views: activityIndicatorView)
addConstraintsWithFormat("V:|[v0(50)]|", views: activityIndicatorView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You need to stop it in the main thread:
DispatchQueue.main.async {
footerView.activityIndicatorView.stopAnimating()
}
Also, set hidesWhenStopped to true:
footerView.activityIndicatorView.hidesWhenStopped = true

Use of unresolved identifier

In my Swift code to handle push notification I have this image:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView:UITableView?
var items = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(animated: Bool) {
let frame:CGRect;(x:0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
self.tableView = UITableView(frame: frame)
self.tableView?.dataSource = self
self.tableView?.delegate = self
self.view.addSubview(self.tableView!)
let btn = UIButton(frame: CGRect(x: 0, y: 25, width: self.view.frame.width, height: 50))
btn.backgroundColor = UIColor.cyanColor()
btn.setTitle("EKLE", forState: UIControlState.Normal)
btn.addTarget(self, action: "addData", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func addData(){
RestApiManager.sharedInstance.getRandomUser { json -> Void in
let results = json["results"]
for (index: String, subJson: JSON) in results{
let user: AnyObject = subJson["user"].object
self.items.addObject(user)
dispatch_async(dispatch_get_main_queue(), {
tableView?.reloadData()
})
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell?
if cell == nil{
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "cell")
}
let user:JSON = JSON(self.items[indexPath.row])
let picURL = user["picture"]["medium"].string
let url = NSURL(string: picURL!)
let data = NSData(contentsOfURL: url!)
cell?.textLabel?.text = user["username"].string
cell?.imageView?.image = UIImage(data: data!)
return cell!
}
}
Here is the error:
Use of unresolved identifier 'subJson'
in line let user: AnyObject = subJson["user"].object
How would this be fixed?
If you are using Swift 2 (Xcode 7) the syntax for looping over a dictionary with typed parameters has changed.
Now you should do like this:
for (index, subJson):(String, JSON) in results {
let user: AnyObject = subJson["user"].object
self.items.addObject(user)
dispatch_async(dispatch_get_main_queue(), {
tableView?.reloadData()
})
}
Old way:
(index: String, subJson: JSON)
New way:
(index, subJson):(String, JSON)