Swift link Image data from Parse array using segues to secondViewController [duplicate] - ios

This question already has answers here:
Swift link Image from Parse array using segues to secondViewController
(2 answers)
Closed 7 years ago.
Here is my code, i am trying to use the "prepareForSegue" function to send an image from tableViewController (firstViewController) to my detailedViewController (secondViewController). I have managed to populate my firstViewController from the parse cloud successfully and I have managed to get my secondViewController Labels to update, but i can not get the imageView to update. I have posted my code below
firstViewController
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let eventDetailVC: EventDetailsVC = segue.destinationViewController as! EventDetailsVC
if let selectedArrayIndex = tableView.indexPathForSelectedRow?.row {
eventDetailVC.detailNameLabel = postedEvents[selectedArrayIndex]
eventDetailVC.detailAddressLabel = postedAddress[selectedArrayIndex]
eventDetailVC.detailCityLabel = postedCity[selectedArrayIndex]
eventDetailVC.detailStateLabel = postedState[selectedArrayIndex]
eventDetailVC.detailStartLabel = postedStart[selectedArrayIndex]
eventDetailVC.detailEndLabel = postedEnd[selectedArrayIndex]
eventDetailVC.detailPriceLabel = postedPrices[selectedArrayIndex]
eventDetailVC.detailDescriptionLabel = postedDescription[selectedArrayIndex]
// The error is here....i think
postedImages[selectedArrayIndex].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
eventDetailVC.detailImageView.image = downloadedImage
}
}
}
}
secondViewController
var detailNameLabel = String()
var detailDescriptionLabel = String()
var detailPriceLabel = String()
var detailStartLabel = String()
var detailEndLabel = String()
var detailAddressLabel = String()
var detailCityLabel = String()
var detailStateLabel = String()
var detailImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
detailName.text = detailNameLabel
detailDescription.text = detailDescriptionLabel
detailPrice.text = detailPriceLabel
detailStart.text = detailStartLabel
detailEnd.text = detailEndLabel
detailAddress.text = detailAddressLabel
detailCity.text = detailCityLabel
detailState.text = detailStateLabel
// its this line below....i think
detailImage.image = detailImageView.image
}
Please can someone help me figure this out, Im kinda new to this whole thing

I don't see where "detailImage" is defined, so this is assuming it is a property on .
Set a breakpoint inside the "getDataInBackgroundWithBlock" completion block to see if and when it is getting called. If it is getting called add "eventDetailVC.detailImage.image = downloadedImage" to the completion block.

Your problem is that the download of the image completes asynchronously, so by the time it has completed, your view controller has already executed the line detailImage.image = detailImageView.image with a nil image.
Rather than putting all of the code in your viewDidLoad, define didSet observers for your properties that set the appropriate UI elements. This way any time the property is updated it will automatically update the UI element;
Finally, your properties have confusing names, detailAddressLabel is actually a string and the UILabel instance seems to be named detailAddress - this has caused you to define detailImageView as UIImageView instead of a UIImage.
My suggested implementation is (after changing the names of IBOutlets and other properties to make more sense):
class someViewController : UIViewController {
#IBOutlet var detailNameLabel : UILabel! {
didSet {
self.detailNameLabel?.text=self.detailName
}
}
#IBOutlet var detailDescriptionLabel : UILabel! {
didSet {
self.detailDescriptionLabel?.text=self.detailDescription
}
}
#IBOutlet var detailPriceLabel : UILabel! {
didSet {
self.detailPriceLabel?.text=self.detailPrice
}
}
#IBOutlet var detailStartLabel : UILabel! {
didSet {
self.detailStartLabel?.text=self.detailStart
}
}
#IBOutlet var detailEndLabel : UILabel! {
didSet {
self.detailEndLabel?.text=self.detailEnd
}
}
#IBOutlet var detailAddressLabel : UILabel! {
didSet {
self.detailAddressLabel?.text=self.detailAddress
}
}
#IBOutlet var detailCityLabel : UILabel! {
didSet {
self.detailCityLabel?.text=self.detailCity
}
}
#IBOutlet var detailImageView : UIImageView! {
didSet {
self.detailImageView?.image=self.detailImage
}
}
var detailName : String = "" {
didSet {
self.detailNameLabel?.text=self.detailName
}
}
var detailDescription : String = "" {
didSet {
self.detailDescriptionLabel?.text=self.detailDescription
}
}
var detailPrice : String = "" {
didSet {
self.detailPriceLabel?.text=self.detailPrice
}
}
var detailStart : String = "" {
didSet {
self.detailStartLabel?.text=self.detailStart
}
}
var detailEnd : String = "" {
didSet {
self.detailEndLabel?.text=self.detailEnd
}
}
var detailAddress: String = "" {
didSet {
self.detailAddressLabel?.text=self.detailAddress
}
}
var detailCity : String = "" {
didSet {
self.detailCityLabel?.text=self.detailCity
}
}
var detailImage : UIImage? {
didSet {
self.detailImageView?.image=self.detailImage
}
}
}

