Cant pass data between view controllers using segue - ios

I am trying to get my app to call to an API, retrieve information about a movie based on a user search, and then pass that data to the next view using segue. Everything seems to be working fine up until the point where the data is supposed to be getting transferred over. My two view controllers and the file where i call my API are below.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
var movieManager = MovieManager()
var movieTitle = ""
var movieDescription = ""
var results: [Results] = []
override func viewDidLoad() {
movieManager.delegate = self
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
//MARK: - Movie Manager Methods
extension ViewController: MovieManagerDelegate {
func didUpdateMovie(title: String?, description: String?, resultsList: [Results]?) {
movieTitle = title!
movieDescription = description!
results = resultsList!
print("\(movieTitle) \n \(movieDescription)")
}
func didFailWithError(error: Error) {
print("error")
}
}
//MARK: - Search Bar Methods
extension ViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
movieManager.searchMovie(for: searchBar.text!)
searchBar.text = ""
searchBar.resignFirstResponder()
performSegue(withIdentifier: "goToResults", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResults" {
if let destinationVC = segue.destination as? ResultsListViewController {
destinationVC.movieTitle = self.movieTitle
}
}
}
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
searchBar.resignFirstResponder()
return true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
import UIKit
class ResultsListViewController: UIViewController {
#IBOutlet weak var movieName: UILabel!
var movieTitle: String = ""
override func viewDidLoad() {
super.viewDidLoad()
movieName.text = movieTitle
}
}import UIKit
class ResultsListViewController: UIViewController {
#IBOutlet weak var movieName: UILabel!
var movieTitle: String = ""
override func viewDidLoad() {
super.viewDidLoad()
movieName.text = movieTitle
}
}
import Foundation
protocol MovieManagerDelegate {
func didUpdateMovie(title: String?, description: String?, resultsList: [Results]?)
func didFailWithError(error: Error)
}
struct MovieManager {
var movieTitle: String?
var movieDescription: String?
var results: [Results]?
var delegate: MovieManagerDelegate?
let baseURL = "https://imdb-api.com/en/API/SearchMovie/(APIKEYHERE)/"
func searchMovie(for userSearch: String){
let urlString = "\(baseURL)\(userSearch)"
if let url = URL(string: urlString){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
let movieInfo = self.parseJSON(safeData)
self.delegate?.didUpdateMovie(title: movieInfo.0!, description: movieInfo.1!, resultsList: movieInfo.2)
}
}
task.resume()
}
}
func parseJSON(_ data: Data) -> (String?, String?, [Results]) {
let decoder = JSONDecoder()
var movieTitle = "", movieDescription = "", searchResults: [Results] = []
do {
if let decodedData = try decoder.decode(MovieData?.self, from: data) {
movieTitle = decodedData.results.first!.title
movieDescription = decodedData.results.first!.description
searchResults = decodedData.results
// print("\(movieTitle) \n \(movieDescription)")
}
return (movieTitle, movieDescription, searchResults)
} catch {
print(error)
}
return (movieTitle, movieDescription, searchResults)
}
}

Problem is Segue to next controller before the result of API.
Try to Segue after API result
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
movieManager.searchMovie(for: searchBar.text!)
searchBar.text = ""
searchBar.resignFirstResponder()
//Segue to next controller before the result of API
performSegue(withIdentifier: "goToResults", sender: self)
}
So your segue to next controller would be after result of parseJSON or didUpdate delegate

Related

How to save data from one view controller and show in another view controller using core data

