0

I have written out some JSON code, uploaded it to my FTP server, and used it in my JSON app. I have also written the codes for my app in Xcode. I use Swift. The problem is that when I run my app, nothing is returned in the UITableView. How do I make the text appear in my iOS Simulator?

UPDATE

I have followed Scriptable's guidance, and this is my new error in Xcode:

Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}

UPDATE ENDED

Here is my JSON web code (in a .json file):

         {"items":[{

            "title" : "Big Little Lies Book Review",
            "date" : "WEDNESDAY 3RD FEBRUARY, 2016",
            "content" : "Few spoilers ahead. I finished reading Big Little Lies by Liane Moriarty a few days ago, and I haven't stopped thinking about it since! The book is so gripping,and the characters (what I love most) are so different. You have Madeline Mackenzie, a bubbly, bright 40 year old; Celeste White, a beautiful, weak lady who is married to a rich businessman; and Jane Chapman, a quiet, 24-year old mum with a mysterious past. The novel is set in Pirriwee, Australia. These characters' children all join Pirriwee Public, beginning Kindergarden. A previous orientation day drama still lingers between the mothers, especially the victim's mum, Renata Klein, and the so-called bully's mum, Jane (at this point, we still are unaware of who the bully is.) The story leads up to the annual trivia night of the school, with the end of each chapter showing a small extract of other mothers recounting the night. A detective is questioning them regard to a murder. In these extracts, we see that there is a conflict between Madeline, Celeste, and Jane as one, and the other mothers (not as much the fathers.) Moriarty makes connections between each character, each conflict, and each personal story. As you read the book, you see these connections strengthening, then all being vividly bonded at the end. The themes of this book are bullying, domestic violence, and teenage problems. Some are clearer and more elaborate than others. She shows great research by reading various books on the topic of domestic violence, which is the burden on Celeste. Each main character (Jane, Celeste, and Madeline) portray their own emotional conflict, some being more able to share than others. In the end, these problems are solved, naturally, as they should, but one problem's answer is harsher than the others. My rating for this fantastic book would be 4.5 stars, and would recommend to older teenagers and adults. This book adaptation will look great on the big screen. Big Little Lies has been envisaged to be shown in early 2017 on HBO, and consists of 8 episodes."
        },{

            "title" : "New Allegiant poster released",
            "date" : "WEDNESDAY 3RD FEBRUARY, 2016",
            "content" : "A new Allegiant poster has been released, and I have added it to Photos. It shows Shailene's character Tris on a swirling staircase (much like a DNAstrand),and also Four (Theo James), Caleb Prior (Ansel Elgort), Christina (Zoe Kravitz), and Peter (Miles Teller.) The new slogan has also been added, saying 'Whatmakes us different ties us together.' Allegiant is out in cinemas on March 18th, 2016. Its world premiere is in New York, being on March 14th (This is not completely confirmed yet.)"
        },{

            "title" : "Allegiant stills released",
            "date" : "FRIDAY 29TH JANUARY, 2016",
            "content" : "Some more Allegiant stills have been released - as if we can't get enough! The two that we have obtained of Shailene's character, Tris, have been added to the Allegiant gallery in Photos."
        },{

            "title" : "New Big Little Lies behind the scenes photos",
            "date" : "FRIDAY 29TH JANUARY, 2016",
            "content" : "With an abundance of Big Little Lies photos, yet we have received more. Most of these are from the first scene of the book, where Shailene's character, Jane, meets Reese Witherspoon's character, Madeline. This is the last day of shooting until April. Filming is being shot in Monterey, California. Some of these photos have been added to the gallery."
        },{

            "title" : "The Divergent Fandom App",
            "date" : "FRIDAY 29TH JANUARY, 2016",
            "content" : "As if the fandom couldn't get any better, The Divergent Series released an app for the fandom to group on. This app contains the latest news and stills regarding the Divergent films. My user is @totallyshailene, feel free to contact me! Once again, Allegiant is out on March 18th, 2016, with it's world premiere happening in New York, but with no date yet announced."
        },{

            "title" : "More Big Little Lies news",
            "date" : "FRIDAY 22ND JANUARY, 2016",
            "content" : "Filming will continue for 'Big Little Lies' from January 25th to January 29th in Monterey, California. Filming will then return in April for two weeks and wrap in May. The show's executive producer has said that post-production would last for approximately six months, and the show would air in early 2017. 'Big Little Lies' is a book-to-tv adaptation, focusing on three mothers played by Shailene Woodley, Reese Witherspoon, and Nicole Kidman."
        },{

            "title" : "Allegiant twitter Q&A",
            "date" : "FRIDAY 22ND JANUARY, 2016",
            "content" : "We were all incredibly excited when The Divergent Series on Twitter (@Divergent) said that we would have a Q&A on Twitter with Shailene Woodley and Theo James (Tris and Four respectively.) Shai and Theo answered great questions, of which you can see on The Divergent Series' Twitter. Shailene talked about what we can look forward to in Allegiant, and also gave a few motivational words - as always! These short videos have been added to its gallery in Videos."
        },{

            "title" : "New Allegiant trailer released",
            "date" : "FRIDAY 22ND JANUARY, 2016",
            "content" : "With all the fans in great anticipation, new 'Allegiant' has been released! This shows more emotional scenes of Tris (Shailene Woodley) and Four (Theo James) and the futuristic society of what is beyond the wall. 'Allegiant' will be out in cinemas on March 18th, 2016. The new trailer has been added to 'Videos.'"
        },{

            "title" : "Big Little Lies has offically began filming",
            "date" : "SUNDAY 10TH JANUARY, 2016",
            "content" : "'Big Little Lies,' Shailene Woodley's new project, officially began filming in California on January 10th. We have also obtained many behind the scenes images of which I have uploaded to 'Photos.'"
        },{

            "title" : "42nd Annual People's Choice Awards",
            "date" : "WEDNESDAY 6TH JANUARY, 2016",
            "content" : "The 42nd Annual People's Choice Awards happened on Wednesday 6th January, 2016. Although Shai wasn't in attendence, she won the award for Choice Female Action Actress for 'Insurgent.' 'Insurgent' was also nominated for Choice Action Movie, but lost to 'Furious 7.' Once again, another successful night for Shailene!"
        }]}

