Working code fails when imported into project - ios

I have a Scroll View tutorial that I customized to download images, rather than using local.
The project works fine. When I import the two files and two corresponding View Controllers into my main project it crashes. I'm getting the error
unexpectedly found nil while unwrapping an Optional value.
I've set break points throughout the project, also set exception breakpoint, but can't locate the issue. The Scroll View presents the first image then bombs.
First VC:
import UIKit
import Alamofire
import AlamofireImage
class TutorialViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var pages = [TutorialStepViewController]()
var stringURLS: [String] = []
var networkStatus = NetworkStatus.searching
var constraintString = ""
enum NetworkStatus {
case searching
case finishedSearching
}
override func viewDidLoad() {
super.viewDidLoad()
scrollView.isPagingEnabled = true
getBrewerHistory(portalID: "7", galleryName: "Brewer History")
activityIndicator.startAnimating()
}
func configureScrollView() {
for i in 0..<stringURLS.count {
let page = createAndAddTutorialStep(stringURLS[i], iconImageName: "", text: "")
pages.append(page)
}
pageControl.numberOfPages = pages.count
var views: [String: UIView] = ["view": view]
for i in 0..<pages.count {
views.updateValue(pages[i].view, forKey: "page" + String(i))
}
let metrics = ["edgeMargin": 10, "betweenMargin": 20]
let verticalConstraints =
NSLayoutConstraint.constraints(
withVisualFormat: "V:|[page0(==view)]|", options: [], metrics: nil, views: views)
NSLayoutConstraint.activate(verticalConstraints)
for page in 0..<pages.count {
switch page {
case 0:
constraintString += "H:|-edgeMargin-[page" + String(page) + "(==view)]-betweenMargin-"
case pages.count-1:
constraintString += "[page" + String(page) + "(==view)]-edgeMargin-|"
default:
constraintString += "[page" + String(page) + "(==view)]-betweenMargin-"
}
}
let horizontalConstraints =
NSLayoutConstraint.constraints(
withVisualFormat: constraintString, options: [.alignAllTop, .alignAllBottom], metrics: metrics, views: views)
NSLayoutConstraint.activate(horizontalConstraints)
}
fileprivate func createAndAddTutorialStep(_ stringURL: String, iconImageName: String, text: String) -> TutorialStepViewController {
let tutorialStep = storyboard!.instantiateViewController(withIdentifier: "TutorialStepViewController") as! TutorialStepViewController
tutorialStep.view.translatesAutoresizingMaskIntoConstraints = false
let stringURL = stringURL
// tutorialStep.backgroundImage = UIImage(named: backgroundImageName)
let imageURL = URL(string: stringURL)
tutorialStep.backgroundImageURL = imageURL
tutorialStep.iconImage = UIImage(named: iconImageName)
tutorialStep.text = text
scrollView.addSubview(tutorialStep.view)
addChildViewController(tutorialStep)
tutorialStep.didMove(toParentViewController: self)
return tutorialStep
}
}
extension TutorialViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = scrollView.bounds.width
let pageFraction = scrollView.contentOffset.x / pageWidth
pageControl.currentPage = Int(round(pageFraction))
}
}
//Mark: Networking Calls
extension TutorialViewController {
func getBrewerHistory (portalID: String, galleryName: String) {
networkStatus = .searching
activityIndicator.isHidden = false
activityIndicator.startAnimating()
let apiURL = "http://www.smarttapp.com/DesktopModules/DnnSharp/DnnApiEndpoint/Api.ashx?method=GetBrewerHistory"
let params = ["PortalID" : portalID,
"GalleryName" : galleryName
]
Alamofire.request(
apiURL,
method: .get,
parameters: params
)
.responseJSON { response in
guard response.result.isSuccess else {
print("Error while fetching JSON: \(String(describing: response.result.error))")
return
}
guard let responseArray = response.result.value as? [NSDictionary] else { return }
for dict in responseArray {
if let url = dict["fileName"] as? String {
let fullURL = "http://www.smarttapp.com" + url
self.stringURLS.append(fullURL)
}
}
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
self.networkStatus = .finishedSearching
self.configureScrollView()
}
}
}
}
Second VC:
import UIKit
class TutorialStepViewController: UIViewController {
#IBOutlet fileprivate weak var backgroundImageView: UIImageView!
#IBOutlet fileprivate weak var iconImageView: UIImageView!
#IBOutlet fileprivate weak var textLabel: UILabel!
var backgroundImage: UIImage?
var backgroundImageURL: URL?
var iconImage: UIImage?
var text: String?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
backgroundImageView.af_setImage(withURL: backgroundImageURL!)
iconImageView.image = iconImage
if let text = text {
let font = UIFont(name: "HelveticaNeue-Light", size:20.0)!
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 8
paragraphStyle.alignment = .center
textLabel.attributedText = NSAttributedString(string: text,
attributes: [NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle])
}
}
}

Related

How to send data in extension to Button function

