I can't import photos in collection view - swift

Need Help
Hello Guys i am trying to fetch gallary photos to uicollection view but it's show me fatelerror if any one have a solution so please help me
i mark the fatel error plese show it end help me erlier its a very important project for me thank you again advance
Hear is the code
class ADDVC: UIViewController {
//MARK:- Outlets
#IBOutlet weak var IMG_SelectedImageView: UIImageView!
#IBOutlet weak var cameraRollCollectionView: UICollectionView!
//MARK:- variables
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult<AnyObject>!
var assetThumbnailSize: CGSize!
//MARK:- Controller Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
let fetchOptions = PHFetchOptions()
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: .some(fetchOptions))
if let first_Obj:AnyObject = collection.firstObject{
//found the album
self.assetCollection = (first_Obj as! PHAssetCollection)
}
//MARK:- Select Photo
tabBarItem.image = UIImage(contentsOfFile: "Plus")
//MARK:- Select Video
}
override func viewWillAppear(_ animated: Bool) {
// Get size of the collectionView cell for thumbnail image
if let layout = self.cameraRollCollectionView!.collectionViewLayout as? UICollectionViewFlowLayout{
let cellSize = layout.itemSize
self.assetThumbnailSize = CGSize(width: cellSize.width, height: cellSize.height)
}
//fetch the photos from collection
self.photosAsset = (PHAsset.fetchAssets(in: self.assetCollection, options: nil) as AnyObject?) as! PHFetchResult<AnyObject>? //HEAR I AM GETTING THE FATEL ERROR
self.cameraRollCollectionView!.reloadData()
}

Related

Sigbart error during prepare for segue/unwind segue

I have an app where it is a marketplace and when you click on a product, it opens a detail view controller passing the data to display on the DetailVC. Additionally, inside the DetailVC, if you click on a button to claim the product, it segues to another VC to finalize the transaction.
In the DetailVC, there is a back button which is an unwind segue back to the main marketplace VC. Inside the TransactionVC, there is a cancel button which takes you back to the DetailVC.
When I am clicking the backButton in the DetailVC to take me back to the main market VC but I am getting a SIGBART Error and this :
020-07-15 09:05:23.707490-0500 evolutionatx[707:141952] Could not cast value of type 'evolutionatx.MarketplaceViewController' (0x1032c7868) to 'evolutionatx.PopUpPurchaseViewController' (0x1032c7ba8).
Here is the code for the DetailVC
import UIKit
import iCarousel
import CoreData
class MarketDetailViewController: UIViewController, UIScrollViewDelegate, iCarouselDelegate, iCarouselDataSource {
var productImageArray = [UIImage]()
var productVideo = String()
var pointsToPurchase = String()
var productName = String()
var productDescription = String()
var companyLogo = UIImage()
var companyWebsite = String()
var additionalProductImage = [UIImage]()
var companyName = String()
var promoCODE = String()
var buyLink = String()
var slides:[Slide] = [];
//IB
#IBOutlet weak var productNameLabel: UILabel!
#IBOutlet weak var productPriceLabel: UILabel!
#IBOutlet weak var productDescLabel: UILabel!
#IBOutlet weak var claimButton: UIButton!
#IBOutlet weak var imgScrollView: UIScrollView!
#IBOutlet weak var websiteButton: UIButton!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var logoDisplay: UIImageView!
#IBOutlet weak var carouselView: iCarousel!
#IBOutlet weak var otherProductslabe: UILabel!
var carouselImages = [UIImage]()
var evoCoin = Int()
override func awakeFromNib() {
super.awakeFromNib()
carouselImages = productImageArray
}
override func viewDidLoad() {
super.viewDidLoad()
valueSetter()
imgScrollView.delegate = self
slides = createSlides()
setupSlideScrollView(slides: slides)
pageControl.numberOfPages = slides.count
pageControl.currentPage = 0
view.bringSubviewToFront(pageControl)
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
pageControl.currentPage = Int(pageIndex)
let maximumHorizontalOffset: CGFloat = scrollView.contentSize.width - scrollView.frame.width
let currentHorizontalOffset: CGFloat = scrollView.contentOffset.x
// vertical
let maximumVerticalOffset: CGFloat = scrollView.contentSize.height - scrollView.frame.height
let currentVerticalOffset: CGFloat = scrollView.contentOffset.y
let percentageHorizontalOffset: CGFloat = currentHorizontalOffset / maximumHorizontalOffset
let percentageVerticalOffset: CGFloat = currentVerticalOffset / maximumVerticalOffset
}
#IBAction func claimProduct(_ sender: Any) {
print("tap rec")
claimProductandPurchase()
}
func claimProductandPurchase(){
evoCOiner()
if(evoCoin >= Int(pointsToPurchase)!){
print("Transaction Successful")
performSegue(withIdentifier: "proceedQuestion", sender: self)
}
else{
showToast(controller: self, message: "Insufficient EvoCoins", seconds: 0.5)
}
}
func showToast(controller: UIViewController, message : String, seconds: Double) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.view.backgroundColor = UIColor.black
alert.view.alpha = 0.6
alert.view.layer.cornerRadius = 15
controller.present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
alert.dismiss(animated: true)
}
}
func evoCoiner(){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "EvoCoins")
request.returnsObjectsAsFaults = false
do{
let result = try context.fetch(request)
for data in result as! [NSManagedObject]
{
evoCoin = data.value(forKey: "evoCoins") as! Int
}
}catch{
print("Failed")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let detailController = segue.destination as! PopUpPurchaseViewController
detailController.ppromo = promoCODE
detailController.link = buyLink
detailController.coinToPurchase = Int(pointsToPurchase)!
}
//This is the unwind used by the transaction back button
#IBAction func unwindToItem(segue: UIStoryboardSegue) {
}
}
Here is the code in the transaction VC
import UIKit
import AMTabView
import CoreData
class MarketplaceViewController: UIViewController, TabItem {
#IBOutlet weak var sView: UIView!
#IBOutlet weak var evoCoinLabe: UILabel!
//For the sake of simplicity I only kept the Unwind functions
//MARK: - UNWIND FUNCTIONS
#IBAction func unwindToMainMarketView(segue: UIStoryboardSegue) {
}
}
How can I fix this error?
Please advise if my question was not clear or properly phrased (if so, sorry I am pretty new to all of this)
As #matt already said in his comment and the error clearly states, you cannot cast a MarketplaceViewController to a PopUpPurchaseViewController.
Furthermore instead of doing a forced cast, always look for a safe one like below. Doing so will prevent crashes.
if let detailController = segue.destination as? PopUpPurchaseViewController {
...
}
else {
// log failed to cast
}