Here is my JSON app code:

import UIKit

class NewsTableViewController: UITableViewController {

var siteURL = "http://annabellesykes.byethost11.com/shailenewoodleyfansappjson.html"
var items = [Item]()

override func viewDidLoad() {
    super.viewDidLoad()

   getLatestNews()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return items.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! NewsTableViewCell

    // Configure the cell...
    cell.titleLabel.text = items[indexPath.row].title
    cell.dateLabel.text = items[indexPath.row].date
    cell.contentLabel.text = items[indexPath.row].content

    return cell
}

func getLatestNews() {

    let request = NSURLRequest(URL: NSURL(string: siteURL)!)
    let urlSession = NSURLSession.sharedSession()
    let task = urlSession.dataTaskWithRequest(request, completionHandler: {
        (data, response, error) -> Void in

        if let error = error {
            print(error)
            return
        }

        if let data = data {
            self.items = self.parseJsonData(data)

            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                self.tableView.reloadData()
            })
        }

    })

    task.resume()
}

func parseJsonData(data: NSData) -> [Item] {

    var items = [Item]()

    do {

        let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary

        let jsonItems = jsonResult?["items"] as! [AnyObject]
        for jsonItem in jsonItems {
            let item = Item()
            item.title = jsonItem["title"] as! String
            item.content = jsonItem["content"] as! String
            item.date = jsonItem["date"] as! String
            items.append(item)
        }

    } catch {
        print(error)
    }

    return items
}
Annabelle Sykes
  • 263
  • 6
  • 17

2 Answers2

1

ok, I think the problem is that you think the first block of code you posted on your question is JSON? Its not, its HTML and Javascript. Thats why your JSON parser is failing.

You have written a webpage, not a webservice, they are very different things. You have a few options:

  • Read up on webservices and create one (recommended)
  • Use a HTML parser, download the page and take out the bits you want
  • Load the HTML into a webview and use javascript to pull out the bits you want

The last two are only there for completeness sake, you should go for the first one.