I'm trying to make a quiz application using the API, I can take api data and show on app but I cannot transfer data from extension in viewController to button pressed.right now, when click the button, I want the clicked option to be green or red, how can I do it?
QuizManager
import Foundation
protocol quizManagerDelegate {
func didUpdateQuiz(_ Quizmanager: QuizManager ,quiz: QuizModel)
}
struct QuizManager {
var delegate: quizManagerDelegate?
func performRequest(){
let urlString = "https://opentdb.com/api.php?amount=1&type=multiple"
if let url = URL(string: urlString){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
print(error!)
return
}
if let safeData = data{
if let quiz = self.parseJSON(quizdata: safeData){
delegate?.didUpdateQuiz(self, quiz: quiz)
}
}
}
task.resume()
}
}
func handle(data: Data?, response: URLResponse?, error: Error?) -> Void {
}
func parseJSON(quizdata: Data) -> QuizModel? {
let decoder = JSONDecoder()
do{
let decodedData = try decoder.decode(Welcome.self, from: quizdata)
let correct = decodedData.results?[0].correct_answer ?? "error"
let quest = decodedData.results?[0].question ?? "error"
let incorrect = decodedData.results?[0].incorrect_answers ?? ["error"]
let question = QuizModel(correctAnswer: correct, question: quest, falseAnswer: incorrect)
return question
} catch {
print(error)
return nil
}
}
}
QuizData
import Foundation
// MARK: - Welcome
struct Welcome: Codable {
let results: [Result]?
}
// MARK: - Result
struct Result: Codable {
let category: String?
let question, correct_answer: String?
let incorrect_answers: [String]?
}
QuizModel
import Foundation
struct QuizModel {
let correctAnswer : String
let question : String
let falseAnswer : [String]
}
ViewController
import UIKit
import GameKit
class ViewController: UIViewController {
#IBOutlet weak var ChoiceButton4: UIButton!
#IBOutlet weak var ChoiceButton3: UIButton!
#IBOutlet weak var ChoiceButton2: UIButton!
#IBOutlet weak var ChoiceButton1: UIButton!
#IBOutlet weak var QuestionTextView: UITextView!
var quizMangager = QuizManager()
#IBAction func OptionsButtonPressed(_ sender: UIButton) {
}
override func viewDidLoad() {
super.viewDidLoad()
QuestionTextView.layer.cornerRadius = 15
quizMangager.delegate = self
quizMangager.performRequest()
}
}
extension ViewController : quizManagerDelegate{
func didUpdateQuiz(_ Quizmanager: QuizManager, quiz: QuizModel) {
DispatchQueue.main.async { [self] in
self.QuestionTextView.text = quiz.question
var allOptions = []
allOptions.append(quiz.falseAnswer[0])
allOptions.append(quiz.falseAnswer[1])
allOptions.append(quiz.falseAnswer[2])
allOptions.append(quiz.correctAnswer)
let generatedValue = Array(allOptions.shuffled().prefix(4))
print(generatedValue)
print(quiz.correctAnswer)
ChoiceButton1.setTitle(generatedValue[0] as? String, for: .normal)
ChoiceButton2.setTitle(generatedValue[1] as? String, for: .normal)
ChoiceButton3.setTitle(generatedValue[2] as? String, for: .normal)
ChoiceButton4.setTitle(generatedValue[3] as? String, for: .normal)
}
}
}
ViewController
import UIKit
import GameKit
class ViewController: UIViewController {
#IBOutlet weak var ChoiceButton4: UIButton!
#IBOutlet weak var ChoiceButton3: UIButton!
#IBOutlet weak var ChoiceButton2: UIButton!
#IBOutlet weak var ChoiceButton1: UIButton!
#IBOutlet weak var QuestionTextView: UITextView!
var quizMangager = QuizManager()
#IBAction func OptionsButtonPressed(_ sender: UIButton) {
}
override func viewDidLoad() {
super.viewDidLoad()
QuestionTextView.layer.cornerRadius = 15
quizMangager.delegate = self
quizMangager.performRequest()
}
}
extension ViewController : quizManagerDelegate{
func didUpdateQuiz(_ Quizmanager: QuizManager, quiz: QuizModel) {
DispatchQueue.main.async { [self] in
self.QuestionTextView.text = quiz.question
var allOptions = []
allOptions.append(quiz.falseAnswer[0])
allOptions.append(quiz.falseAnswer[1])
allOptions.append(quiz.falseAnswer[2])
allOptions.append(quiz.correctAnswer)
let generatedValue = Array(allOptions.shuffled().prefix(4))
print(generatedValue)
print(quiz.correctAnswer)
ChoiceButton1.setTitle(generatedValue[0] as? String, for: .normal)
ChoiceButton2.setTitle(generatedValue[1] as? String, for: .normal)
ChoiceButton3.setTitle(generatedValue[2] as? String, for: .normal)
ChoiceButton4.setTitle(generatedValue[3] as? String, for: .normal)
}
}
}
You need to "hold onto the quiz data."
So, add a var property to your view controller:
var quizMangager = QuizManager()
// add this
var theQuiz: QuizModel?
then, in your didUpdateQuiz func, set that property:
func didUpdateQuiz(_ Quizmanager: QuizManager, quiz: QuizModel) {
DispatchQueue.main.async { [self] in
// add this
self.theQuiz = quiz
self.QuestionTextView.text = quiz.question
// ... no other changes
Now, connect all your buttons to #IBAction func OptionsButtonPressed and try this:
#IBAction func OptionsButtonPressed(_ sender: UIButton) {
guard let thisQuiz = theQuiz,
let btnTitle = sender.currentTitle
else { return }
if btnTitle == thisQuiz.correctAnswer {
sender.setTitleColor(.systemGreen, for: [])
} else {
sender.setTitleColor(.systemRed, for: [])
}
}

dropdown array becomes empty for few cells after adding cells in tableview and scroll up

Initially when I tap of hierarchy button and parentLocationLevelTwoBtnAction at that time parentLocationNameArr is not empty but after adding few more cells and I scroll up parentLocationNameArr is empty
import UIKit
import DropDown
import ObjectMapper
//Stock Btn Cell Delegate
protocol AddStorageLocationMasterBtnCellDelegate : AnyObject {
func didPressButton(_ tag: Int)
func didPressHierachyButton(_ tag: Int)
func didPressHierachytext(_ tag: Int,sender:String)
func didPressParenttext(_ tag: Int,sender:String, id:String)
func didPressParentTwotext(_ tag: Int,sender:String, id:String)
}
class AddStorageLocationMasterTVCell: UITableViewCell {
#IBOutlet var parentLTextLHeight: NSLayoutConstraint!
#IBOutlet weak var bgView: UIView!
#IBOutlet weak var deleteBtn: UIButton!
#IBOutlet weak var storageLocationNameView: UIView!
#IBOutlet var warnDescriptionbtn: UIButton!
#IBOutlet weak var storageLocationNameTF: UITextField!
#IBOutlet var warnNamebtn: UIButton!
#IBOutlet weak var descriptionView: UIView!
#IBOutlet weak var descriptionTextView: UITextView!
#IBOutlet weak var hierachyView: UIView!
#IBOutlet weak var hierachyTF: UITextField!
#IBOutlet weak var hierachyBtn: UIButton!
#IBOutlet weak var parentLocationView: UIView!
#IBOutlet weak var parentLocationTF: UITextField!
#IBOutlet weak var parentBgView: UIView!
#IBOutlet weak var parentHeightConstant: NSLayoutConstraint!
#IBOutlet weak var parentLocationLevelOneBtn: UIButton!
#IBOutlet weak var parentLocationLevelTwoView: UIView!
#IBOutlet weak var parentLocationLevelTwoTF: UITextField!
#IBOutlet weak var parentLocationTextLabel: UILabel!
#IBOutlet weak var stackView: UIStackView!
#IBOutlet weak var stackViewHeight: NSLayoutConstraint!
#IBOutlet weak var parentLcationLabel: UILabel!
var cellDelegate: AddStorageLocationMasterBtnCellDelegate?
let dropDown = DropDown() //2
var selectedId = 0
var accountID = ""
var storageLocationArr = NSMutableArray()
var storageLocationLevelThreeArr = NSMutableArray()
var serviceVC = ServiceController()
var parentLocationDict = [String]()
var parentLocationId = [String]()
var parentLocationArr = [NSArray]()
var parentLocationNameArr = [String]()
var parentLocationNameIdsArr = [String]()
var parentLocationDetailsDict = NSMutableArray()
var parentLocationNameLevethreeArr = [String]()
var parentLocationNameLevethreeIdsArr = [String]()
var parentLocationDetailsLevethreeDict = NSMutableArray()
var levelValue = 0
var idLevelThree = ""
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.parentBgView.isHidden = true
self.parentHeightConstant.constant = 0
storageLocationNameView.layer.borderColor = UIColor.gray.cgColor
storageLocationNameView.layer.borderWidth = 0.5
storageLocationNameView.layer.cornerRadius = 3
storageLocationNameView.clipsToBounds = true
descriptionView.layer.borderColor = UIColor.gray.cgColor
descriptionView.layer.borderWidth = 0.5
descriptionView.layer.cornerRadius = 3
descriptionView.clipsToBounds = true
hierachyView.layer.borderColor = UIColor.gray.cgColor
hierachyView.layer.borderWidth = 0.5
hierachyView.layer.cornerRadius = 3
hierachyView.clipsToBounds = true
parentLocationView.layer.borderColor = UIColor.gray.cgColor
parentLocationView.layer.borderWidth = 0.5
parentLocationView.layer.cornerRadius = 3
parentLocationView.clipsToBounds = true
parentLocationLevelTwoView.layer.borderColor = UIColor.gray.cgColor
parentLocationLevelTwoView.layer.borderWidth = 0.5
parentLocationLevelTwoView.layer.cornerRadius = 3
parentLocationLevelTwoView.clipsToBounds = true
bgView.backgroundColor = .white
bgView.layer.cornerRadius = 5.0
bgView.layer.shadowColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
bgView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
bgView.layer.shadowRadius = 6.0
bgView.layer.shadowOpacity = 0.7
hierachyTF.text = "Level 1"
selectedId = 1
}
#IBOutlet var parentButton: UIButton!
// override func setSelected(_ selected: Bool, animated: Bool) {
// super.setSelected(selected, animated: animated)
//
// // Configure the view for the selected state
// }
#IBAction func deleteBtnAction(_ sender: UIButton) {
cellDelegate?.didPressButton(sender.tag)
}
var tagVal=Int()
#IBAction func hierachyBtnAction(_ sender: UIButton) {
let selectedTagHierachy = sender.tag
cellDelegate?.didPressHierachyButton(selectedTagHierachy)
dropDown.dataSource = ["Level 1","Level 2","Level 3"]//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
self.selectedId = index
self.hierachyTF.text = item
self.cellDelegate?.didPressHierachytext(selectedTagHierachy, sender: item)
print(self.levelValue)
if index == 0 {
self.parentBgView.isHidden = true
self.parentHeightConstant.constant = 0
}
else if index == 1{
self.levelValue = index+1
self.get_StorageLocationMaster_API_Call(level: index+1, tag: selectedTagHierachy)
self.parentBgView.isHidden = false
self.parentHeightConstant.constant = 120
self.parentLcationLabel.text = "Parent Location L1"
self.parentLocationLevelTwoView.isHidden = true
}
else if index == 2{
self.levelValue = index+1
self.get_StorageLocationMaster_API_Call(level: index+1, tag: selectedTagHierachy)
self.parentBgView.isHidden = false
self.parentHeightConstant.constant = 120
self.parentLcationLabel.text = "Parent Location L2 and L1"
self.parentLocationLevelTwoView.isHidden = false
}
}
}
#IBAction func parentLocationBtnAction(_ sender: UIButton) {
let selectedTagParentLocation = sender.tag
// cellDelegate?.didPressParenttext(<#T##tag: Int##Int#>, sender: sender, id: <#T##String#>)
dropDown.dataSource = parentLocationNameLevethreeArr//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
self.parentLocationLevelTwoTF.text = item
self.cellDelegate?.didPressParentTwotext(selectedTagParentLocation, sender: item, id:self.parentLocationNameLevethreeIdsArr[index] )
}
}
#IBAction func parentLocationLevelTwoBtnAction(_ sender: UIButton)
{
let selectedTagParentLocation = sender.tag
dropDown.dataSource = parentLocationNameArr//4
dropDown.anchorView = sender //5
dropDown.bottomOffset = CGPoint(x: 0, y: sender.frame.size.height) //6
dropDown.show() //7
dropDown.selectionAction = { (index: Int, item: String) in //8
// guard let _ = self else { return }
// sender.setTitle(item, for: .normal) //9
// if self?.parentLocationNameLevethreeArr.count ?? 0>0
// {
// self?.parentLocationLevelTwoTF.text = self?.parentLocationNameLevethreeArr[0]
// self?.cellDelegate?.didPressParentTwotext(sender.tag, sender: self?.parentLocationNameLevethreeArr[0] ?? "", id: self?.parentLocationNameLevethreeIdsArr[0] ?? "")
// }
self.parentLocationTF.text = item
self.idLevelThree = self.parentLocationNameIdsArr[index]
self.cellDelegate?.didPressParenttext(selectedTagParentLocation, sender: item, id: self.parentLocationNameIdsArr[index] )
print(self.levelValue)
if self.levelValue==3
{
self.get_StorageLocationByParentLocation_API_Call(level: 2, tag: selectedTagParentLocation)
}
}
}
// MARK: Get Storage Location Master API Call
func get_StorageLocationByParentLocation_API_Call(level:Int,tag:Int) {
let defaults = UserDefaults.standard
accountID = (defaults.string(forKey: "accountId") ?? "")
// let newString = parentLocation.replacingOccurrences(of: " ", with: "%20")
if idLevelThree != ""
{
let urlStr = Constants.BaseUrl + getAllStorageLocationByParentUrl + "\(2)/" + "\(idLevelThree)/" + accountID
serviceVC.requestGETURL(strURL: urlStr, success: {(result) in
let respVo:GetStorageLocationMasterRespVo = Mapper().map(JSON: result as! [String : Any])!
DispatchQueue.main.async { [self] in
let status = respVo.STATUS_CODE
let message = respVo.STATUS_MSG
if status == 200 {
if message == "SUCCESS" {
if respVo.result != nil {
if respVo.result!.count > 0 {
let resultObj:[String:Any]=result as? [String:Any] ?? [String:Any]()
let resultArr:NSMutableArray=resultObj["result"]as? NSMutableArray ?? NSMutableArray()
self.storageLocationLevelThreeArr = NSMutableArray()
self.storageLocationLevelThreeArr = resultArr
self.parentLocationNameLevethreeArr.removeAll()
self.parentLocationNameLevethreeIdsArr.removeAll()
for obj in self.storageLocationLevelThreeArr {
let sDict=obj as? NSDictionary
let isCanEd:Bool = sDict?.value(forKey: "canEdit") as? Bool ?? false
// sDict(sDict?[i] as AnyObject).value(forKey: "canEdit") as? Bool
if isCanEd == true {
let slocName = sDict?.value(forKey: "slocName") as? String ?? ""
let idsStr = sDict?.value(forKey: "_id") as? String ?? ""
self.parentLocationNameLevethreeIdsArr.append(idsStr)
self.parentLocationNameLevethreeArr.append(slocName)
print("level 2 : \(parentLocationNameLevethreeArr)")
}
}
if self.parentLocationNameLevethreeArr.count > 0 {
self.parentLocationLevelTwoTF.text = self.parentLocationNameLevethreeArr[0]
self.cellDelegate?.didPressParentTwotext(tag, sender: self.parentLocationNameLevethreeArr[0], id: self.parentLocationNameLevethreeIdsArr[0])
}
// else{
// self.parentLocationLevelTwoTF.text = ""
// }
self.parentLTextLHeight.constant=0
self.parentLocationTextLabel.isHidden=true
self.parentLocationTextLabel.text=""
}
else {
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No parent storage location is created currently. Pls create a parent storage location before creating the storage location when use creates a storage location without a custom parent storage location"
self.parentLocationTextLabel.numberOfLines = 0
self.parentLocationTextLabel.lineBreakMode = .byWordWrapping
self.parentLocationLevelTwoTF.text = ""
self.parentLocationNameLevethreeArr=[String]()
self.parentLocationNameLevethreeIdsArr=[String]()
}
}
}
}
else {
// self.view.makeToast(message)
}
}
}) { (error) in
// self.view.makeToast("app.SomethingWentToWrongAlert".localize())
print("Oops, your connection seems off... Please try again later")
}
}
else
{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 2 storage location exists currently. Pls create a level 2 storage location before creating levele 3 storage location"
}
}
// MARK: Get AddressBook API Call
func get_StorageLocationMaster_API_Call(level:Int,tag:Int) {
let defaults = UserDefaults.standard
accountID = (defaults.string(forKey: "accountId") ?? "")
let urlStr = Constants.BaseUrl + getAllStorageLocationByHierachyLevelUrl + "\(1)/" + accountID
serviceVC.requestGETURL(strURL: urlStr, success: {(result) in
let respVo:GetStorageLocationMasterRespVo = Mapper().map(JSON: result as! [String : Any])!
DispatchQueue.main.async {
let status = respVo.STATUS_CODE
let message = respVo.STATUS_MSG
if status == 200 {
if message == "SUCCESS" {
if respVo.result != nil {
if respVo.result!.count > 0 {
let resultObj:[String:Any]=result as? [String:Any] ?? [String:Any]()
let resultArr:NSMutableArray=resultObj["result"]as? NSMutableArray ?? NSMutableArray()
print(resultArr)
self.storageLocationArr = NSMutableArray()
self.storageLocationArr = resultArr
if self.storageLocationArr.count==0
{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
}
else
{
self.parentLTextLHeight.constant=0
self.parentLocationTextLabel.isHidden=true
let ddict=self.storageLocationArr[0] as? NSDictionary
self.parentLocationNameArr = [String]()
self.parentLocationNameIdsArr = [String]()
for obj in self.storageLocationArr {
let sDict=obj as? NSDictionary
let isCanEd:Bool = sDict?.value(forKey: "canEdit") as? Bool ?? false
// sDict(sDict?[i] as AnyObject).value(forKey: "canEdit") as? Bool
if isCanEd == true {
let slocName = sDict?.value(forKey: "slocName") as? String ?? ""
let idsStr = sDict?.value(forKey: "_id") as? String ?? ""
self.parentLocationNameIdsArr.append(idsStr)
self.parentLocationNameArr.append(slocName)
print(self.parentLocationNameArr)
self.parentLocationDetailsDict.addObjects(from: sDict?.value(forKey: "parentLocationDetails") as? NSMutableArray as! [Any])
}
}
let parentLocationDetails=ddict?.value(forKey: "parentLocationDetails")as? NSArray
print(self.levelValue)
if self.levelValue==3
{
if self.parentLocationNameArr.count>0
{
self.idLevelThree = self.parentLocationNameIdsArr[0] ?? ""
self.parentLocationTF.text = self.parentLocationNameArr[0]
self.cellDelegate?.didPressParenttext(tag, sender: self.parentLocationNameArr[0], id: self.parentLocationNameIdsArr[0])
}
else{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 2 storage location exists currently. Pls create a level 2 storage location before creating levele 3 storage location"
}
// if self.parentLocationDetailsDict.count > 0
// {
self.get_StorageLocationByParentLocation_API_Call(level: 2, tag:tag)
print("parent level 2 :\(self.parentLocationNameLevethreeArr)")
// }
}
else
{
if self.parentLocationNameArr.count>0
{
self.parentLocationTF.text = self.parentLocationNameArr[0]
self.cellDelegate?.didPressParenttext(tag, sender: self.parentLocationNameArr[0], id: self.parentLocationNameIdsArr[0])
}
else{
self.parentLTextLHeight.constant=40
self.parentLocationTextLabel.isHidden=false
self.parentLocationTextLabel.text="No level 1 storage location exists currently. Pls create a level 1 storage location before creating levele 3 storage location"
}
}
}
}
else {
}
}
}
}
else {
// self.view.makeToast(message)
}
}
}) { (error) in
// self.view.makeToast("app.SomethingWentToWrongAlert".localize())
print("Oops, your connection seems off... Please try again later")
}
}
}
Thanks in advance🙏