Creating a JTAppleCalendar inside a xib view

I'm trying to create a calendar using JTAppleCalendar inside a xib view because I want a paging type thing for it. On the first page is some information, and the second page is the calendar. I followed the tutorials for JTAppleCalendar on multiple sites, but my project always crashes, probably because I'm doing something wrong.
I have 3 files, a DetailViewController for setting up and displaying the pages, a dataViewController to connect the xib vars, and a CollectionViewCell for the calendar cells.
DetailViewController
import UIKit
import JTAppleCalendar
class DetailViewController: UIViewController {
var sportName: String = ""
var numClasses: Int = 0
var pages : [dataViewController]{
get {
let page1: dataViewController = Bundle.main.loadNibNamed("dataView", owner: self, options: nil)?.first as! dataViewController
page1.label.text = sportName
page1.classDuration.text = String(numClasses)
let page2: dataViewController = Bundle.main.loadNibNamed("secondDataView", owner: self, options: nil)?.first as! dataViewController
page2.calendar.calendarDataSource = self as? JTACMonthViewDataSource
page2.calendar.calendarDelegate = self as? JTACMonthViewDelegate
page2.calendar.reloadData()
return [page1, page2]
}
}
#IBOutlet weak var detailDescriptionLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
func configureView() {
// Update the user interface for the detail item.
if let detail = detailItem {
if let label = detailDescriptionLabel {
label.text = detail.description
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let back = UIBarButtonItem(title: "Back",style: .plain,target: self,action: #selector(backButton(_:)))
self.navigationItem.leftBarButtonItem = back
configureView()
view.bringSubviewToFront(pageControl)
setupScrollView(pages: pages)
pageControl.numberOfPages = pages.count
pageControl.currentPage = 0
}
var detailItem: String? {
didSet {
// Update the view.
configureView()
}
}
#objc
func backButton (_ sender: Any) {
performSegue(withIdentifier: "detailToList", sender: self)
}
func setupScrollView(pages: [dataViewController]){
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(pages.count), height: view.frame.height)
scrollView.isPagingEnabled = true
for i in 0 ..< pages.count {
pages[i].frame = CGRect(x: view.frame.width * (CGFloat(i)), y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(pages[i])
}
}
}
extension DetailViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
pageControl.currentPage = Int(pageIndex)
}
}
extension dataViewController: JTACMonthViewDataSource, JTACMonthViewDelegate {
func configureCalendar(_ calendar: JTACMonthView) -> ConfigurationParameters {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy MM dd"
formatter.timeZone = Calendar.current.timeZone
formatter.locale = Calendar.current.locale
let startDate = formatter.date(from: "2020 01 01")!
let endDate = Date()
return ConfigurationParameters(startDate: startDate, endDate: endDate)
}
func calendar(_ calendar: JTACMonthView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTACDayCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "dateCell", for: indexPath) as! CollectionViewCell
cell.dateLabel.text = cellState.text
return cell
}
func calendar(_ calendar: JTACMonthView, willDisplay cell: JTACDayCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
let cell = cell as! CollectionViewCell
cell.dateLabel.text = cellState.text
}
}
dataViewController
import JTAppleCalendar
class dataViewController: UIView {
//Page 1
#IBOutlet weak var label: UILabel!
#IBOutlet weak var classDuration: UILabel!
//Page 2
#IBOutlet weak var calendar: JTACMonthView!
}
CollectionViewCell
import UIKit
import JTAppleCalendar
class CollectionViewCell: JTACDayCell {
#IBOutlet weak var dateLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
And of course, the xib files. In DetailViewController, I moved the last extension part to dataViewController, but it didn't change anything. I'm also pretty sure I did many things wrong or inefficiently.
Can anyone help successfully implement the JTAppleCalendar inside the xib view, that would be appreciated! Thanks!
In your DetailViewController You are setting delegate and dataSource of calendar to self which is not conforming those protocols.
page2.calendar.calendarDataSource = self as? JTACMonthViewDataSource
page2.calendar.calendarDelegate = self as? JTACMonthViewDelegate
If thoose are needed to be handled in DetailViewController, I suggest you to start with implementing methods in DetailViewController not in dataViewController
extension DetailViewController: JTACMonthViewDataSource, JTACMonthViewDelegate

Swift is it possible to update UILabel when UIstepper in a custom tableview cell , is increase or decrease

I am trying to update a UIlabel through refreshLabel() outside of the tableview as the stepper changes value.Have seen multiple examples using eventhandlers but do not know how to use them.(would like the easiest way as im am new to swift.)
CustomCell code
import UIKit
class cartTVC: UITableViewCell , UICollectionViewDataSource, UICollectionViewDelegate{
var collectionCell : cartCVC!
#IBOutlet weak var stepper: UIStepper!
#IBOutlet weak var lblPrice: UILabel!
#IBOutlet weak var lblQuantity: UILabel!
var img : UIImage?
var name = ""
var index : Int?
var quantity : Int?
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.reloadData()
stepper.wraps = true
stepper.autorepeat = true
stepper.maximumValue = 100
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
layer.borderWidth = 2
layer.borderColor = UIColor.black.cgColor
layer.cornerRadius = 10
// Configure the view for the selected state
}
#IBAction func valueChange(_ sender: UIStepper) {
var cart:[CartItems]
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext{
let data = try? context.fetch(CartItems.fetchRequest())
cart = data as! [CartItems]
cart[index!].quantity = Int16(stepper.value)
cart[index!].totalPrice = cart[index!].price * Int64(cart[index!].quantity)
(UIApplication.shared.delegate as? AppDelegate)?.saveContext()
lblQuantity.text = String(stepper.value).description
lblPrice.text = "\(cart[index!].totalPrice) CREDITS"
}
}
}