I need help with solving one problem with core data. I have a news app with two view controllers. In the main view controller I'm loading news data in table view in custom cell. Here I have a button, on which should I tap and save news to another view controller. How it looks now: How it looks So when we tap on this blue button, it should save news from the cell and display on second view controller. I have created a core data model like this: Core data model Here is code in my first view controller:
import UIKit
import SafariServices
import CoreData
class ViewController: UIViewController, UISearchBarDelegate, UpdateTableViewDelegate {
#IBOutlet weak var pecodeTableView: UITableView!
private var articles = [News]()
// private var viewModels = [NewsTableViewCellViewModel]()
private var viewModel = NewsListViewModel()
var newsTitle: String?
var newsAuthor: String?
var newsDesc: String?
var urlString: String?
var newsDate: String?
private let searchVC = UISearchController(searchResultsController: nil)
var selectedRow = Int()
override func viewDidLoad() {
super.viewDidLoad()
pecodeTableView.delegate = self
pecodeTableView.dataSource = self
pecodeTableView.register(UINib(nibName: S.CustomCell.customNewsCell, bundle: nil), forCellReuseIdentifier: S.CustomCell.customCellIdentifier)
// fetchAllNews()
viewModel.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
categoryMenu()
loadData()
}
private func loadNewsData(api: String){
let apiService = APIService(categoryCode: api)
apiService.getNewsData {(result) in
switch result{
case .success(let NewsOf):
CoreData.sharedInstance.saveDataOf(news: NewsOf.articles)
case .failure(let error):
print("Error processing json data: \(error)")
}
}
}
func reloadData(sender: NewsListViewModel) {
self.pecodeTableView.reloadData()
}
//MARK: - Networking
private func loadData(){
viewModel.retrieveDataFromCoreData()
}
//MARK: - UIView UImenu
func categoryMenu(){
var categoryAction: UIMenu{
let menuAction = Category.allCases.map { (item) -> UIAction in
let name = item.rawValue
return UIAction(title: name.capitalized, image: UIImage(systemName: item.systemImage)) { [weak self](_) in
self?.loadNewsData(api: name)
self?.loadData()
self?.reloadData(sender: self!.viewModel)
}
}
return UIMenu(title: "Change Category", children: menuAction)
}
let categoryButton = UIBarButtonItem(image: UIImage(systemName: "scroll"), menu: categoryAction)
navigationItem.leftBarButtonItem = categoryButton
}
#IBAction func goToFavouritesNews(_ sender: UIButton) {
performSegue(withIdentifier: S.Segues.goToFav, sender: self)
}
private func createSearchBar() {
navigationItem.searchController = searchVC
searchVC.searchBar.delegate = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.numberOfRowsInSection(section: section)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: S.CustomCell.customCellIdentifier, for: indexPath) as? CustomNewsCell
let object = viewModel.object(indexPath: indexPath)!
cell?.setCellWithValuesOf(object)
cell?.saveNewsBtn.tag = indexPath.row
cell?.saveNewsBtn.addTarget(self, action: #selector(didTapCellButton(sender:)), for: .touchUpInside)
return cell!
}
#objc func didTapCellButton(sender: FavouritesCell) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "SavedNews", in: context)
let newNewsSave = SavedNews(entity: entity!, insertInto: context)
newNewsSave.author = newsAuthor
newNewsSave.desc = newsDesc
newNewsSave.title = newsTitle
do {
try context.save()
savedNews.append(newNewsSave)
navigationController?.popViewController(animated: true)
} catch {
print("Error saving")
}
print("Done")
}
Also I want to show you my parsing functions and model for this: *APIService.swift*
import Foundation
class APIService{
private var dataTask: URLSessionDataTask?
public let resourceURL: URL
private let API_KEY = "e2a69f7f9567451ba484c85614356c30"
private let host = "https://newsapi.org"
private let headlines = "/v2/top-headlines?"
init(categoryCode: String){
let resourceString = "\(host)\(headlines)country=us&category=\(categoryCode)&apiKey=\(API_KEY)"
print(resourceString)
guard let resourceURL = URL(string: resourceString) else {
fatalError()
}
self.resourceURL = resourceURL
}
//MARK: - Get News
func getNewsData(completion: #escaping (Result<Articles, Error>) -> Void){
dataTask = URLSession.shared.dataTask(with: resourceURL) { (data, response, error) in
if let error = error{
completion(.failure(error))
print("DataTask error: - \(error.localizedDescription)")
}
guard let response = response as? HTTPURLResponse else{
print("Empty Response")
return
}
print("Response status code: - \(response.statusCode)")
guard let data = data else {
print("Empty Data")
return
}
do{
let decoder = JSONDecoder()
let jsonData = try decoder.decode(Articles.self, from: data)
DispatchQueue.main.async {
completion(.success(jsonData))
}
}catch let error{
completion(.failure(error))
}
}
dataTask?.resume()
}
}
And here is NewsModel.swift:
import Foundation
struct Articles: Codable {
let articles: [News]
private enum CodingKeys: String, CodingKey{
case articles = "articles"
}
}
struct News: Codable {
let author: String?
let source: Source
let title: String
let description: String?
let url: URL?
let urlToImage: URL?
let publishedAt: String?
private enum CodingKeys: String, CodingKey{
case author = "author"
case title = "title"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case description = "description"
case source = "source"
}
}
struct Source: Codable {
let name: String?
}
Here is my code in CustomNewsCell.swift:
import UIKit
protocol CustomNewsDelegate: AnyObject {
func btnFavPress(cell: CustomNewsCell)
}
private var loadImage = LoadToImage()
private var formatDate = FormatDate()
class CustomNewsCell: UITableViewCell {
weak var delegate: CustomNewsDelegate?
#IBOutlet weak var saveNewsBtn: UIButton!
#IBOutlet weak var imageOutlet: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var descLabel: UILabel!
#IBOutlet weak var authorLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCellWithValuesOf(_ news: SavedNews){
updateUI(title: news.title, url: news.url, urlToImage: news.urlToImage, publishedAt: news.publishedAt, author: news.author ?? "No author", description: news.desc, source: news.source)
}
private func updateUI(title: String?, url: URL?, urlToImage: URL?, publishedAt: String?, author: String, description: String?, source: String?){
//title
self.titleLabel.text = title
self.authorLabel.text = author
self.descLabel.text = description
//date
let dateString = formatDate.formatDate(from: publishedAt ?? "")
let date = formatDate.formatDateString(from: dateString)
self.dateLabel.text = date
//image
guard let urlToImageString = urlToImage else {return}
imageOutlet.image = nil
loadImage.getImageDataFrom(url: urlToImageString) { [weak self] data in
guard let data = data, let image = UIImage(data: data) else{
DispatchQueue.main.async {
self?.imageOutlet.image = UIImage(named: "noImage")
}
return
}
self?.imageOutlet.image = image
}
}
#IBAction func saveBtnPressed(_ sender: UIButton) {
delegate?.btnFavPress(cell: self)
}
}
First time I've tried with delegate method for this blue button, but now as you can see I've created a selector method. Maybe it's not correct and need to fix it. Here is the code in the second view controller, which should show saved news from first view controller:
import UIKit
import CoreData
var savedNews = [SavedNews]()
class FavouriteNewsViewController: UIViewController {
#IBOutlet weak var favTableView: UITableView!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var result: [SavedNews] = []
var newsTitleNew: String?
var newsDescNew: String?
var newsAuthor: String?
override func viewDidLoad() {
super.viewDidLoad()
favTableView.delegate = self
favTableView.delegate = self
fetch()
// loadSavedNews()
favTableView.register(UINib(nibName: S.FavouriteCell.favouriteCell, bundle: nil), forCellReuseIdentifier: S.FavouriteCell.favouriteCellIdentifier)
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
// fetch()
favTableView.reloadData()
}
#IBAction func goToNewsFeed(_ sender: UIButton) {
performSegue(withIdentifier: S.Segues.goToNewsFeed, sender: self)
}
}
extension FavouriteNewsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return savedNews.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = favTableView.dequeueReusableCell(withIdentifier: S.FavouriteCell.favouriteCellIdentifier, for: indexPath) as! FavouritesCell
let newRslt: SavedNews!
newRslt = savedNews[indexPath.row]
cell.favAuthor.text = newRslt.author
cell.favDesc.text = newRslt.desc
cell.favTitle.text = newRslt.title
return cell
}
func fetch() {
let request = NSFetchRequest<SavedNews>(entityName: "SavedNews")
do {
savedNews = try context.fetch(request)
} catch {
print(error)
}
}
}
And code for cell for this controller:
import UIKit
import CoreData
class FavouritesCell: UITableViewCell {
#IBOutlet weak var favImage: UIImageView!
#IBOutlet weak var favTitle: UILabel!
#IBOutlet weak var favDesc: UILabel!
#IBOutlet weak var favAuthor: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
If somebody can help with this, it will be amazing. Because I really don't how to do this. Thank you!

How to assign a value to a variable in a class from JSON or pass this value to the next function?

Hi everyone!
At the moment, I am taking a course at the Harvard computer science CS50.
My homework is almost ready, but has some incompleteness.
I cannot assign a value from a function to a variable in the class or pass
this value to the next function.
import UIKit
class PokemonViewController: UIViewController {
var url: String!
var name: String!
#IBOutlet var pokemonImage: UIImageView!
#IBOutlet var nameLabel: UILabel!
#IBOutlet var numberLabel: UILabel!
#IBOutlet var type1Label: UILabel!
#IBOutlet var type2Label: UILabel!
#IBOutlet var catchButton: UIButton!
#IBOutlet var descriptionLabel: UILabel!
// MARK: - additional properties
var currentDescURL: String!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadPokemon()
showPokemonDescription()
}
//MARK: - pokemon loading
func loadPokemon() {
guard let pokemonURL = URL(string: url) else { return }
URLSession.shared.dataTask(with: pokemonURL) { (data, _, error) in
guard let data = data else { return }
do {
let result = try JSONDecoder().decode(PokemonResult.self, from: data)
DispatchQueue.main.async {
self.navigationItem.title = self.capitalize(text: result.name)
self.nameLabel.text = self.capitalize(text: result.name)
self.numberLabel.text = String(format: "#%03d", result.id)
for typeEntry in result.types {
if typeEntry.slot == 1 {
self.type1Label.text = typeEntry.type.name
}
else if typeEntry.slot == 2 {
self.type2Label.text = typeEntry.type.name
}
}
// Create Image and Update ImageView
guard let imageURL = URL(string: result.sprites.front_default) else { return }
if let data = try? Data(contentsOf: imageURL) {
self.pokemonImage.image = UIImage(data: data)
}
self.currentDescURL = result.species.url
print(self.currentDescURL)
}
} catch let error { print(error) }
}.resume()
}
// MARK: - Get the URL of a specific Pokémon
func showPokemonDescription() {
guard let pokemonDescriptionURL = URL(string: currentDescURL) else { return }
URLSession.shared.dataTask(with: pokemonDescriptionURL) { (data, _, error) in
guard let data = data else { return }
do {
let result = try JSONDecoder().decode(PokemonDescription.self, from: data)
DispatchQueue.main.async {
// Check and get first pokemon description in English
for index in 0..<result.flavor_text_entries.count {
if result.flavor_text_entries[index].language.name == "en" {
self.descriptionLabel.text = result.flavor_text_entries[index].flavor_text
}
}
}
} catch let error { print(error) }
}.resume()
}
}
The first function loadPokemon() inside itself gets value from JSON and prints the value to the console -> print(self.currentDescURL). Moreover, if you display this value in viewWillAppear, then "nil" will be displayed in the console. I understand that the loadPokemon() function processes the values in the stream that occur at the very end. Perhaps because of this, the variable currentDescURL cannot get the value from the loadPokemon() function and the showPokemonDescription() function cannot use this value since currentDescURL is nil.
I ask you to explain to me what my mistake is and to help finish the assignment.
Move the call for method showPokemonDescription from viewWillAppear to loadPokemon after the currentDescURL property is set.
class PokemonViewController: UIViewController {
//...
var currentDescURL: String!
//...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadPokemon()
getPreferences()
// <- remove the call from here
}
//...
func loadPokemon() {
//...
self.currentDescURL = result.species.url
self.showPokemonDescription() // <- move the call here
}
//...
func showPokemonDescription() {
//...
}
}