Swift 4- App crashes on button press that starts segue

I am programming an application and it is supposed to go to another view controller on a button press but instead it crashes when I run it. The editor shows this: and with editor breakpointing on it shows this: but there is no error in the console. Here is the code for the viewcontroller that does the segue:
//
// DoTodayViewController.swift
// Paley Foundation: Starfish Support
//
// Created by Sa'ar Lipshitz on 10/28/17.
//
import UIKit
class DoTodayViewController: UIViewController {
#IBOutlet weak var navItem: UINavigationItem!
#IBOutlet weak var getBtn: UIButton!
#IBOutlet weak var suggestBtn: UIButton!
var name = "Sa'ar"
override func viewDidLoad() {
super.viewDidLoad()
getBtn.layer.cornerRadius = 8
getBtn.clipsToBounds = true
suggestBtn.layer.cornerRadius = 8
suggestBtn.clipsToBounds = true
navItem.prompt = "What would you like to do today, "+name+"?"
}
#IBAction func suggest(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "SuggestViewController") as! SuggestViewController
navigationController?.pushViewController(vc, animated: true)
}
//This crashes my app:
#IBAction func get(_ sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "AccessViewController") as! AccessViewController
navigationController?.pushViewController(vc, animated: true)
}
}
and here is my code for the viewcontroller that gets opened:
//
// AccessViewController.swift
// Paley Foundation: Starfish Support
//
// Created by Sa'ar Lipshitz on 10/29/17.
//
import UIKit
import Firebase
import Material
class AccessViewController: UIViewController {
var adviceRef: DatabaseReference!
var advice: [[String: Any]] = []
var i = 0
var card: Card!
var loadingLbl: UILabel!
var panGesture = UIPanGestureRecognizer()
var cardOrigPos: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
adviceRef = Database.database().reference().child("Advice")
var advDict: NSDictionary?
adviceRef.observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
advDict = value
print(advDict as Any)
for (_, adv) in advDict! {
self.advice.append(adv as! [String : Any])
}
print(self.advice)
self.showNextCard()
}) { (error) in
print(error.localizedDescription)
}
let swipeRec = UIPanGestureRecognizer(target: self, action: #selector(swipe(sender:)))
card.isUserInteractionEnabled = true
card.addGestureRecognizer(swipeRec)
}
#objc func swipe(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
let velocity = sender.velocity(in: view)
let direction = velocity
print("Translation: \(translation)")
if sender.state == .began {
cardOrigPos = card.center
} else if sender.state == .changed {
card.center = CGPoint(x: cardOrigPos.x+translation.x, y: cardOrigPos.y+translation.y)
} else if sender.state == .ended {
if velocity.y == 0 && velocity.x == 0 {
UIView.animate(withDuration: 0.3, animations: {
self.card.center = self.view.center
})
} else {
UIView.animate(withDuration: 0.3, animations: {
self.card.center = CGPoint(x: self.cardOrigPos.x+direction.x*5, y: self.cardOrigPos.y+direction.y)
})
self.showNextCard()
}
}
}
func showNextCard() {
if advice.count >= 0 {
let adv = advice[i]
setCard(adv["username"] as? String, adv["title"] as! String, adv["desc"] as! String, image: adv["image"] as? UIImage)
i += 1
if i >= advice.count {
i = 0
}
}
}
func setCard(_ username: String?, _ title: String, _ desc: String, image: UIImage?) {
let toolbar = setToolbar(username ?? "", title)
card = Card()
card.toolbar = toolbar
card.toolbarEdgeInsetsPreset = .square3
card.toolbarEdgeInsets.bottom = 0
card.toolbarEdgeInsets.right = 8
card.contentView = setContentView(content: desc)
card.contentViewEdgeInsetsPreset = .wideRectangle3
card.layer.borderWidth = 1.0
card.layer.borderColor = UIColor.black.cgColor
card.layer.cornerRadius = 2
view.layout(card).horizontally(left: 20, right: 20).center()
}
func setToolbar(_ username: String, _ title: String) -> Toolbar {
let toolbar = Toolbar(rightViews: [setMoreBtn()])
toolbar.title = title
toolbar.detail = username
toolbar.detailLabel.textColor = Color.grey.base
return toolbar
}
func setMoreBtn() -> IconButton {
let moreBtn = IconButton(image: Icon.cm.moreVertical, tintColor: Color.grey.base)
return moreBtn
}
func setContentView(content: String) -> UILabel {
let contentView = UILabel()
contentView.numberOfLines = 0
contentView.text = content
contentView.font = RobotoFont.regular(with: 14)
return contentView
}
}
When I tried using print statements to debug, the one in the DoTodayViewController.get(_ sender: Any) method ran but not the one in AccessViewController.viewDidLoad()
Make sure you changed the class of the view controller object in the storyboard to AccessViewController and that the Storyboard ID is correctly spelled. You may be encountering a nil when trying to force unwrap storyboard?.instantiateViewController(withIdentifier: "AccessViewController") as! AccessViewController. Try using if let wherever an optional needs to be unwrapped to handle the scenario of it being nil.