Related

How to check if a user inputed answer has letters, and if so, how would you just default that answer into a 0?

Heres the code I have so far, now when a user inputs any letter, my label display nothing, what I would like to figure out is how to turn that nothing "", into a 0. I tried doing an if statement on my "label.txt ="'s but that didn't pan out. What would be a better way of finding my desired results?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var game1: UITextField!
#IBOutlet weak var game2: UITextField!
#IBOutlet weak var game3: UITextField!
#IBOutlet weak var series: UILabel!
#IBOutlet weak var average: UILabel!
#IBOutlet weak var high: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func calculate(_ sender: Any) {
self.view.endEditing(true)
guard
let text1 = game1.text,
let text2 = game2.text,
let text3 = game3.text
else { return }
guard
let game1Results = Int(text1),
let game2Results = Int(text2),
let game3Results = Int(text3)
else { return }
let gameResultsArray = [game1Results, game2Results, game3Results]
let sumArray = gameResultsArray.reduce(0, +)
let positiveArray = gameResultsArray.filter {
(item: Int) -> Bool in return item > 0
}
var avgArrayValue = 0
if positiveArray.count == 0
{
avgArrayValue = 0
}else {
avgArrayValue = sumArray / positiveArray.count
}
series.text = "\(sumArray)"
average.text = "\(avgArrayValue)"
if let maximumVal = gameResultsArray.max() {
high.text = String(maximumVal)
}
}
}
Here is what you need, convert String to Int and give the default 0. Instead of using the guard let return use this method:
Instead of this:
guard let game1Results = Int(text1) else { return }
Use this:
let game1Results = Int(text1) ?? 0

TableViewCell pass data to ViewController (Parse.com)?

Tell me what can be a mistake. I have 6 columns, two columns belong to TableViewCell. The other 4 belong to the ViewController. How do I tie the rows correctly so that the match information matches its row in TableViewCell.
import UIKit
import Parse
class DetailTennisViewController: UIViewController {
#IBOutlet weak var imageTennis: UIImageView!
#IBOutlet weak var outClose: UIButton!
#IBOutlet weak var titleTennis: UILabel!
#IBOutlet weak var textTennis: UITextView!
#IBOutlet weak var progTennis: UILabel!
#IBAction func closeOut(_ sender: Any) {
dismiss(animated: false, completion: nil)
}
var tenises : Tennis?
func configureButton() {
outClose.layer.cornerRadius = 0.5 * outClose.bounds.size.width
outClose.clipsToBounds = true
}
override func viewDidLoad() {
super.viewDidLoad()
loadTennis()
configureButton()
}
func loadTennis () {
let qwery = PFQuery(className: "tennis")
qwery.getFirstObjectInBackground() { (object,error) ->Void in
if error == nil {
self.textTennis.text = object!["textTen"] as? String
self.progTennis.text = object!["progTen"] as? String
self.titleTennis.text = object!["titleTen"] as? String
let imageFile = object!["tenImage"] as? PFFile
imageFile?.getDataInBackground() { (data:Data?, error:Error?)->Void in
if error == nil {
if let imageData = data {
self.imageTennis.image = UIImage(data: imageData)
}
}
}
}
}
}
}
How to make the data string Parse.com How to make the data TableViewCell cells corresponded to the description ViewController. In my code, when the cell is opened, the same data is displayed. I uploaded 4 events and information about them. So the information about them opens up the same. How to make the one that is indicated by their "objectId"

How can I passing data UIViewContoller from UIView in swift3

