I would like to know how should I behave if I got several articles in table view controller, which are loaded and parsed from some API. Then I would like to click on some article to view his detail.
Should I load all articles on start up with all data and then pass concrete whole article to next detail table controller or just send article id and in new table controller load again whole one article with passed id?
I think that is much better second method, but have no idea how to do it. Any help? Thanks a lot.
EDIT: added code
MainTableViewController:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let articleId = articles[indexPath.row].Id
let destination = DetailTableViewController()
destination.articleId = articleId
destination.performSegue(withIdentifier: "Main", sender: self)
}
DetailTableViewController:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
// Vyzkoušíme jestli jsme připojeni do internetu
if Helper.hasConnectivity() {
// Zapneme načítací obrazovku
setLoadingScreen()
// Načteme jídla
loadMainArticles()
} else {
promptAlert(title: "Upozornění", message: "Ujistěte se, že Vaše zařízení je připojené k internetu")
}
}
private func loadMainArticles() {
ApiService.sharedInstance.fetchArticle(part: "GetArticle", articleId: "brananske-posviceni--spravna-lidova-zabava-s-pecenou-husou") { (articles: [Article]) in
self.removeLoadingScreen()
self.tableView.separatorStyle = .singleLine
if articles.count == 0 {
self.promptAlert(title: "Upozornění", message: "Žádná data")
}
self.selectedArticle = articles[0]
self.tableView.reloadData()
}
}
ApiService:
func fetchArticle(part: String, articleId: String, completion: #escaping ([Article]) -> ()) {
var Id = ""
var Title = ""
var Content = ""
var Picture = ""
var PublishDate = ""
let url = NSURL(string: "http://xxx")
URLSession.shared.dataTask(with: url! as URL) { (data, response, error) in
if error != nil {
print(error as Any)
return
}
do {
let json = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments)
var articles = [Article]()
for dictionary in json as! [[String: AnyObject]] {
.
.
.
let article = Article(Id: Id, Title: Title, Content: Content, Picture: Picture, PublishDate: PublishDate, Categories: Categories)
articles.append(article!)
}
DispatchQueue.main.async(execute: {
completion(articles)
})
}
}.resume()
}
The problem is that when I do the segue after click on row, then should loadMainArticles. The method is triggered, but always stops on URLSession row and immediately jump to resume() and the completion block is never triggered. Is there any reason why?
This is a choice that should be done according to article data model size.
You should pay attention to which data you need to show on TableView single cell and which on Article detail page.
I suppose you to show:
Title and posted hour in TableView
Title, hour, long description, maybe some image in Detail page
In this case i would reccommend you to download only title and hour for each article item, and then, in detail page, download single item details (avoid to download unused content, since user could not open every item).
Otherwise, if amounts of data are similar, download all informations on first connection and open detail page without making any other network request.
I think that is much better second method, but have no idea how to do it.
You need to retrieve article id from TableView selected cell and pass it to DetailPageViewController using prepareForSegue. In DetailPageViewController ViewDidLoad send article id to your backend api and retrieve article details to show.
Related
So I have an app that lets you search for words and gives you the definition and other details about it. I use 2 different apis so if you use a wildcard search (e.g. ?OUSE) you get all the possibilities and if you put in the whole word you just get the one result.
To cut down on API usage, when run for a single word I collect all the data in a WordDetail object. Similary, when run for a wildcard search, each word is created as a WordDetail object but with a lot of missing data.
My plan is, for wildcard search, when you select a specific word, it'll then go use the API again and retrieve the data, update the array, and then navigate you to the DetailViewController.
My problem is (I think), it's navigating to the DetailViewController before it's updated the array. Is there a way to make things wait before it has all the information before navigating?
The did select function looks like this...
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var word: WordDetails?
word = results[indexPath.row]
if word?.results.count == 0 {
fetchWords(word: word!.word, updating: true)
}
print(word?.word)
print(word?.pronunciation)
let detailVC = TabBarController()
detailVC.selectedWord = word
detailVC.navigationItem.title = word?.word.capitalizingFirstLetter()
tableView.deselectRow(at: indexPath, animated: true)
navigationController?.pushViewController(detailVC, animated: true)
}
and the update to the array happens here...
func parseJSON(resultData: Data, update: Bool){
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(WordDetails.self, from: resultData)
if update {
if let row = self.results.firstIndex(where: {$0.word == decodedData.word}) {
self.results[row] = decodedData
}
} else {
results.append(decodedData)
DispatchQueue.main.async {
self.resultLabel.text = "\(self.results.count) results found"
self.resultsView.reloadData()
}
}
} catch {
print(error)
}
}
could be a timing problem or might be a stupid approach. My alternative is to just run the api call again in the DetailViewController for words that are missing data as they came from a wildcard search.
UPDATE
Found a solution using DispatchSemaphore
Define it globally
let semaphore = DispatchSemaphore(value: 0)
Ask the code to wait for a signal before proceding, which I added to the didSelectRowAt function
_ = semaphore.wait(timeout: .distantFuture)
And then send a signal when the code has done what it needed to do e.g.
if update {
if let row = self.results.firstIndex(where: {$0.word == decodedData.word}) {
self.results[row] = decodedData
DispatchQueue.main.async {
self.resultsView.reloadData()
}
semaphore.signal()
}
}
Which then allows the rest of the code to carry on. Has worked perfectly in the few test cases I've tried.
I'm loading my UITableView from an Api call but although the data is retrieved fairly quickly, there is a significant time delay before it is loaded into the table. The code used is below
import UIKit
class TrackingInfoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var table : UITableView?
#IBOutlet var indicator : UIActivityIndicatorView?
#IBOutlet var spinnerView : UIView?
var tableArrayList = Array<TableData>()
struct TableData
{
var dateStr:String = ""
var nameStr:String = ""
var codeStr:String = ""
var regionStr:String = ""
init(){}
}
override func viewDidLoad() {
super.viewDidLoad()
table!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
spinnerView?.hidden = false
indicator?.bringSubviewToFront(spinnerView!)
indicator!.startAnimating()
downloadIncidents()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func BackToMain() {
performSegueWithIdentifier("SearchToMainSegue", sender: nil)
}
//#pragma mark - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1 //BreakPoint 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArrayList.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell
cell.incidentDate.text = tableArrayList[indexPath.row].dateStr
cell.incidentText.text = tableArrayList[indexPath.row].nameStr
cell.incidentCode.text = tableArrayList[indexPath.row].codeStr
cell.incidentLoctn.text = tableArrayList[indexPath.row].regionStr
return cell //BreakPoint 4
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
AppDelegate.myGlobalVars.gIncName = tableArrayList[indexPath.row].nameStr
AppDelegate.myGlobalVars.gIncDMA = tableArrayList[indexPath.row].codeStr
performSegueWithIdentifier("SearchResultsToDetailSegue", sender: nil)
}
func alertView(msg: String) {
let dialog = UIAlertController(title: "Warning",
message: msg,
preferredStyle: UIAlertControllerStyle.Alert)
dialog.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
presentViewController(dialog,
animated: false,
completion: nil)
}
func downloadIncidents()
{
var event = AppDelegate.myGlobalVars.gIncName
var DMA = AppDelegate.myGlobalVars.gIncDMA
if event == "Enter Event Name" {
event = ""
}
if DMA == "Enter DMA" {
DMA = ""
}
let request = NSMutableURLRequest(URL: NSURL(string: "http://incident-tracker-api-uat.herokuapp.com/mobile/events?name=" + event)!,
cachePolicy: .UseProtocolCachePolicy,
timeoutInterval: 10.0)
request.HTTPMethod = "GET"
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if error != nil {
self.alertView("Error - " + error!.localizedDescription)
}
else {
do {
var incidentList: TableData
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) as? Array<Dictionary<String, AnyObject>> {
for item in json {
if let dict = item as? Dictionary<String, AnyObject> {
incidentList = TableData()
if let nameStr = dict["name"] as? String {
incidentList.nameStr = nameStr
}
if let codeStr = dict["dma"] as? String {
incidentList.codeStr = codeStr
}
if let dateStr = dict["supplyOutageStart"] as? String {
let tmpStr = dateStr
let index = tmpStr.startIndex.advancedBy(10)
incidentList.dateStr = tmpStr.substringToIndex(index)
}
if let regionStr = dict["region"] as? String {
incidentList.regionStr = regionStr
}
self.tableArrayList.append(incidentList)
}
}
self.spinnerView?.hidden = true
self.indicator?.stopAnimating()
self.table?.reloadData() //BreakPoint 3
}
}catch let err as NSError
{
self.alertView("Error - " + err.localizedDescription)
}
}
})
task.resume() //BreakPoint 1
}
When the class is run, it hits BreakPoint 1 first and then hits BreakPoint 2 and then quickly goes to BreakPoint 3, it then goes to BreakPoint 2 once more. Then there is a delay of about 20 to 30 seconds before it hits Breakpoint 4 in cellForRowAtIndexPath() and the data is loaded into the UITableView. The view is displayed quickly afterwards.
The data is retrieved quite quickly from the Web Service so why is there a significant delay before the data is then loaded into the tableView? Is there a need to thread the Web Service method?
You are getting server response in a background thread so you need to call the reloadData() function on the UI thread. I am suspecting that the wait time can vary depending on whether you interact with the app, which effectively calls the UI thread, and that's when the table actually displays the new data.
In a nutshell, you need to wrap the self.table?.reloadData() //BreakPoint 3 with
dispatch_async(dispatch_get_main_queue()) {
// update some UI
}
The final result would be
Pre Swift 3.0
dispatch_async(dispatch_get_main_queue()) {
self.table?.reloadData()
}
Post Swift 3.0
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
The table view should begin to reload in a fraction of a second after you call tableView.reloadData().
If you make UI calls from a background thread, however, the results are "undefined". In practice, a common effect I've seen is for the UI changes to take an absurdly long time to actually take effect. The second most likely side-effect is a crash, but other, strange side-effects are also possible.
The completion handler for NSURLSession calls is run on a background thread by default. You therefore need to wrap all your UI calls in a call to dispatch_async(dispatch_get_main_queue()) (which is now DispatchQueue.main.async() in Swift 3.)
(If you are doing compute-intensive work like JSON parsing in your closure it's best to do that from the background so you don't block the main thread. Then make just the UI calls from the main thread.)
In your case you'd want to wrap the 3 lines of code marked with "breakpoint 3" (all UI calls) as well as the other calls to self.alertView()
Note that if you're sure the code in your completion closure is quick you can simply wrap the whole body of the closure in a call to dispatch_async(dispatch_get_main_queue()).
Just make sure you reload your tableview in inside the Dispatch main async, just immediately you get the data
I have a table view controller and above the cell is a segmented control. The segmented control has 3 options. Past Posts, Current Posts, and Future Posts. I am trying to figure out how to load the specific data into the table view depending on what index is selected on the segmented control.
For example if Past Posts is selected I want to load the Past Post data from Parse Server into the table view. Or of Future Posts is selected load the Future Posts date from Parse Server into the table view.
I am not at all sure how to load the "selected" data, then remove and load different data if the index changes. Any help is much appreciated!
Also, I know how to fetch data from Parse Server. I only mention that to explain where my data is coming from.
I would do something creating a controller that performs the fetch, the parsing, and returns a closure with the associated identifier if it ever changes, you can still use this approach. Something along these lines.
UPDATE
With help from Rob's answer I wanted to put a little context into my answer for completeness.
typealias PostsCompletionClosure = (requestIdentifier : String, posts : [Post])->Void
class PostController {
func fetchPastPosts(requestIdentifier : String,
completion : PostsCompletionClosure,
queue : dispatch_queue_t?) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let queryParams = ["status" : "past"]
self.performQuery(queryParams, completion: { (requestID, posts) in
dispatch_async(queue != nil ? queue : dispatch_get_main_queue()) {
completion(requestIdentifier : requestIdentifier, posts : posts)
}
})
}
}
func fetchCurrentPosts(requestIdentifier : String,
completion : PostsCompletionClosure,
queue : dispatch_queue_t?) {
// Same as Above
}
func fetchFuturePosts(requestIdentifier : String,
completion : PostsCompletionClosure,
queue : dispatch_queue_t?) { {
// Same as Above
}
private func performQuery(queryParams: [String : String],
completion : PostsCompletionClosure) {
let query = PFQuery(className: "Posts")
for {key, value) in queryParams {
query.whereKey(key, equalTo: value)
}
query.findObjectsInBackgroundWithBlock { objects, error in
guard let error == nil else {
// Handle Error
return
}
if let results = objects as? [Post] {
dispatch_get_main_queue()) {
completion(requestIdentifier : requestIdentifier, posts : posts)
}
})
}
}
You can even create a post request queue for the segment requests, and cancel all prior operations if you are about to start a new one, thus never even giving it an opportunity to reload your data in the first place.
Here is a possible approach on how to implement the viewController :)
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet var segnmentControl: UISegmentedControl!
var posts: [Post]?
var activeRequestId: String = ""
// This should prolly be injected or a singleton
let postsController = PostController()
override func viewDidLoad() {
super.viewDidLoad()
didSelectSelegment(segnmentControl)
}
#IBAction func didSelectSelegment(sender: UISegmentedControl) {
posts = nil
tableView.reloadData()
activeRequestId = "\(sender.selectedSegmentIndex)"
switch sender.selectedSegmentIndex {
case 0:
self.postsController.fetchPastPosts(activeRequestId, completion: { (requestIdentifier, posts) in
self.reloadDataWith(requestIdentifier, posts : [Post])
})
case 1:
self.postsController.fetchCurrentPosts(activeRequestId, completion: { (requestIdentifier, posts) in
self.reloadDataWith(requestIdentifier, posts : [Post])
})
case 2:
self.postsController.fetchFuturePosts(activeRequestId, completion: { (requestIdentifier, posts) in
self.reloadDataWith(requestIdentifier, posts : [Post])
})
default:
fatalError("unexpected segment index")
}
}
func reloadDataWith(requestIdentifier : String,
posts : [Post]) {
if self.requestIdentifier == requestIdentifier {
self.posts = posts
self.tableView.reloadData()
}
}
}
The basic idea would be that as the segmented control changes, you would initiate a PFQuery that would populate your model, and then trigger the reloading of the table. For example, something like:
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var posts: [Post]?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func didChangeValueForSegmentedControl(sender: UISegmentedControl) {
// first empty the table
posts = nil
tableView.reloadData()
// prepare new query
let query = PFQuery(className: "Posts")
switch sender.selectedSegmentIndex {
case 0:
query.whereKey("status", equalTo: "past")
case 1:
query.whereKey("status", equalTo: "current")
case 2:
query.whereKey("status", equalTo: "future")
default:
fatalError("unexpected segment index")
}
// now perform query
query.findObjectsInBackgroundWithBlock { objects, error in
guard error == nil else {
// report error
return
}
guard let searchResults = objects as? [Post] else {
// handle situation where results were not an array of `Post` objects
return
}
self.posts = searchResults
self.tableView.reloadData()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts?.count ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PostCell
let post = posts![indexPath.row]
// configure `cell` using `post`
return cell
}
}
Now, those whereKey clauses are certainly not right, and that would change depending how your object model was set up, but this illustrates the basic idea. Initiate PFQuery on the basis of which segmented control was selected and then update the results accordingly.
Now, this all makes a lot of assumptions (that you've defined your table view and specified the view controller as its data source; that you've hooked up the outlet for the table view; that you've hooked up the IBAction for valueChanged on the segmented control; that you've defined a cell prototype with a custom cell type; etc.), but it illustrates the key parts of the solution.
I'm currently in the process of creating an app to display the latest football scores. I've connected to an API through a URL and pulled back the team names for the english premier league into an array of strings.
The problem seems to come from populating the iOS table view that I intend to display the list of teams with. The data appears to be pulled from the API fine, but for some reason the TableView method which creates a cell and returns it doesn't seem to be called. The only time I can get the method to be called is when I actually hard code a value into the array of team names.
Here is my code:
class Main: UIViewController {
var names = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let URL_String = "https://football-api.com/api/?Action=standings&APIKey=[API_KEY_REMOVED]&comp_id=1204"
let url = NSURL(string: URL_String)
let urlRequest = NSURLRequest(URL: url!)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler: {
(data, response, error) in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
if let teams = json["teams"] as? [[String : AnyObject]] {
for team in teams {
if let name = team["stand_team_name"] as? String {
self.names.append(name)
}
}
}
} catch {
print("error serializing JSON: \(error)")
}
})
task.resume()
}
// Number of Sections In Table
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
// Number of Rows in each Section
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
// Sets the content of each cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
cell.textLabel?.text = names[indexPath.row]
return cell
}
}
Just wondering if anyone can point me in the right direction here. This code doesn't crash or throw any errors, it just refuses to load a table view. The only reason I can possibly think of is that the array of team names is empty after completing a request to the API. However I've set breakpoints throughout and checked the values of local variables and the desired information is being pulled from the API as intended...
you are in the correct way , just refresh the table using reloadData once you got the new data from API
if let teams = json["teams"] as? [[String : AnyObject]] {
for team in teams {
if let name = team["stand_team_name"] as? String {
self.names.append(name)
}
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.yourtableViewname.reloadData()
})
}
Im a just starting with programming apps in Xcode 7 / Swift 2.0
Im am pretty far with developing my ideas, but I can't seem to get the error handling to work.
The viewcontroller it concerns is presenting dates where and when our band plays.
In this Viewcontroller I call Json data from our online server and parse it into a tableview. It all works. But i want the following things to happen too.
If there is no connection whatsoever (wifi/4G/3G) perform a segue (No Connection)
If the server or the php script is unreachable, perform a segue (server error
)
If there is no data available (as in Empty Array) Just give a message "There are no dates set."
The Json I get from my PHP script:
(
{
date = "some date";
description = "Some description";
location = "Some location";
others = "some details";
showtime = "some time";
},
{
date = "some date";
description = "Some description";
location = "Some location";
others = "some details";
showtime = "some time";
}
)
This is the ViewController
import UIKit
class GigsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var gigsdata: NSArray = []
override func viewDidLoad() {
super.viewDidLoad()
let logo = UIImage(named: "where_is_header_navigationController.jpg")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
func dataOfJson(url: String) -> NSArray {
let gigsdata = NSData(contentsOfURL: NSURL(string: url)!)
let jsonArray: NSArray = try! NSJSONSerialization.JSONObjectWithData(gigsdata!, options: .MutableContainers) as! NSArray
return jsonArray
}
gigsdata = dataOfJson("http://www.mydomain.eu/app/myscript.php")
}// end of viewDidLoad
// MARK: Table View Delegate Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if gigsdata.count != 0 {
return gigsdata.count
} else {
return 1
}
}
func allowMultipleLines(tableViewCell:UITableViewCell) {
tableViewCell.textLabel?.numberOfLines = 0
tableViewCell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("GigsCell")! as UITableViewCell
// setting the text color
cell.textLabel?.textColor = UIColor.whiteColor()
//Getting the JSON data and turn it into objects
let maingigsdata = (gigsdata[indexPath.row] as! NSDictionary)
//setting constants for the detailview
let gigsDate = maingigsdata["date"] as! String
let gigsLocation = maingigsdata["location"] as! String
// Setting the number of lines per row
cell.textLabel!.numberOfLines = 2
// Filling the cell with data
cell.textLabel!.text = ("\(gigsDate) \n\(gigsLocation)")
// setting the beackground color when selected
let backgroundView = UIView()
backgroundView.backgroundColor = UIColor.darkGrayColor()
cell.selectedBackgroundView = backgroundView
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Like i said, im fairly new to this, so please dont go around and name all kinds of proceduresm, functions or things like that.
Please don't think that I don't try myself, but 'm stuck now for two weeks.
The thing I saw a lot on videos and tutorials was the DO TRY CATCH thing.
But implementing that as good as I can gave me just all kinds of errors, so I must be doing something wrong there.
I hope that there is someone out there who can help me out and make me a lot wiser as I am today!
You should use NSURLRequest or some lib like Alamofire to fetch the data. NSData contentsOfURL is not asynchronous and in your case blocks the main thread. I wonder if you can compile your code as NSData contentOfURL throws and exception, which must be catched. Check the domain of NSError object, which is thrown. It can be e.g. NSURLErrorDNSLookupFailed, NSURLErrorDomain, NSURLErrorNotConnectedToInternet, NSURLErrorInternationalRoamingOff.
https://github.com/Alamofire/Alamofire
To detech the connection type:
Detect carrier connection type (3G / EDGE / GPRS)
Example of the error handling based on your code:
do {
// Blocks your UI if you do this in the main thread!
let gigsdata = NSData(contentsOfURL: NSURL(string: url)!)
}
catch let error as! NSError {
if error.domain == NSURLErrorNotConnectedToInternet {
// If you do the data fetch using the background queue then this must be dispatched to the main queue:
performSegueWithIdentifier("noInternet", sender: self)
}
}
For the 1st and 2nd issue I came up with the following working code:
// performing a first check if there is an connection based on the HTTPStatusCode 200
Alamofire.request(.GET, "http://www.google.com")
.responseJSON { response in
if response.response?.statusCode == 200 {
print("Code is 200 and good")
}else{
print("Code is not 200 and therefor bad")
self.performSegueWithIdentifier("NoConnectionSegue", sender: self)
}
}
I implemented the code in the first view controller of my app and the 'NoConnectionSegue' is a view controller that "blocks" the whole screen with a message that the app is not usable without an internet connection and a friendly request to close the app and try later.
Of course the url "google.com" can be replaced with your own domain.
For the 3rd issue I had the following solution.
The viewcontroller is a TableView with cells populated by a json file on a remote server. At the end of the viewDidLoad I check if the array.count is less then 1.
If so, then perform a segue to a new viewcontroller of the kind: "Present Modally" and the presentation: "Over current context".
This way I don't get the navigationbar that I used in the previous Tableview.
Leaving the original Tableview controller with one empty cell invisable in the background.
It might not be the cleanest and the best way. But at least I got what I wanted.
the code:
// check if there are any gigs, otherwise perform segue to NoGigs
if self.arrRes.count <= 1 {
self.performSegueWithIdentifier("NoGigsSegue", sender: self)
}