Parsing json data through alamofire in table view cells

I am trying to parse json data in my table view cell and its not parsing and not showing the cells . I am attaching all my code please tell me whats the mistake i am doing .. I am not getting any error but the cells are not showing. I have made separate class and functions for json parsing and storing it in an array .
//
// ViewController.swift
// WorkingFeed2
//
// Created by keshu rai on 08/08/17.
// Copyright © 2017 keshu rai. All rights reserved.
//
import UIKit
import Alamofire
import MediaPlayer
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
var post : PostData!
var posts = [PostData]()
typealias DownloadComplete = () -> ()
var arrayOfPostData : [String] = []
#IBOutlet weak var feedTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedTable.dataSource = self
feedTable.delegate = self
}
func downloadPostData(completed: #escaping DownloadComplete) {
Alamofire.request("https://new.example.com/api/posts/get_all_posts").responseJSON { response in
let result = response.result
if let dict = result.value as? Dictionary<String,AnyObject> {
if let successcode = dict["STATUS_CODE"] as? Int {
if successcode == 1 {
if let postsArray = dict["posts"] as? [Dictionary<String,AnyObject>]
{
for obj in postsArray
{
let post = PostData(postDict: obj)
self.posts.append(post)
print(obj)
}
// self.posts.remove(at: 0)
self.feedTable.reloadData()
}
}
}
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 419
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : ImageTableViewCell = self.feedTable.dequeueReusableCell(withIdentifier: "contentViewReuse") as! ImageTableViewCell
let post = posts[indexPath.row]
print(post)
cell.configureCell(post : post)
return cell
}
}
This is my PostData Class.
import Foundation
class PostData {
var _profileImageURL : String?
var _fullName : String?
var _location : String?
var _title : String?
var _postTime : String?
var _likes : Int?
var _comments : Int?
var _mediaType : String?
var _contentURL : String?
var _content : String?
var _plocation : String?
var profileImageURL : String
{
if _profileImageURL == nil {
_profileImageURL = ""
}
return _profileImageURL!
}
var fullName : String
{
if _fullName == nil {
_fullName = ""
}
return _fullName!
}
var location : String {
if _location == nil {
_location = ""
}
return _location!
}
var title : String {
if _title == nil {
_title = ""
}
return _title!
}
var postTime : String {
if _postTime == nil {
_postTime = ""
}
return _postTime!
}
var likes : Int {
if _likes == nil {
_likes = 0
}
return _likes!
}
var comments : Int {
if _comments == nil {
_comments = 0
}
return _comments!
}
var mediaType : String {
if _mediaType == nil {
_mediaType = ""
}
return _mediaType!
}
var contentURL : String {
if _contentURL == nil {
_contentURL = ""
}
return _contentURL!
}
var content : String {
if _content == nil {
_content = ""
}
return _content!
}
var pLocation : String {
if _plocation == nil {
_plocation = ""
}
return _plocation!
}
init(postDict : Dictionary<String , AnyObject>)
{
if let postsArray = postDict["posts"] as? [Dictionary<String,AnyObject>]
{
for i in 1..<postsArray.count
{
let fullName1 = postsArray[i]["full_name"] as? String
self._fullName = fullName1
let profileImageURL1 = postsArray[i]["profile_pic"] as? String
self._profileImageURL = profileImageURL1
let location1 = postsArray[i]["user_city"] as? String
self._location = location1
let title1 = postsArray[i]["title"] as? String
self._title = title1
let postTime1 = postsArray[i]["order_by_date"] as? String
self._postTime = postTime1
let likes1 = postsArray[i]["liked_count"] as? Int
self._likes = likes1
let comments1 = postsArray[i]["comment_count"] as? Int
self._comments = comments1
let mediaType1 = postsArray[i]["media_path"] as? String
self._mediaType = mediaType1
let contentURL1 = postsArray[i]["media_path"] as? String
self._contentURL = contentURL1
let content1 = postsArray[i]["content"] as? String
self._content = content1
let plocation1 = postsArray[i]["location"] as? String
self._plocation = plocation1
}
}
}
}
This is my PostDataTableViewCell code.
import UIKit
import Alamofire
class PostDataTableViewCell: UITableViewCell {
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var titlePost: UILabel!
#IBOutlet weak var profileFullName: UILabel!
#IBOutlet weak var profileUserLocation: UILabel!
#IBOutlet weak var likeBtn: UIButton!
var buttonAction: ( () -> Void) = {}
var pressed = false
#IBAction func likeBtnPressed(_ sender: Any) {
if !pressed {
let image = UIImage(named: "Like-1.png") as UIImage!
likeBtn.setImage(image, for: .normal)
pressed = true
} else {
let image = UIImage(named: "liked.png") as UIImage!
likeBtn.transform = CGAffineTransform(scaleX: 0.15, y: 0.15)
UIView.animate(withDuration: 2.0,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: .allowUserInteraction,
animations: { [weak self] in
self?.likeBtn.transform = .identity
},
completion: nil)
likeBtn.setImage(image, for: .normal)
pressed = false
}
}
#IBAction func commentBtnPressed(_ sender: Any) {
print("Commented")
}
#IBAction func shareBtnPressed(_ sender: Any) {
self.buttonAction()
}
#IBAction func readContentBtnPressed(_ sender: Any) {
print("Read")
}
#IBOutlet weak var contentPostLabel: UILabel!
#IBOutlet weak var contentTypeView: UIView!
#IBOutlet weak var likeAndCommentView: UIView!
#IBOutlet weak var numberOfLikes: UILabel!
#IBOutlet weak var numberOfComments: UILabel!
#IBOutlet weak var postLocation: UILabel!
#IBOutlet weak var postTimeOutlet: UILabel!
func configureCell(post : PostData)
{
titlePost.text = "\(post.title)"
profileFullName.text = "\(post.fullName)"
profileUserLocation.text = "\(post.location)"
numberOfLikes.text = "\(post.likes) Likes"
numberOfComments.text = "\(post.comments) Comments"
postLocation.text = "\(post.pLocation)"
postTimeOutlet.text = "\(post.postTime)"
let url = URL(string: post.profileImageURL)
let data = try? Data(contentsOf: url!)
profileImage.image = UIImage(data: data!)
contentPostLabel.text = "\(post.content)"
if post.mediaType == "image"
{
let url1 = URL(string: post.contentURL)
let data1 = try? Data(contentsOf: url1!)
let image = UIImage(data: data1!)
let imageToView = UIImageView(image: image!)
imageToView.frame = CGRect(x: 0, y: 0, width: 375 , height: 250)
imageToView.contentMode = UIViewContentMode.scaleToFill
contentTypeView.addSubview(imageToView)
}
else if post.mediaType == "null"
{
print("Status")
}
else if post.mediaType == "video"
{
print("Video")
}
else if post.mediaType == "youtube"
{
print("youtube")
}
}
}
Most likely the issue occurs because you are trying to parse the value for key posts twice, once in PostData and once in ViewController.
First of all in Swift 3 a JSON dictionary is [String:Any], secondly – as already mentioned in my comment – private backing variables are nonsense in Swift.
The class PostData can be reduced to
class PostData {
let profileImageURL : String
let fullName : String
let location : String
let title : String
let postTime : String
let likes : Int
let comments : Int
let mediaType : String
let contentURL : String
let content : String
let plocation : String
init(postDict : [String:Any])
{
fullName = postDict["full_name"] as? String ?? ""
profileImageURL = postDict["profile_pic"] as? String ?? ""
location = postDict["user_city"] as? String ?? ""
title = postDict["title"] as? String ?? ""
postTime = postDict["order_by_date"] as? String ?? ""
likes = postDict["liked_count"] as? Int ?? 0
comments = postDict["comment_count"] as? Int ?? 0
mediaType = postDict["media_path"] as? String ?? ""
contentURL = postDict["media_path"] as? String ?? ""
content = postDict["content"] as? String ?? ""
plocation = postDict["location"] as? String ?? ""
}
}