How can i passing data uiviewController from uiview
I am Using function but it was not working
protocol name is startcalldelegate and function name is startcall
UIView Code
protocol StartCallDelegate: class {
func startCall(localNickname :String, remoteNickname :String)}
class CardView: UIView {
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
weak var delegate: CardViewDelegate?
weak var socketdelegate: StartCallDelegate?
#IBOutlet weak var UserPhoto: UIImageView!
#IBOutlet weak var UserNickName: UILabel!
#IBOutlet weak var UserAge: UILabel!
#IBOutlet weak var UserPeople: UILabel!
var localNickname: String = ""
var remoteNickname: String = ""
#IBAction func SendMessage(_ sender: Any) {
print("SendMessage")
//print(localNickName)
//print(UserNickName.text!)
}
#IBAction func SendVideoCall(_ sender: Any) {
print("SendVideoCall")
let entityDescription = NSEntityDescription.entity(forEntityName: "Profile", in: managedObjectContext)
let request = NSFetchRequest<NSFetchRequestResult>()
request.entity = entityDescription
do {
let objects = try managedObjectContext.fetch(request)
if objects.count > 0 {
let match = objects[0] as! NSManagedObject
localNickname = match.value(forKey: "nick") as! String
} else {
print("Nothing founded")
}
} catch {
print("error")
}
remoteNickname = UserNickName.text!
socketdelegate?.startCall(localNickname: localNickname, remoteNickname: remoteNickname)
delegate?.VideoChatSegue()
}
}
UIViewcontroller Code
class ViewController: UIViewcontroller, StartCallDelegate {
var localNickname: String = ""
var remoteNickname: String = ""
override func viewDidLoad() {
super.viewDidLoad()
print(localNickname)
print(remoteNickname)
}
func startCall(localNickname: String, remoteNickname: String) {
print("Action startcall func")
self.localNickname = localNickname
self.remoteNickname = remoteNickname
}
startCall func not working
You need to define delegate in viewcontroller' ViewDidLoad
let objOardView = CardView() // this is only test purpose
objOardView.socketdelegate = self

Swift custom updateUI() function does not work on viewDidLoad

I'm working on an app, that should request some data from my server. I'm using Alamofire to do that, and then use SWXMLHash to parse the XML data. There are two View Controllers, on the first one I can write a shipment number, then override function prepareForSegue and send that number to the next View Controller that should display data from server and updateUI on viewDidLoad, but it does not. Where is a problem?
My Class:
class Shipment {
private var _shipmentNumber: String!
private var _shipmentStatus: String!
private var _trackURL: String!
var shipmentNumber: String {
if _shipmentNumber == nil {
_shipmentNumber = ""
}
return _shipmentNumber
}
var shipmentStatus: String {
if _shipmentStatus == nil {
_shipmentStatus = ""
}
return _shipmentStatus
}
init(spNumber: String) {
self._shipmentNumber = spNumber
_trackURL = "..."
}
func requestXmlInformation(completed: DownloadComplete) {
let url = NSURL(string: _trackURL)!
Alamofire.request(.GET, url).responseData { response in
if let xmlToParse = response.data as NSData! {
let xml = SWXMLHash.parse(xmlToParse)
do {
let xmlSpWeight = try xml["fmresultset"]["resultset"]["record"]["field"].withAttr("name", "ТotalWeight")["data"].element!.text! as String
self._shipmentStatus = xmlSpStatus
print(self._shipmentStatus)
} catch let err as NSError {
print(err.debugDescription)
}
}
}
}
}
My Second View Controller
#IBOutlet weak var numberLbl: UILabel!
#IBOutlet weak var weightLbl: UILabel!
#IBOutlet weak var statusLbl: UILabel!
#IBOutlet weak var packageQtyLbl: UILabel!
var shipment: Shipment!
override func viewDidLoad() {
super.viewDidLoad()
shipment.requestXmlInformation { () -> () in
self.updateUi()
print(self.statusLbl.text)
}
}
updateUI function:
func updateUi() {
numberLbl.text = shipment.shipmentNumber
weightLbl.text = shipment.shipmentWeight
statusLbl.text = shipment.shipmentStatus
packageQtyLbl.text = shipment.shipmentPackageQty
}
It prints data in terminal but i think updateUI function does not work.
Make sure that the code in your requestXmlInformation closure is called on the main thread. You shouldn't update the UI in background threads.
shipment.requestXmlInformation { () -> () in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.updateUi()
print(self.statusLbl.text)
})
}
Also, you don't seem to call the complete closure anywhere in your requestXmlInformation method

Alamofire returns nil always in request