Simon McLoughlin
  • 8,293
  • 5
  • 32
  • 56
0

Your current code is just a webpage, You could create a server side script to generate and return valid JSON for a particular URL or you could just create a .json file.

For example:

create a blank file called example.json and put the following in it

 {
"items": [{
    "title": "Allegiant stills released",
    "date": "FRIDAY 29TH JANUARY, 2016",
    "content": "Some more Allegiant stills have been released - as if we can't get enough! The two that we have obtained of Shailene's character, Tris, have been added to the Allegiant gallery in Photos."
}, {
    "title": "Allegiant stills released",
    "date": "FRIDAY 29TH JANUARY, 2016",
    "content": "Some more Allegiant stills have been released - as if we can't get enough! The two that we have obtained of Shailene's character, Tris, have been added to the Allegiant gallery in Photos."
}, {
    "title": "Allegiant stills released",
    "date": "FRIDAY 29TH JANUARY, 2016",
    "content": "Some more Allegiant stills have been released - as if we can't get enough! The two that we have obtained of Shailene's character, Tris, have been added to the Allegiant gallery in Photos."
}, {
    "title": "Allegiant stills released",
    "date": "FRIDAY 29TH JANUARY, 2016",
    "content": "Some more Allegiant stills have been released - as if we can't get enough! The two that we have obtained of Shailene's character, Tris, have been added to the Allegiant gallery in Photos."
}]

}

Then upload to your server and in your iOS application use the following URL:

http://annabellesykes.byethost11.com/example.json

It would be worthwhile you reading up on generating the JSON 'on demand' though, try something like http://www.tutorialspoint.com/json/json_php_example.htm. It's probably not the best tutorial out there but should give you a good starting point and show you what your looking for.

EDIT:

This code is working for me locally..

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let request = NSURLRequest(URL: NSURL(string: "http://local.test-application/example.json")!)
        let urlSession = NSURLSession.sharedSession()
        let task = urlSession.dataTaskWithRequest(request, completionHandler: {
            (data, response, error) -> Void in

            if let error = error {
                print(error)
                return
            }

            if let data = data {

                do {

                    let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary

                    print(jsonResult)

                    let jsonItems = jsonResult?["items"] as! [String:AnyObject]
                    for jsonItem in jsonItems {
                        print(jsonItem)
                    }

                } catch {
                    print(error)
                }


            }

        })

        task.resume()

    }

With this JSON file: https://filetea.me/t1s5uHGTDlCRNudTgqIMT5Mqw