How to ensure I'm not accessing outlets before they're loaded in

I'm making an interactive story app. The PageController: UIViewController controls the story, the first page loads fine but when I make a selection, app crashes with the fatal error Unexpectedly found nil when unwrapping. on line:
firstChoiceButton.setTitle(firstChoice.title, for: UIControlState())
Looking it up, it seems like there's an optional... maybe it's not communicating with my Story.swift file?
Maybe It's the #IBOutlet firstChoiceButton? but all of my #IBOutlets/Actions are hooked up right I think... Help?
import UIKit
class PageController: UIViewController {
#IBOutlet weak var storyLabel: UILabel!
#IBOutlet weak var firstChoiceButton: UIButton!
#IBOutlet weak var secondChoiceButton: UIButton!
#IBOutlet weak var backdrop2: UIImageView!
var page: Page?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)}
init(page: Page) {
self.page = page
super.init(nibName: nil, bundle: nil)}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()}
override func viewDidLoad() {
super.viewDidLoad()
if let page = page {
let attributedString = NSMutableAttributedString(string: page.story.text)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributedString.length))
if let firstChoice = page.firstChoice {
firstChoiceButton.setTitle(firstChoice.title, for: UIControlState())
firstChoiceButton.addTarget(self, action: #selector(PageController.loadFirstChoice), for: .touchUpInside)
} else {
firstChoiceButton.setTitle("Meep", for: UIControlState())
firstChoiceButton.addTarget(self, action: #selector(PageController.playAgain), for: .touchUpInside)
}
if let secondChoice = page.secondChoice {
secondChoiceButton.setTitle(secondChoice.title, for: UIControlState())
secondChoiceButton.addTarget(self, action: #selector(PageController.loadSecondChoice), for: .touchUpInside)
}
storyLabel.attributedText = attributedString
}
}
#IBAction func loadFirstChoice() {
if let page = page, let firstChoice = page.firstChoice {
let nextPage = firstChoice.page
let pageController = PageController(page: nextPage)
// playSound(nextPage.story.soundEffectURL as URL)
navigationController?.pushViewController(pageController, animated: true)
}
}
#IBAction func loadSecondChoice() {
if let page = page, let secondChoice = page.secondChoice {
let nextPage = secondChoice.page
let pageController = PageController(page: nextPage)
// playSound(nextPage.story.soundEffectURL as URL)
navigationController?.pushViewController(pageController, animated: true)
}
}
#IBAction func playAgain() {
navigationController?.popToRootViewController(animated: true)
}
}
You should instantiate the view controller programatically and push it to the navigation controller stack. Here is some code to help you get started.
func loadFirstChoice() {
if let page = page, let firstChoice = page.firstChoice {
let nextPage = firstChoice.page
//let pageController = PageController(page: nextPage)
// playSound(nextPage.story.soundEffectURL as URL)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let newPage = mainStoryboard.instantiateViewController(withIdentifier: "newpage") as? PageController { //newpage is the storyboard id of the view controller
newPage.page = nextPage
navigationController?.pushViewController(newPage, animated: true)
}
}
}