Usually Alamofire working nice with simple urls like:
"http://somesite.com/folder/file.json"
But when I use:
"http://somesite.com/folder/(jsonName.text).json
it always give me a nil... jsonName is a TextField as well...
That's the whole Controller:
import UIKit
import CoreLocation
import Alamofire
import SwiftyJSON
import CoreData
typealias CompletionHandler = (obj:AnyObject?, error:Bool?) -> Void
class LoginViewController: UIViewController, UITabBarControllerDelegate, UITextFieldDelegate, NSURLConnectionDelegate {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
#IBOutlet weak var wePrepareQuestLabel: UILabel!
#IBOutlet weak var downQuestProgres: UIActivityIndicatorView!
#IBOutlet weak var doNotCloseAppLabel: UILabel!
#IBOutlet weak var loginBgImage: UIImageView!
#IBOutlet weak var EmptyCodeError: UILabel!
#IBOutlet weak var loginTabBarItem: UITabBarItem!
#IBOutlet weak var QuestCodeTextField: UITextField!
#IBOutlet weak var loginTextFieldImage: UIImageView!
#IBOutlet weak var downloaded: UIButton!
#IBOutlet weak var createQuestButton: UIButton!
#IBAction func createQuest(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("WebViewController") as! UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
let Path: String = ""
#IBAction func QuestFetchButton(button: UIButton) {
if QuestCodeTextField.text.isEmpty {
EmptyCodeError.hidden = false
}
else if IJReachability.isConnectedToNetwork() {
}
else
{
QuestCodeTextField.hidden = true
button.hidden = true
EmptyCodeError.hidden = true
createQuestButton.hidden = true
doNotCloseAppLabel.hidden = false
wePrepareQuestLabel.hidden = false
loginTextFieldImage.hidden = true
downQuestProgres.hidden = false
self.downloaded.hidden = false
// questDownloadSaveJSON()
var objThisVC = LoginViewController()
objThisVC.callAndGetResponse { (obj, error) -> Void in
if (obj != nil) {
self.setUpDataInCoreData(obj)
print("ALL DIE")
self.performSegueWithIdentifier("QuestsListViewController", sender: nil)
}
else {
println("Response nil!!")
}
}
}
}
var file:NSFileHandle?
var pathURL: NSURL
{
let folder = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
let path = folder.stringByAppendingPathComponent("\(QuestCodeTextField.text).json")
let url = NSURL(fileURLWithPath: path)
return url!
}
var code: String = ""
override func viewDidLoad() {
super.viewDidLoad()
QuestCodeTextField.text = code
self.QuestCodeTextField.delegate = self;
}
func setUpDataInCoreData(obj:AnyObject?){
println("Web Serviece Response \(obj)")
let dirEvent = obj as! NSDictionary
var aryEvent = dirEvent.valueForKey("events") as! NSArray
var indexEvent : Int = 0;
for (dirContent) in aryEvent
{
// Create Event Instance
var newItem: Events = NSEntityDescription.insertNewObjectForEntityForName("Events", inManagedObjectContext: self.appDelegate.cdh.backgroundContext!) as! Events
newItem.title = dirContent.valueForKey("title") as! String
newItem.indexID = String(indexEvent++) as String
println(newItem.title)
println(newItem.indexID)
var indexContent : Int = 0;
var aryContent = dirContent.valueForKey("content") as! NSArray
for (dirContentDetail) in aryContent{
var contentEntity: Content = NSEntityDescription.insertNewObjectForEntityForName("Content", inManagedObjectContext: self.appDelegate.cdh.backgroundContext!) as! Content
contentEntity.content_type = dirContentDetail.valueForKey("content_type") as! String
contentEntity.visible = dirContentDetail.valueForKey("visible") as! Bool
contentEntity.indexID = String(indexContent++) as String
println(contentEntity.content_type)
println(contentEntity.visible)
if contentEntity.content_type == "text"{
contentEntity.data_type = dirContentDetail.valueForKey("data") as! String
}
else if contentEntity.content_type == "image" || contentEntity.content_type == "audio" || contentEntity.content_type == "video" || contentEntity.content_type == "choice" {
contentEntity.data_type = ""
if (dirContentDetail.valueForKey("data") != nil && dirContentDetail.valueForKey("data")?.count>0 )
{
var indexImage : Int = 0;
var aryDTImages = dirContentDetail.valueForKey("data") as! NSArray
if aryDTImages.count > 0 {
for strContentDetail in aryDTImages as! [String]{
var objDtImg : DataTypeImage = NSEntityDescription.insertNewObjectForEntityForName("DataTypeImage", inManagedObjectContext: self.appDelegate.cdh.backgroundContext!) as! DataTypeImage
var strURL : NSString = NSString(string: strContentDetail)
objDtImg.urlString = strURL as String
objDtImg.indexID = String(indexImage++) as String
objDtImg.dtImages = contentEntity
// her have to set image to content
contentEntity.content = newItem
}
}
}
}
// here have to set entity to content
contentEntity.content=newItem
}// this is the end of content for loop
}// end of aryEvent
// here to save statement
self.appDelegate.cdh.saveContext(self.appDelegate.cdh.backgroundContext!)
// self.table.reloadData()
}
func callAndGetResponse(complitionHandler : CompletionHandler){
complitionHandler(obj: nil, error: true)
Alamofire.request(.GET, "http://g57732cr.bget.ru/\(QuestCodeTextField.text).json").responseJSON() {
(_, _, data, error) in
if error == nil {
complitionHandler(obj: data, error: false)
}
else{
complitionHandler(obj: nil, error: true)
self.performSegueWithIdentifier("QuestsListViewController", sender: nil)
}
// Fetch all data from Core Data
//self.fetchAllData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Hide keyboard by tap on the rest of the view
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
view.endEditing(true)
}
//ReturnButton hides keyboard
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "QuestsListViewController"){
var destination = segue.destinationViewController as! UINavigationController
let VC = destination.topViewController as! QuestListViewController
VC.questCode = self.QuestCodeTextField.text
}
}
}

Resources