How use coredata in MVC - swift

I can use Core Data in Functions but i can´t create in MVC, like this:
class addBD{
func add(){
let entityDescripition = NSEntityDescription.entityForName("Radar",inManagedObjectContext: managedObjectContext!)
let task = Radar(entity: entityDescripition!, insertIntoManagedObjectContext: managedObjectContext)
task.descricao = vlrDesc.text
task.latitude = fieldLatitude.text
task.longitude = fieldLongitude.text;
task.velocidade = picker.selectedRowInComponent(0)
managedObjectContext?.save(nil)
}
}
import UIKit
import CoreData
class adicionarRadar: UIViewController, NSFetchedResultsControllerDelegate {
func createTask() {
adic.add()
}
I have this errors:
Use of unresolved identifier 'managedObjectContext'
Use of unresolved identifier 'vlrDesc'
... all of the variables
class addBD{
func add(){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entityDescripition = NSEntityDescription.entityForName("Radar",inManagedObjectContext: managedContext)
let task = Radar(entity: entityDescripition!, insertIntoManagedObjectContext: managedContext)
task.descricao = vlrDesc.text
task.latitude = fieldLatitude.text
task.longitude = fieldLongitude.text;
task.velocidade = picker.selectedRowInComponent(0)
managedContext.save(nil)
}
}
import UIKit
import CoreData
class adicionarRadar: UIViewController, NSFetchedResultsControllerDelegate {
var velocidade = ["40","50","70","90","100","120"]
var latitude:String = ""
var longitude:String = ""
var descrip:String = ""
var velocid:NSNumber = 0.0
var task: Radar? = nil
var idPicker:Int = 0
let adic = adiciona()
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
#IBOutlet weak var fieldLatitude: UITextField!
#IBOutlet weak var fieldLongitude: UITextField!
#IBOutlet weak var picker: UIPickerView!
#IBOutlet weak var vlrDesc: UITextField!
#IBAction func adicionar(sender: AnyObject) {
if task != nil {
editTask()
} else {
createTask()
}
dismissViewController()
}
func createTask() {
adic.add()
}
func editTask() {
task?.descricao = vlrDesc.text
task?.latitude = fieldLatitude.text
task?.longitude = fieldLongitude.text
task?.velocidade = picker.selectedRowInComponent(0)
println(picker.selectedRowInComponent(0))
managedObjectContext?.save(nil)
}
func dismissViewController() {
navigationController?.popViewControllerAnimated(true)
}
func textFieldSouldReturn (textField: UITextField) -> Bool{
textField.resignFirstResponder()
return true
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
override func viewDidLoad() {
vlrDesc.text = descrip
fieldLatitude.text = latitude
fieldLongitude.text=longitude
idPicker = Int(velocid)
picker.selectRow(idPicker, inComponent: 0, animated: true)
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return velocidade[row]
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return velocidade.count
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

First, I would start by having a look here:
http://www.raywenderlich.com/85578/first-core-data-app-using-swift
That should get you started and should guide you on where you need to go.
For the first error: Use of unresolved identifier 'managedObjectContext', this is happening because you haven't actually retrieved this context from the AppDelegate
Use this in your add() function:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
Now you have access to the managed context shared throughout your app for CoreData.
For the second error, you must have not declared or instantiated these variables somewhere in your code.
EDIT: Second Error:
So, the problem is that the function does not have a reference to those variables. They are declared in a different class and thus the class addBD can not interact with them.
One solution could be to add parameters to the function func add(), try changing it to something like
func add(vlrDesc: String, etc, etc)
And when you call add, pass in the vlrDesc and other variables as arguments.

Related

How to add elements to a realm database

I am working on a simple app that catalogues information. Right now I am just trying to collect information and then add it to a realm database. Unfortunately I cannot figure it out and no matter what method I try (based on tutorials and the Realm website) I get the error "Use of unresolved identifier 'realm'.
This is the code based on the command button executing the command.
#IBAction func Submit(_ sender: Any) {
let myList = WineList()
myList.vinyard = Vinyard.text
myList.type = typeField.text
myList.name = Name.text
myList.grape = Grape.text
myList.year = Year.text
myList.price = Price.text
myList.rating = rateField.text
myList.purchased = purch
myList.notes = Notes.text
//from realm website example
try! realm.write{
realm.add(myList)
}
//from tutorials
//realm.beginWrite()
//realm.add(myList)
//try realm.commitWrite()
}
Can anyone please advise me on what I am doing wrong? I will post all of my code below.
import UIKit
import RealmSwift
class RankViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var purch = ""
#IBOutlet weak var typeField : UITextField!
#IBOutlet weak var rateField : UITextField!
#IBOutlet weak var Vinyard: UITextField!
#IBOutlet weak var Name: UITextField!
#IBOutlet weak var Grape: UITextField!
#IBOutlet weak var Year: UITextField!
#IBOutlet weak var Price: UITextField!
#IBOutlet weak var Notes: UITextField!
#IBAction func Purchased(_ sender: UISwitch) {
if (sender.isOn == true){
purch = "Yes"
}
else {
purch = "No"
}
}
let wineTypes = ["Red","White","Rose","Sparkling","Ice - Red","Ice - White", "Port","Fruit","Other"]
let wineRate = ["Hurray", "Meh", "Boo"]
var typeView = UIPickerView()
var rateView = UIPickerView()
override func viewDidLoad() {
super.viewDidLoad()
let realm = try! Realm()
print (Realm.Configuration.defaultConfiguration.fileURL)
typeView.delegate = self
typeView.dataSource = self
rateView.delegate = self
rateView.dataSource = self
Vinyard.delegate = self
Name.delegate = self
Grape.delegate = self
Year.delegate = self
Price.delegate = self
Notes.delegate = self
typeField.inputView = typeView
rateField.inputView = rateView
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
if pickerView == typeView {
// Returns for typeView
return 1
}
else if pickerView == rateView {
// Returns for rateView
return 1
}
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == typeView {
// Returns for typeView
return wineTypes.count
}
else if pickerView == rateView {
// Returns for rateView
return wineRate.count
}
return wineRate.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == typeView {
// Returns for typeView
return wineTypes[row]
}
else if pickerView == rateView {
// Returns for rateView
return wineRate[row]
}
return wineRate[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == typeView {
// Do stuff for typeView
typeField.text = wineTypes[row]
typeField.resignFirstResponder()
}
else if pickerView == rateView {
// Do stuff for rateView
typeField.text = wineRate[row]
typeField.resignFirstResponder()
}
}
#IBAction func Submit(_ sender: Any) {
let myList = WineList()
myList.vinyard = Vinyard.text
myList.type = typeField.text
myList.name = Name.text
myList.grape = Grape.text
myList.year = Year.text
myList.price = Price.text
myList.rating = rateField.text
myList.purchased = purch
myList.notes = Notes.text
//from realm website example
try! realm.write{
realm.add(myList)
}
//from tutorials
//realm.beginWrite()
//realm.add(myList)
//try realm.commitWrite()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
Year.resignFirstResponder()
Price.resignFirstResponder()
}
}
extension RankViewController : UITextFieldDelegate{
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Separate file
import Foundation
import RealmSwift
class WineList: Object {
#objc dynamic var vinyard: String?
#objc dynamic var name: String?
#objc dynamic var grape: String?
#objc dynamic var year: String?
#objc dynamic var price: String?
#objc dynamic var notes: String?
#objc dynamic var type: String?
#objc dynamic var rating: String?
#objc dynamic var purchased: String?
}
Variables only exist with the function or class they are created. So take these two functions
func getData() {
let realm = Realm()
let results = realm.objects...
}
and
func printData() {
print(results) //this won't work
}
as you can see, the var 'realm' is instantiated in getData so that var is only available within that function and would not be available within the printData function.
In your case you've instantiated the realm var within viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
let realm = try! Realm()
therefore it will only be available within the viewDidLoad function.
To correct your issue, you need to instantiate realm within the function where you're trying to use it
#IBAction func Submit(_ sender: Any) {
let myList = WineList()
...
let realm = try! Realm()
try! realm.write{
realm.add(myList)
}
to expand on that a bit. Take your RankViewController class
class RankViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var purch = ""
See the 'purch' var? That's called a 'class var' and because it's defined at a high level within the class, it would be available throughout the class.
func printData() {
print(self.purch) //this will work
}
note that I preceded purch with self. when I referenced it. To me, that's a good indicator it's a class var and makes the code more readable. However, it's not required.

Swift 4 delegates and passing textfield data

I am trying to make an app using the GoogleBooks API where I can use either a title or author or both to search for books. I am currently just working on the delegate portion to be able to pass the search terms to the results table view. However, I am getting errors with the variables I am using being let constants but I have them declared as var so I'm not sure where I am messing up.
This is the UIViewController code for the view with the two search boxes and the button:
import UIKit
protocol ViewControllerDelegate: class {
func searchInput(_ titleFromSearch: String?, authorFromSearch: String?)
}
class ViewController: UIViewController {
#IBOutlet weak var titleFromSearch: UITextField!
#IBOutlet weak var authorFromSearch: UITextField!
weak var delegate: ViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
titleFromSearch.delegate = self
authorFromSearch.delegate = self
}
override func touchesEnded(_ touches: Set<UITouch>, with event:
UIEvent?) {
super.touchesEnded(touches, with: event)
titleFromSearch.resignFirstResponder()
authorFromSearch.resignFirstResponder()
}
}
extension ViewController: UITextFieldDelegate {
func fieldsDidEndEditing(_ titleEntered: UITextField, authorEntered:
UITextField) {
if let delegateController = delegate {
delegateController.searchInput(titleFromSearch.text,
authorFromSearch: authorFromSearch.text)
}
}
}
And this is the code for the TableViewController that I have set up for the results to be displayed in.
import UIKit
import GoogleBooksApiClient
class SearchResultsTableViewController: UITableViewController {
var titleFromSearch: String?
var authorFromSearch: String?
var data = [Volume]()
override func viewDidLoad() {
super.viewDidLoad()
let session = URLSession.shared
let client = GoogleBooksApiClient(session: session)
let req = GoogleBooksApi.VolumeRequest.List(query: "Google")
let task: URLSessionDataTask = client.invoke(
req,
onSuccess: { [weak self] volumes in
self?.data = volumes.items
self?.tableView.reloadData()
},
onError: { error in
print("\(error)") }
)
task.resume()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
let item = data[indexPath.row]
cell.textLabel?.text = item.volumeInfo.title
cell.detailTextLabel?.text = item.volumeInfo.authors.first
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let destination = segue.destination as? ViewController {
destination.delegate = self
}
}
}
Here is where I get the let constant error is with these two assignment statements:
extension SearchResultsTableViewController: ViewControllerDelegate {
func searchInput(_ titleFromSearch: String?, authorFromSearch: String?)
{
titleFromSearch = titleFromSearch
authorFromSearch = authorFromSearch
}
}
I added all the code because as I said I am new to iOS and I'm not sure where this error stems from in the code.
In the two lines causing your errors:
titleFromSearch = titleFromSearch
authorFromSearch = authorFromSearch
you are attempting to assign the parameters to themselves. You want to set the parameter values to your properties of the same name. To do this, add self. to the property references:
self.titleFromSearch = titleFromSearch
self.authorFromSearch = authorFromSearch

