I have a class in which I need to check a URL for json data compile that in an array and see if the latest content is an article/project/survey. My code compiles but it compare the strings to see if its an article/project/survey. Not sure what im doing wrong?
my code is
class LocalNotificationsManager {
var articleSurveyOrProject = String()
func checkForNewContent() {
let url = "https://cdn.contentful.com/spaces/maz0qqmvcx21/entries?access_token=ae8163cb8390af28cd3d7e28aba405bac8284f9fe4375a605782170aef2b0b48";
var jsonData:NSData?
let url = "https://cdn.contentful.com/spaces/maz0qqmvcx21/entries?access_token=ae8163cb8390af28cd3d7e28aba405bac8284f9fe4375a605782170aef2b0b48";
var jsonData:NSData?
var latestContentDates = [String]()
do{
jsonData = try NSData(contentsOfURL: NSURL(string: url)!, options: NSDataReadingOptions.DataReadingUncached)
let jsonObject:AnyObject? = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.AllowFragments)
if let itemArray = jsonObject?.objectForKey("items") as? NSArray{
for item in itemArray{
if let sysItem = item.objectForKey("sys"){
//this is createdAt
if let createdAt = sysItem.objectForKey("createdAt") as? String{
print("createdAt:\(createdAt)")
latestContentDates.append(createdAt)
}
if let contentTypeItem = sysItem.objectForKey("contentType")!.objectForKey("sys"){
//this is id
if let id = contentTypeItem.objectForKey("id") as? String{
content.append(id)
}
}
}
}
}
}catch let err as NSError{
print("err:\(err)")
}
let articleSurveyOrProject = content[0]
print("articleSurveyOrProject:\(articleSurveyOrProject)")
sendLocalNotification()
}
func sendLocalNotification() {
if (articleSurveyOrProject == "article") {
print(Article)
} else if (articleSurveyOrProject == "survey") {
print("Survey")
} else if (articleSurveyOrProject == "project")
{
print("Project")
} else {
print("Oops! something went wrong it didnt get any values")
}
}
}
Note: Im working in swift2
The problem is this line:
let articleSurveyOrProject = content[0]
Delete let.
Related
I need to sync two json files to add new content from File A (located in the app bundle) to File B after an app update.
Both json files are arrays of dictionaries. I need to iterate the dictionaries form File A, and based on the "id" value, if a dictionary is not present in File B I need to append those missing dictionaries and save File B back to the file system.
I have a solution below that does this, and seems to work. But it's SO ugly! Granted I put this together in about 15 minutes cringing the whole way but I'm sure there has to be a better way of handling this. Also, I don't want to further muddy the waters by converting these dictionaries to structs or models for the comparison only to convert them back to dictionaries -> json.
Any advise here would be great! I prefer clean code and this is a mess.
typealias JSON = [[String: Any]]
static private func uglySync() {
let fileName: String = "someFileName"
guard let sourceUrl = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
guard let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let destinationUrl = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json")
do {
let sourceData = try Data(contentsOf: sourceUrl)
do {
if let sourceArray = try JSONSerialization.jsonObject(with: sourceData, options: .mutableContainers) as? JSON {
do {
let destinationData = try Data(contentsOf: destinationUrl)
do {
if let destinationArray = try JSONSerialization.jsonObject(with: destinationData, options: .mutableContainers) as? JSON {
var mutableArray = destinationArray
sourceArray.forEach({ (item) in
if let itemId = item["id"] as? String {
let foundItem = destinationArray.filter { $0["id"] as! String == itemId }.first
if foundItem == nil {
mutableArray.append(item)
}
}
})
do {
let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
try jsonData.write(to: destinationUrl)
} catch let error as NSError {
print("Couldn't write to file: \(error.localizedDescription)")
}
} else {
print("Cound not process json")
}
} catch {
print(error.localizedDescription)
}
} catch {
print(error.localizedDescription)
}
} else {
print("Cound not process json")
}
} catch {
print(error.localizedDescription)
}
} catch {
print(error.localizedDescription)
}
// oh wow the try catches :/
}
I've grouped converting the files to jsonArray to simplify the do...catch. Alternatively, if you don't need to print the error message, you could opt to have Optional try? as well to remove the do...catch block.
typealias JSONArray = [[String: Any]]
private func jsonArray(from fileURL: URL) -> JSONArray? {
do {
let fileData: Data = try Data(contentsOf: fileURL)
guard let jsonArray = (try JSONSerialization.jsonObject(with: fileData, options: .mutableContainers)) as? JSONArray else {
debugPrint("Failed to find JSON Array table")
return nil
}
return jsonArray
} catch {
print(error.localizedDescription)
return nil
}
}
func sync() {
let fileName: String = "someFileName"
guard
let fileURL: URL = Bundle.main.url(forResource: fileName, withExtension: "json"),
let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first,
let destinationURL: URL = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json"),
let sourceArray = jsonArray(from: fileURL),
let destinationArray = jsonArray(from: destinationURL)
else {
return
}
var mutableArray = destinationArray
let destinationIDArray = destinationArray.compactMap { $0["id"] as? String }
mutableArray.forEach { (item) in
if let itemId = item["id"] as? String, !(destinationIDArray.contains { $0 == itemId }) {
mutableArray.append(item)
}
}
// Update File
do {
let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
try jsonData.write(to: destinationURL)
} catch {
print("Couldn't write to file: \(error.localizedDescription)")
}
}
I think you can put the different trys in the same do block.
do {
try function1()
try function2()
} catch {
print(error.localizedDescription)
}
So afterwards your function may look like
typealias JSON = [[String: Any]]
static private func moderatelyOkSync() {
let fileName: String = "someFileName"
guard let sourceUrl = Bundle.main.url(forResource: fileName, withExtension: "json") else { return }
guard let destinationDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let destinationUrl = destinationDirectory.appendingPathComponent("Data/" + fileName + ".json")
do {
let sourceData = try Data(contentsOf: sourceUrl)
if let sourceArray = try JSONSerialization.jsonObject(with: sourceData, options: .mutableContainers) as? JSON {
let destinationData = try Data(contentsOf: destinationUrl)
}
var mutableArray = destinationArray
sourceArray.forEach({ (item) in
if let itemId = item["id"] as? String {
let foundItem = destinationArray.filter { $0["id"] as! String == itemId }.first
if foundItem == nil {
mutableArray.append(item)
}
}
})
let jsonData = try JSONSerialization.data(withJSONObject: mutableArray, options: .prettyPrinted)
try jsonData.write(to: destinationUrl)
} catch {
print(error.localizedDescription)
}
}
The way I would do it is to Decode the json files with struct and then encode(serialization) it to the other files. Because the code to do that would be a 2 liner, but you would first have to layout all the variables in the struct. Probably still not optimal
My code below is trying to take core data from a NSManagedObject append it to an array. The core data element is saved as a string. My code is not compelling. Ideally the code should be able to append code into the array then the array is filled, find the sum of the numbers added together and print them into the viewDidLoad() func.
var itemName : [NSManagedObject] = []
func performAction() {
let appD = UIApplication.shared.delegate as! AppDelegate
let context = appD.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Data")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
var retrievedData = [Double]()
for data in result as! [NSManagedObject] {
if let value = data.value(forKey: "ee") as? Double {
retrievedData.append(value)
}
}
let arraySum = retrievedData.reduce(0, +)
print(arraySum)
} catch {
print("Failed")
}
}
I reviewed your code when you will need to change small thing over there. Replace performAction function as per my updated answer.
func performAction() {
let appD = UIApplication.shared.delegate as! AppDelegate
let context = appD.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Data")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
var retrievedData = [Double]()
for data in result as! [NSManagedObject] {
if let value = data.value(forKey: "ee") as? String {
retrievedData.append(Double(value) ?? 0)
}
}
let arraySum = retrievedData.reduce(0, +)
print(arraySum)
} catch {
print("Failed")
}
}
I currently have my set-up as followed:
I am running a query in Firebase to extract all of the genres within an array of genres, like so:
var genresLabelIndex : [String] = ["Horror", "Fiction", "Romance"]
Then I am creating a blank arrays for each of the genres to be able to store the information of the genres within each of the areas like so:
var horrorData = [InformationForFeed]()
var fictionData = [InformationForFeed]()
var romanceData = [InformationForFeed]()
InformationForFeed looks like so:
class InformationForFeed {
fileprivate var _uploadKey:String!
fileprivate var _userKey:String!
fileprivate var _imageURL:String!
fileprivate var _socialMedia:[String]
var uploadKey:String!{
return _uploadKey
}
var userKey:String!{
return _userKey
}
var imageURL:String!{
return _imageURL
}
init(dictionary:Dictionary<String,AnyObject>, socials: [String]) {
_socialMedia = socials
if let uploadKey = dictionary["upload_key"] as? String {
self._uploadKey = uploadKey
}
if let userKey = dictionary["user_key"] as? String {
self._userKey = userKey
}
if let imageURL = dictionary["imageUrl"] as? String {
self._imageURL = imageURL
}
}
}
I am then creating an Array of the list of genres arrays like so:
1) First I am creating an empty array of arrays like this:
var genreArrayIndex : [[InformationForFeed]] = []
2) Then within my init() of the UIView I am setting what will be in the array like this:
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
I then will run a function called getData() that will run my query and start storing the information.
I store my information of each genre in a tempArray, and then I set the genreArrayIndex[index] to equal the tempArray and then clear the tempArray as seen in getData below.
func getData() {
for genre in genresLabelIndex {
let dbReference = Database.database().reference().child("genres").child(genre)
let query = dbReference.queryLimited(toLast: 6)
query.observeSingleEvent(of: .value, with: { (snapshot : DataSnapshot) in
if snapshot.childrenCount > 0 {
for s in snapshot.children.allObjects as! [DataSnapshot] {
let item = s.value as! Dictionary<String,AnyObject?>
let facebook = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["facebook_link"]
let audible = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["audible_link"]
let amazon = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["amazon_link"]
var socialsArray = [String]()
if facebook != nil {
socialsArray.append(facebook! as! String)
} else {
socialsArray.append("nil")
}
if audible != nil {
socialsArray.append(audible! as! String)
} else {
socialsArray.append("nil")
}
if amazon != nil {
socialsArray.append(amazon! as! String)
} else {
socialsArray.append("nil")
}
let data = InformationForFeed(dictionary: item as Dictionary<String,AnyObject>, socials: socialsArray)
self.newArray.append(data)
}
}
self.genreArrayIndex[self.genreArrayIndexCount] = self.newArray
self.genreArrayIndexCount = self.genreArrayIndexCount + 1
self.newArray.removeAll()
self.internalIndex = self.internalIndex + 1
if self.internalIndex == self.genresLabelIndex.count {
self.tableView.reloadData()
}
})
}
}
My tempArray looks like this:
var newArray = [InformationForFeed]()
The index looks like this:
var genreArrayIndexCount : Int = 0
Now comes the issue....
All of the information is properly being stored in the genreArrayIndex .....but... it is not actually storing the information in the arrays that being stored in genreArrayIndex.
So in other words if you were to print(self.genreArrayIndex) it would be fully populated. But if you were to print(self.fictionData) it would be blank.
How can I resolve this?
Array is a value type. That means its contents are copies. Initializing genreArrayIndex with empty horrorData, (and others) and then filling it with getData() does not also copy the data back into horrorData. I would recommend eliminating
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
and replacing horrorData, fictionData, ... with computed properties. Perhaps like this.
var horrorData: [InformationFeed] {
return genreArrayIndex[0]
}
I unable to get the driverId from this JSON
[data: [{"id":"619","driverId":"6789","starting_time":"2016-12-12 23:24:50","end_time":null}]]
Here is my full code
//selector Method SESSION_STATUS_REQUEST_COMPLETE
func afterServiceStatus(notification : NSNotification) {
print(notification.userInfo!)
guard let data = notification.userInfo!["data"] else{
print("data have no idea ")
return
}
if let driverId = notification.userInfo![0]!["driverId"] {
print(driverId)
}
// if let driverId = data["driverId"] as? String{
//
// print(driverId)
// }
}
You can try this...
func afterServiceStatus(notification : NSNotification) {
print(notification.userInfo!)
guard let data = notification.userInfo!["data"] else{
print("data have no idea ")
return
}
let driverId = notification.userInfo![0]?.objectForKey("data")?.valueForKey("driverId")
print(driverId)
}
You should try to avoid all the force unwraps, because they make your code vulnerable to crashing if you get back JSON in an unexpected format.
This should retrieve the driverId from your dictionary:
func afterServiceStatus(notification: NSNotification) {
guard
let userInfo = notification.userInfo as? [String: Any],
let data = userInfo["data"] as? [[String: Any]],
let driverId = data[0]["driverId"] as? String
else {
return
}
print(driverId)
}
func afterServiceStatus(notification : NSNotification) {
print(notification.userInfo!)
guard let data = notification.userInfo!["data"] else{
print("data have no idea ")
return
}
if let driverId = notification.userInfo[0]["data"]["driverId"].string
{
print(driverId)
}
}
If it doesn't work then forward me link, I'll give you proper solution.
I am trying to create a file name from the URL. I have to forcefully remove the first item in the array every time. Like the C# implementation where they check for empty string.
Is it possible to remove the "/" in the array? Is there a better way to implement this?
let url = "https://stackoverflow.com/questions/ask"
var filePathComponents:[String] = []
filePathComponents = assetURL.pathComponents as! [String]
filePathComponents.removeAtIndex(0)
let fileName = "-".join(filePathComponents)
I would recommend
filePathComponents.filter { return $0 != "/" }
You don't have to use mutability if you use range indexing (with ..<).
And to make it convenient to use, let's put it in an extension as a computed property.
Example for String:
extension String {
var pathNameWithoutPrefix: String {
get {
return "-".join(self.pathComponents[2 ..< self.pathComponents.count])
}
}
}
let filePath = "http://stackoverflow.com/questions/ask".pathNameWithoutPrefix
println(filePath) // "questions-ask"
Example for NSURL:
extension NSURL {
var pathURLWithoutPrefix: NSURL? {
get {
if let filePathComponents = self.pathComponents as? [String] {
return NSURL(string: "-".join(filePathComponents[1 ..< filePathComponents.count]))
}
return nil
}
}
}
if let url = NSURL(string: "http://stackoverflow.com/questions/ask"),
let fileURL = url.pathURLWithoutPrefix {
println(fileURL) // "questions-ask"
}
Here's the same extensions for Swift 2:
extension String {
var pathNameWithoutPrefix: String {
get {
let str = self as NSString
return "-".join(str.pathComponents[2 ..< str.pathComponents.count])
}
}
}
extension NSURL {
var pathURLWithoutPrefix: NSURL? {
get {
if let filePathComponents = self.pathComponents {
return NSURL(string: "-".join(filePathComponents[1 ..< filePathComponents.count]))
}
return nil
}
}
}
let linkURL = NSURL(string: "http://stackoverflow.com/questions/ask")!
if let comps = linkURL.pathComponents as? [String] {
let fileName = "-".join(dropFirst(comps)) // "questions-ask"
}
Swift 2.0
let linkURL = NSURL(string: "http://stackoverflow.com/questions/ask")!
if let comps = linkURL.pathComponents?.dropFirst() {
let fileName = "-".join(comps) // "questions-ask"
}
Different approach using the host and path properties of NSURL
if let assetURL = NSURL(string: "http://stackoverflow.com/questions/ask") {
let fileNameWithHost = assetURL.host!.stringByAppendingPathComponent(assetURL.path!) // "stackoverflow.com/questions/ask"
let fileNameWithoutHost = assetURL.path!.substringFromIndex(assetURL.path!.startIndex.successor()) // "questions/ask"
}