How to Disable all the Links from webView once it is loaded?

I am making simple web based application where I want to disable all the links when the page is loaded fully into the webView and for that I also tried this answer. But when I try this my UIActivityIndicatorView is stopped displaying.
This is my code:
import UIKit
class ViewController: UIViewController,UIWebViewDelegate {
#IBOutlet var webView: UIWebView!
#IBOutlet weak var Activity: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
Activity.hidden = true
var myString = "https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_456"
let myURL = NSURL(string: myString)
let myReq = NSURLRequest(URL: myURL!)
webView.loadRequest(myReq)
webView.delegate = self
}
func webViewDidStartLoad(webView: UIWebView){
var activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
var activityBarButtonItem = UIBarButtonItem(customView: activityIndicator)
navigationItem.rightBarButtonItem = activityBarButtonItem
activityIndicator.startAnimating()
}
func webViewDidFinishLoad(webView: UIWebView){
navigationItem.rightBarButtonItem = nil
}
}
Can anybody tell me how can I achieve that?
Thanks In advance!
What about displaying a transparent view over it?
EDIT
Try adding a new gesture recognizer to it and tell it to do nothing for taps?
let recognizer = UITapGestureRecognizer(target: self, action:Selector("handleTouch:"))
recognizer.delegate = self
webView.addGestureRecognizer(newTap)
func handleTouch(recognizer:UIPanGestureRecognizer) {}
Theres a great tut on gestures in swift here Swifty_Gestures