UITableView not displaying prototype cells

I am trying to make an app that connects to chromecast to play a video on TV, up till now I am still trying to display the video links using two view controllers, one contains a webview that makes the user gets the video page, the other is to display all video links inferred from the first view to make the user select which video to cast from the page. I am able to get the links but the problem is it doesn't want to be displayed in the table view cells. I have tried many methods but I noticed, for some reason the UITableViewDataSource methods are not being called at all. Here is the code:
ViewController.swift:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
//MARK: Outlets
#IBOutlet weak var searchBar: UITextField!
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var cancelButton: UIButton!
#IBOutlet weak var searchBarTrailingConstraint: NSLayoutConstraint!
//MARK: Properties
static var videoURLs: [String] = []
//MARK: Methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
cancelButton.layer.cornerRadius = 5
cancelButton.isHidden = true
webView.delegate = self
}
func webViewDidFinishLoad(_ webView: UIWebView) {
var videoTag = ""
var embedTag = ""
let htmlCode = webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
let htmlTags = htmlCode!.components(separatedBy: "\n") as [String]
for tag in htmlTags{
var videoURL = ""
if tag.contains("<video") {
videoTag = tag.substring(from: tag.range(of: "<video")!.lowerBound)
videoTag = videoTag.substring(to: (videoTag.range(of: ">")?.upperBound)!)
if videoTag.contains("src"){
videoTag = tag.substring(from: tag.range(of: "src")!.upperBound)
for x in videoTag.characters{
if x == "\""{
continue
}else if x == "="{
continue
}else if x == ">"{
break
}else{
videoURL.append(x)
}
}
}
ViewController.videoURLs.append(videoURL)
}
if tag.contains("<embed") {
embedTag = tag.substring(from: tag.range(of: "<embed")!.lowerBound)
embedTag = embedTag.substring(to: (embedTag.range(of: ">")?.upperBound)!)
if embedTag.contains("src"){
embedTag = tag.substring(from: tag.range(of: "src")!.upperBound)
for x in embedTag.characters{
if x == "\""{
continue
}else if x == "="{
continue
}else if x == ">"{
break
}else{
videoURL.append(x)
}
}
}
ViewController.videoURLs.append(videoURL)
}
}
NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: "Done")))
}
//MARK: Actions
#IBAction func cancelPressed() {
cancelButton.isHidden = true
searchBarTrailingConstraint.constant = 0.0
UIView.animate(withDuration: 0.25) {
self.view.layoutIfNeeded()
}
searchBar.resignFirstResponder()
}
#IBAction func searchBarPressed() {
searchBarTrailingConstraint.constant = (cancelButton.frame.width + 8.0) * -1
UIView.animate(withDuration: 0.25) {
self.view.layoutIfNeeded()
}
cancelButton.isHidden = false
}
#IBAction func returnButtonPressed(_ sender: UITextField) {
cancelPressed()
if let url = URL(string: sender.text!){
if UIApplication.shared.canOpenURL(url){
let request = URLRequest(url: url)
webView.loadRequest(request)
}else{
let googleSearchURL = URL(string: "https://www.google.com/search?client=safari&q=\(url)&ie=UTF-8&oe=UTF-8")
let request = URLRequest(url: googleSearchURL!)
webView.loadRequest(request)
}
}else{
var searchString: [String] = []
var searchWord = ""
for x in (sender.text?.characters)!{
if x == " "{
searchString.append(searchWord)
searchWord = ""
}else{
searchWord.append(x)
}
}
//For appending the last word not followed by a space
if !(searchString.last == searchWord){
searchString.append(searchWord)
}
var googleSearchURL = "https://www.google.com/search?client=safari&ie=UTF-8&oe=UTF-8&q="
for element in searchString{
googleSearchURL.append(element)
if !(searchString.last == element){
googleSearchURL.append("+")
}
}
let request = URLRequest(url: URL(string:googleSearchURL)!)
webView.loadRequest(request)
}
}
#IBAction func backButtonPressed(_ sender: UIButton) {
if webView.canGoBack{
webView.goBack()
}
}
#IBAction func forwardButtonPressed(_ sender: UIButton) {
if webView.canGoForward {
webView.goForward()
}
}
}
MediaTableViewController:
import UIKit
import AVFoundation
class MediaTableViewController: UIViewController, UITableViewDataSource {
var videoURLs: [String] = []
var videoScreenshots: UIImage!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(MediaTableViewController.replyToNotification), name: nil, object: nil)
self.tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videoURLs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("NOW!\n\n\n", indexPath.count)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MediaTableViewCell
cell.videoImage.image = videoScreenshot(url: videoURLs[indexPath.count])
cell.videoURL.text = videoURLs[indexPath.count]
return cell
}
#objc func replyToNotification(){
videoURLs = ViewController.videoURLs
ViewController.videoURLs = []
}
// MARK: - Table view data source
func videoScreenshot(url: String) -> UIImage? {
let asset = AVURLAsset(url: URL(string: url)!)
let generator = AVAssetImageGenerator(asset: asset)
generator.appliesPreferredTrackTransform = true
do {
let imageRef = try generator.copyCGImage(at: CMTime(value: asset.duration.value/2, timescale: asset.duration.timescale), actualTime: nil)
return UIImage(cgImage: imageRef)
}
catch let error as NSError
{
print("Image generation failed with error \(error)")
return nil
}
}
}
MediaTableViewCell.swift:
import UIKit
class MediaTableViewCell: UITableViewCell {
#IBOutlet weak var videoImage: UIImageView!
#IBOutlet weak var videoURL: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
Here is the Main.storyboard:
You do not call reloadData() thus the tableView is idle.
To fix this the following to MediaTableViewController:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
As I see you didn't implement tableView delegate
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(MediaTableViewController.replyToNotification), name: nil, object: nil)
self.tableView.delegate = self
self.tableView.dataSource = self
}
then add this method to your controller
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
hope this will help