Remove the UIView at Runtime and Automatically Correct the UI

I have a UIViewController. I have made a MyProfile section. Now what i want to do is that if a person has only one picture then the 4 images section (which is a uiview) disappear and my UI (AboutLabel and TextSection comes up) will set according to that
Please see this picture: https://www.dropbox.com/s/gwokb8ge4pu5cw3/MyProfile.png?dl=0
class MyProfileViewController: UIViewController , UIImagePickerControllerDelegate{
#IBOutlet weak var sidebarButton: UIBarButtonItem!
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var ageLabel: UILabel!
#IBOutlet weak var totalPicView: UIView!
#IBOutlet weak var aboutMeLabel: UITextView!
var imagesArray = [UIImageView]()
var tag: Int?
var check = false
var myUserInfo: UsersInformation!
var age: Int?
override func viewDidLoad() {
super.viewDidLoad()
if revealViewController() != nil
{
// revealViewController().rearViewRevealWidth = 62
sidebarButton.target = revealViewController()
sidebarButton.action = #selector(SWRevealViewController.revealToggle(_:))
//revealViewController().rightViewRevealWidth = 150
//rightReveal.target = revealViewController()
//rightReveal.action = "rightRevealToggle:"
view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
if NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) != nil
{
let uid = DataService.ds.currentUserID
DataService.ds.currentUserRef.observeEventType(.Value, withBlock: { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]
{
if let userDictionary = snapshot.value as? Dictionary<String , AnyObject>
{
print("ProfileData")
self.myUserInfo = UsersInformation(id:uid, userInfo: userDictionary)
}
}
/*SavingDataFUnction*/
self.setProfileData()
})
}
}
func setProfileData()
{
age = giveMeAge()
let width = view.frame.width
let height = view.frame.height
print("w:\(width) ; h \(height)")
/*Basic Information*/
self.nameLabel.text = myUserInfo.uName
self.ageLabel.text = "Age: " + String(age!)
self.aboutMeLabel.text = myUserInfo.about
if myUserInfo.imageUrl[0] == noImageUrl
{
profilePic.image = UIImage(named: "Profile")
/*Hide totalPicView and Adjust aboutLabel and TextView*/
//totalPicView.viewWithTag(101)?.hidden = true
//totalPicView.frame.size.height = 0
}
else if myUserInfo.imageUrl.count >= 1
{
/*FirstPic is Profile Pic*/
let profile = myUserInfo.imageUrl[0]
profilePic.kf_setImageWithURL(NSURL(string: profile))
for i in 0 ... 3
{
let url = self.myUserInfo.imageUrl[i]
let imgOne = UIImageView(frame: CGRectMake(89.5 * CGFloat(i), 0, 89.5, totalPicView.frame.height))
imgOne.kf_setImageWithURL(NSURL(string: url))
imgOne.tag = 11 + i
imagesArray.append(imgOne)
self.totalPicView.addSubview(imgOne)
}
for image: UIImageView in imagesArray
{
image.userInteractionEnabled = true
image.clipsToBounds = true
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.setImage))
image.addGestureRecognizer(tapGesture)
}
}
}
func setImage(gesture: UITapGestureRecognizer) {
print(gesture.view?.tag)
tag = gesture.view?.tag
performSegueWithIdentifier("showImages", sender: self)
//presentViewController(imagePicker, animated: true, completion: nil)
}
func setMyUI(imageView: UIImageView)
{
aboutMeLabel.layer.borderColor = UIColor.blackColor().CGColor
aboutMeLabel.layer.cornerRadius = 5
aboutMeLabel.layer.borderWidth = 1
}
func giveMeAge() -> Int
{
let dob = myUserInfo.dob
let todaysDate = NSDate() //dateFromString("2015-02-04 23:29:28", format: "yyyy-MM-dd HH:mm:ss")
let dateFormater = NSDateFormatter()
dateFormater.dateFormat = "MM/dd/yyyy"
let currentDate = dateFormater.dateFromString(dateFormater.stringFromDate(todaysDate))
let myDob = dateFormater.dateFromString(dob)
let calendar: NSCalendar = NSCalendar.currentCalendar()
let age = calendar.components(.Year, fromDate: myDob! , toDate: currentDate!, options: [])
return age.year
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImages"
{
let dest = segue.destinationViewController as! ProfileImages
dest.arrarayOfImages = imagesArray
dest.tag = tag
dest.uname = myUserInfo.uName
dest.myage = age
}
}
}
Ok if I understand correctly you want to remove the UIView section with the 4 UIImageViews if the user has just one/no picture/s. Why not try with an if statement in your viewDidLoad (Swift 3 syntax):
if(yourImageViewArray.count <= 1){
yourUIViewForImages.isHidden = true
}
Once your UIView yourUIViewForImages is hidden, your stack should adjust accordingly. Unless you have hardcoded CGRect values (x,y) for your About sections. It would really help to post your code as already mentioned in your comments section.

Resources