Data persistence after call to webservice iOS

Sorry for my English.
I have many problems in achieving data persistence after call the webservice .
Everything works correctly but I need to use that data in other methods .
As seen in the image once charge data on the screen then I want to give the user the option to use them well or load new data . But not as saving the data recovery webservice .
I was trying to use NSUserDefault but neither work .
From already thank you very much , any response is helpful .
Regards!
ViewController:
class ViewController: UIViewController {
let defaults = NSUserDefaults.standardUserDefaults()
#IBOutlet weak var myLabel2: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let newVC : SecondViewController = segue.destinationViewController as! SecondViewController
let telefono = myLabel2.text!
newVC.recibirString = telefono
}
#IBAction func mostrarAlgo(sender:AnyObject) {
//something
}
}
SecondViewController:
class SecondViewController: UIViewController {
let defaults = NSUserDefaults.standardUserDefaults()
var tel: String = ""
#IBOutlet weak var myLabel1: UITextField!
#IBOutlet weak var myLabel3: UITextField!
#IBOutlet weak var myLabel4: UITextField!
#IBOutlet weak var myLabel5: UITextField!
#IBOutlet weak var myLabel6: UITextField!
#IBOutlet weak var myLabel7: UITextField!
#IBOutlet weak var myLabel8: UITextField!
var recibirString = String()
override func viewDidLoad() {
super.viewDidLoad()
myLabel1.text = recibirString
performRequestAndUpdateUI2(myLabel1.text!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func performRequestAndUpdateUI2(tel:String) {
WebService.llamarWebService (tel,completionHandler: { datos in
guard datos.count == 5 else {
self.myLabel8.text = ("El número ingresado no está registrado.")
return
}
guard datos[0] as! String == "OK" else {
print("not everything was OK")
return
}
dispatch_async(dispatch_get_main_queue()) {
self.myLabel3.text = datos[0] as? String
self.myLabel4.text = datos[1] as? String
self.myLabel5.text = datos[2] as? String
self.myLabel6.text = datos[3] as? String
self.myLabel7.text = datos[4] as? String
self.myLabel8.text = ("Usted está registrado.")
//need save this data
}
})
}
#IBAction func guardarDatos(sender: AnyObject) {
// do something
}
}
WebService:
class WebService{
var telefono = ""
class func llamarWebService(telefono:String, completionHandler: (datos:NSArray)->()){
let urlPath = "http://xxxxxxxxxxx.com.ar/xxxxxxxxxx/forwarder_number?phone=\(telefono)"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
var arreglo:NSArray!
let task = session.dataTaskWithURL(url!,completionHandler: {data,response,error -> Void in
if (error != nil){
print(error?.localizedDescription)
}
let nsdata: NSData = NSData(data: data!)
arreglo = self.retornarDatos(nsdata)
completionHandler(datos: arreglo)
})
task.resume()
}
class func retornarDatos(nsdata: NSData)-> Array<String>{
let datos = NSString(data:nsdata,encoding: NSUTF8StringEncoding)
let partes = datos?.componentsSeparatedByString(",")
var arreglo : [String] = []
for i in partes!{
arreglo.append(i)
}
return arreglo
}
}

Most of the time HTML doesn't load first time

I have this app that I made with Swift, for fun and because I'm a beginner. Basically what it does is you can enter an artist name and song name and it fetches lyrics from AZLyrics.com based on the artist and song name you entered. For some reason most of the time when I try and load lyrics the first time when I open the app it doesn't load (it loads the 2nd, 3rd, 4th etc time). Here is my code could someone please tell me how I could fix this?
First View controller
import UIKit
var lyricsWithQuotes = ""
var urlError = false
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var songName: UITextField!
#IBOutlet var artistName: UITextField!
#IBAction func search(sender: AnyObject) {
var url = NSURL(string: "http://www.azlyrics.com/lyrics/" + artistName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + "/" + songName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + ".html")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error == nil {
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!
var urlContentArray = urlContent.componentsSeparatedByString("<!-- Usage of azlyrics.com content by any third-party lyrics provider is prohibited by our licensing agreement. Sorry about that. -->")
if urlContent.containsString("It's a place where all searches end!") {
urlError = true
} else {
var lyricsArray = urlContentArray[1].componentsSeparatedByString("<br><br>")
var lyrics = lyricsArray[0] as! String
var lyricsWithoutBR = lyrics.stringByReplacingOccurrencesOfString("<br>", withString: "")
var lyricsWithoutSlashDiv = lyricsWithoutBR.stringByReplacingOccurrencesOfString("</div>", withString: "")
var lyricsWithoutI = lyricsWithoutSlashDiv.stringByReplacingOccurrencesOfString("<i>", withString: "")
var lyricsWithoutSlashI = lyricsWithoutI.stringByReplacingOccurrencesOfString("</i>", withString: "")
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
}
} else {
urlError = true
}
})
task.resume()
} else {
urlError = true
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func viewDidLoad() {
super.viewDidLoad()
artistName.delegate = self
songName.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Second View Controller
import UIKit
var lyricsComplete = ""
class ViewController2: UIViewController {
#IBOutlet var lyricsDisplay: UITextView!
override func viewDidAppear(animated: Bool) {
if urlError == true {
urlError = false
lyricsDisplay.text = "Couldn't find that song!"
} else {
lyricsComplete = lyricsWithQuotes
lyricsDisplay.text = lyricsComplete
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After your NSURLSession has completed - basically this line:
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
You have two options:
Option One - Programatically launch the view:
let storyboard = UIStoryboard(name: "STORYBOARD NAME HERE", bundle: nil)
let newVC = storyboard.instantiateViewControllerWithIdentifier("VIEW CONTROLLER IDENTIFIER HERE") as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
If you have a navigation controller:
self.navigationController?.pushViewController(newVC, animated: true)
If you don't have a navigation controller:
self.showViewController(newVC, sender: self)
Options 2 - Trigger the Segue:
performSegueWithIdentifier("SEGUE NAME HERE", sender: nil)
Then intercept the Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if(segue.identifier == "SEGUE NAME HERE"){
let newVC = segue.destinationViewController as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
}
}
If you use option 2, make sure the Segue is between the View Controllers and not attached to your button:
Like this:
Not like this:

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