UILabel throwing Thread1: EXC_BAD_ACCESS (code=1, address 0x…) in Swift 2

when I would like to make the data from the valise, table view controller (SelectedCity) ,app crash and error : Thread1: EXC_BAD_ACCESS (code=1, address 0x…)
error is in line labelcity!.text = tit varibale tit not problem ,I think the problem lies in the UIlabel (labelcity)
can you help me?
AircraftSearch
class AircraftSearch: UIViewController ,SendbackDelegate{
#IBOutlet weak var Mabda: UIButton!
#IBOutlet weak var maghsad: UIButton!
#IBOutlet weak var labelcity: UILabel!
var Airurl = NSURL()
var ScrOrDstArray = [MabdaAndMaghsad]()
var origin = [String]() // save mabda
var purpose = [String]() // save maghsad
var sendDataToTableview = [String]()
var tit = String()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
GetPassCity()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func selectMabda(sender: AnyObject) {
sendDataToTableview = origin
performSegueWithIdentifier("SelectedCellSegue", sender: sender)
}
#IBAction func selectMaghsad(sender: AnyObject) {
sendDataToTableview = purpose
print(sendDataToTableview)
performSegueWithIdentifier("SelectedCellSegue", sender: sender)
}
func originAndpurpose() {
let dataCity = ScrOrDstArray
for i in dataCity{
if i.SrcOrDst == true{
origin.append(i.Name)
}else{
purpose.append(i.Name)
}
}
}
func sendNameToPreviousVC(SelectCity: String) {
print("\(tit) selected ") //return data
tit = SelectCity
labelcity!.text = tit
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SelectedCellSegue" {
if let VC = segue.destinationViewController as? SelectedCity {
VC.toTake = sendDataToTableview
VC.delegate = self
}
}
}
}
SelectedCity view
import UIKit
protocol SendbackDelegate:class {
func sendNameToPreviousVC(City:String)
}
class SelectedCity: UITableViewController {
var toTake = [String]()
var selecteCity = String()
weak var delegate: SendbackDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return toTake.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("stcell", forIndexPath: indexPath) as? mAndMCell
let nameCity = toTake[indexPath.row]
print(nameCity)
cell!.nameCityLabel.text = nameCity
return cell!
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRowAtIndexPath(indexPath) as! mAndMCell!
selecteCity = currentCell.nameCityLabel!.text as String!
sendBackIdCity(selecteCity)
navigationController?.popViewControllerAnimated(true)
}
func sendBackIdCity(name: String){
self.delegate?.sendNameToPreviousVC(name)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "backCitySegue"{
var VCOne = segue.destinationViewController as? AircraftSearch
self.delegate = VCOne
}
}
}
Instead of
#IBOutlet weak var labelcity: UILabel? = UILabel()
try:
#IBOutlet weak var labelcity: UILabel!
Consider to remove weak keyword in the property declaration. Usage of this keyword prevents just created UILabel object from it's retaining, so the object deallocates immediately.
var labelcity: UILabel? = UILabel()
Or another option is to move object instantiation into viewDidLoad method:
var labelcity: UILabel!
...
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
//you code for subview adding into view controller's view
labelcity = label
GetPassCity()
}
I solved the problem:
override func viewDidLoad() {
super.viewDidLoad()
labelcity.text = tit
GetPassCity()
}
func sendNameToPreviousVC(SelectCity: String) {
tit = SelectCity
}