Also if your using non HTTPS URL's in your project you'll need to AllowArbitaryLoads... see http://iosdevtips.co/post/121756573323/ios-9-xcode-7-http-connect-server-error

Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • I did this, but its still the same. – Annabelle Sykes Feb 08 '16 at 11:31
  • what error are you getting now? it shouldn't be the same one as before. in your swift code you are doing `jsonResult?["items"]` so you may need to embed the JSON array in an items property, I'll update the JSON above to show what i mean – Scriptable Feb 08 '16 at 11:33
  • I will edit the question to add the new error code. Thanks, in advance, for all your help! – Annabelle Sykes Feb 08 '16 at 11:35
  • what url is the json file at? – Scriptable Feb 08 '16 at 11:41
  • it is invalid json, you have code at the bottom commented out, comments dont work in json. literally just put what i put in the file, nothing else – Scriptable Feb 08 '16 at 11:43
  • I took the commented lines out, but now the Xcode error message has gone back to what it was before: **Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}** – Annabelle Sykes Feb 08 '16 at 11:45
  • change your NSJSONReadingOptions to .AllowFragments – Scriptable Feb 08 '16 at 11:46
  • There is a new error message: **Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}** – Annabelle Sykes Feb 08 '16 at 11:52
  • change the json to what I've put above in my answer. make sure there is nothing else in the file – Scriptable Feb 08 '16 at 11:55
  • The error message is the same: **This error message now appears: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}** – Annabelle Sykes Feb 08 '16 at 12:11
  • I think you just have whitespace in there, should start with {, no spaces – Scriptable Feb 08 '16 at 12:13
  • I removed them, but the error message is still: **Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}** – Annabelle Sykes Feb 08 '16 at 12:30
  • By the way, I have set `AllowArbitaryLoads` – Annabelle Sykes Feb 08 '16 at 12:33
  • it must be the JSON document, if I use my local example.json file it works fine – Scriptable Feb 08 '16 at 13:01
  • Are there any more suggestions to what I can do? – Annabelle Sykes Feb 08 '16 at 13:03
  • yes, the file is just valid JSON, you should be able to download and edit the file for your needs – Scriptable Feb 08 '16 at 13:19
  • I pasted the exact same code, but the error is still the same. – Annabelle Sykes Feb 08 '16 at 13:26
  • must be a problem with the file, mine is working as you can see – Scriptable Feb 08 '16 at 13:30
  • Can you check my url again? – Annabelle Sykes Feb 08 '16 at 13:31
  • same error, your file still has formatting issues and whitespace – Scriptable Feb 08 '16 at 13:34
  • checkout this other answer regarding that particular error: http://stackoverflow.com/questions/21452385/json-text-did-not-start-with-array-or-object-and-option-to-allow-fragments-not-s?lq=1 – Scriptable Feb 08 '16 at 13:40
  • I saw this before and it didn't help. How do I get rid of whitespace? – Annabelle Sykes Feb 08 '16 at 13:42
  • When i created that file (example.json) i copied the JSON directly, without any whitespace and created the file in the command line and pasted it in and saved. If you want to remove the whitespace, just deleted the spaces before the start of the first {. – Scriptable Feb 08 '16 at 13:46
  • I removed the whitespace before the first {, but it is still showing the same error message. – Annabelle Sykes Feb 08 '16 at 13:49
  • The response from your server when I make my request can be seen here... http://pastebin.com/AjkgdmKN . It is not returning the JSON, you need to check your hosting solution to see if anything is being injected into the page. Or check your webserver settings – Scriptable Feb 08 '16 at 14:10
  • How do I check these? – Annabelle Sykes Feb 08 '16 at 14:11
  • That's too broad for me to answer here. It could be any number of things. Your server could of been compromised or there could be some scripts being injected by a CDN such as cloudfront. The only quick fix would be to host your .json file elsewhere for now. check http://stackoverflow.com/questions/32345649/php-api-file-returning-junk-html-instead-of-json-response-when-hosted-online – Scriptable Feb 08 '16 at 14:13
  • Currently I use byet.host – Annabelle Sykes Feb 08 '16 at 14:22
  • that is likely the cause of your issue, it injects code into your page – Scriptable Feb 08 '16 at 14:22
  • If you go to my link and yours, the inspect element is different – Annabelle Sykes Feb 08 '16 at 14:26
  • yes, becuase my host doesnt inject anything to the response of my pages, It seems yours does. try a free AWS account or something – Scriptable Feb 08 '16 at 14:27
  • What hosts do you suggest, other than AWS? – Annabelle Sykes Feb 08 '16 at 14:30
  • try Digital Ocean, very good and cheap. Here is my referral link which might get you some free credit/free trial https://m.do.co/c/837c2bbfc109 - Edit, yes you get $10 free credit to try – Scriptable Feb 08 '16 at 14:38
  • Aren't there any ones where I don't have to put in credit card details. I don't have a credit card. – Annabelle Sykes Feb 08 '16 at 14:47
  • you probably do have to yeah... I'm not sure which hosting solution is best for you... But we know the cause of your issue now – Scriptable Feb 08 '16 at 14:54
  • That's great. Could you help by keep looking for free ftp hosts? Why can't ByetHost do it? – Annabelle Sykes Feb 08 '16 at 14:56
  • Sorry I've done my searching for free hosts years ago, I soon realised they are free for a reason... they are not very good and usualy the websites and hosting come with data breaches, downtime, forced/injected advertising etc and I'd prefer to help people with coding problems. Good luck with the project – Scriptable Feb 08 '16 at 14:59
  • Thank you so much for your help! I really appreciate the hours you spent with it! – Annabelle Sykes Feb 08 '16 at 15:06
  • your welcome, if your happy that the issue is now closed please choose and accept one of the answers so that others can see its done. – Scriptable Feb 08 '16 at 15:33