iOS Swift delegates

I'm very new to Swift, and I'm having trouble using delegates. When the user taps on a table row in AdminAddCatTableViewController, I want to drop a pin on the map at the user's current location in AdminViewController, and I'm trying to do this using a delegate. Obviously there's something wrong with my code, as the pin does not get dropped.
In AdminAddCatTableViewController, I have
import UIKit
import Firebase
protocol AddCatDelegate: class {
func addPin(sender: AdminAddCatTableViewController)
}
class AdminAddCatTableViewController: UITableViewController {
weak var delegate:AddCatDelegate?
let admin = "secret-number"
let ref = Firebase(url: "firease_url")
#IBOutlet weak var snowballGPSLabel: UILabel!
#IBOutlet weak var smokeyGPSLabel: UILabel!
#IBOutlet weak var shadowGPSLabel: UILabel!
#IBOutlet weak var spotsGPSLabel: UILabel!
#IBOutlet weak var sunnyGPSLabel: UILabel!
var catRefArray: [AnyObject] = []
var coord:String = ""
let shareData = ShareData.sharedInstance
func updateCoord() {
if let bar = self.shareData.someString {
self.coord = bar
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "updateCoord", userInfo: nil, repeats: true)
var catNameArray: [AnyObject] = []
catNameArray.append("Snowball")
catNameArray.append("Smokey")
catNameArray.append("Shadow")
catNameArray.append("Spots")
catNameArray.append("Sunny")
for i in 0...4 {
catRefArray.append(self.ref.childByAppendingPath("admin").childByAppendingPath(self.admin).childByAppendingPath(catNameArray[i] as! String))
}
catRefArray[0].observeEventType(.Value, withBlock: { snapshot in
if let value:String = snapshot.value as? String {
self.snowballGPSLabel.text = value
}
}, withCancelBlock: { error in
print(error.description)
// same for the other rows
})
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (indexPath.row == 0) {
let ref0 = self.ref.childByAppendingPath("admin").childByAppendingPath(self.admin)
ref0.updateChildValues(["Snowball": self.coord])
delegate?.addPin(self)
}
// same for other rows
}
In AdminViewController, I have
import UIKit
import MapKit
import CoreLocation
class AdminViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBAction func logOutDidTouch(sender: AnyObject) {
performSegueWithIdentifier("adminToLogin", sender: self)
}
#IBOutlet weak var mapView: MKMapView!
var locationManager: CLLocationManager!
var previousLocation : CLLocation!
var latitude = 0.0;
var longitude = 0.0;
//Declare Class Variable
let shareData = ShareData.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
//On loading the screen the map kit view is shown and the current location is found and is being updated.
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
let status = CLLocationManager.authorizationStatus()
if status == .NotDetermined || status == .Denied || status == .AuthorizedWhenInUse {
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
mapView.delegate = self
mapView.showsUserLocation = true
mapView.mapType = MKMapType(rawValue: 0)!
mapView.userTrackingMode = MKUserTrackingMode(rawValue: 2)!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
mapView.mapType = MKMapType(rawValue: 0)!
}
override func viewWillAppear(animated: Bool) {
//updates the location
locationManager.startUpdatingHeading()
locationManager.startUpdatingLocation()
}
override func viewWillDisappear(animated: Bool) {
locationManager.stopUpdatingHeading()
locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
self.latitude = newLocation.coordinate.latitude
self.longitude = newLocation.coordinate.longitude
self.shareData.someString = "\(self.latitude)" + "," + "\(self.longitude)"
print(self.shareData.someString)
}
}
extension AdminViewController: AddCatDelegate {
func addPin(sender:AdminAddCatTableViewController) {
// drop a pin
self.mapView.delegate = self
let coordinate = mapView.userLocation.coordinate
let dropPin = MKPointAnnotation()
dropPin.coordinate = coordinate
dropPin.title = "Cat"
mapView.addAnnotation(dropPin)
}
}
Well you are never setting the delegate on your AdminAddCatTableViewController, so it is always nil and never called.
Why do you even have an extension of AdminViewController? Just remove the extension and make AdminViewController implement the delegate. To set the delegate implement something like this in your AdminViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
if segue.identifier == "YourSegueIdentifier" {
if let vc = segue.destinationViewController as? AdminAddCatTableViewController {
vc.delegate = self
}
}
}