How get Single Url From an Array of urls? - arrays

This is My Code:
urll = NSURL(string: "http://xxxxxxxxxxx.com/api/?slider=uij6sdnb")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(urll) {(NSData, response, error) -> Void in
do {
let records = try NSJSONSerialization.JSONObjectWithData(NSData!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for record in records {
// let urlid = Int(record["slide_id"] as! String)
let urimage = record["slide_url"] as! String
self.urls = [urimage]
print(self.urls.count)
}
}
catch {
print("Json Error")
}
}
task.resume()
When I Print :
print(urimage)
it gaves me 4 url like this:
http://sdkladlkasjd1.jpg
http://sdkladlkasjd2.jpg
http://sdkladlkasjd3.jpg
http://sdkladlkasjd4.jpg
When I print:
print(urimage[1])
It gaves me :
'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion
When i put it in another value :
var urls = [String]()
self.urls = [urimage]
and I print:
print(self.urls.count)
it gaves me
1
1
1
1
How on earch I can access one of this urls !?
I want to Show them on imageview but I can !

As Julian Kniephoff rightly mentioned, you are printing each URL in the for loop, thus you cannot access one particular one. However, there is also another issue, in that you are replacing the urls array with the latest url each time.
To solve this, simply replace the line self.urls = [urimage] with self.urls.append(urimage).
You can then access a particular image outside the for loop by doing something like self.urls[1].
This is also why printing the count of the array returns 1, since each time around you are setting the array to just the one latest element in the loop.
In the end, your code may look something like this
url = NSURL(string: "http://xxxxxxxxxxx.com/api/?slider=uij6sdnb")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) {(data, response, error) -> Void in
do {
let records = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for record in records {
//let urlid = Int(record["slide_id"] as! String)
let urimage = record["slide_url"] as! String
self.urls.append(urimage)
}
print(self.urls[1]) //Prints http://sdkladlkasjd2.jpg
}
catch {
print("Json Error")
}
//print(self.urls[1])
}
task.resume()

Related

How to take a function result and turn it into a key value pair array

I am fairly new to Swift but I have a function that returns a key value pair result of numbers
func dataPostRequest(_ url:String,_ paramString:String)
{
let url:NSURL = NSURL(string: url)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
guard let _:NSData = data as NSData?, let _:URLResponse = response, error == nil else {
print("error")
return
}
if let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
{
print(dataString)
}
}
task.resume()
}
I am able to call the function like this:
dataPostRequest("https://myserver.com/","user_email=emailtest.com")
This works correctly but I want to now use the data that I've pulled and display it in a Table View. I have my tableView set up correctly but I am wondering how I can take my function and turn it into a key value pair array or a dictionary that I can use. I have tried creating an empty dictionary and set my function call to it but I get an error:
var emptyDictionary = [Int: Int]()
emptyDictionary = dataPostRequest("https://myserver.com/","user_email=emailtest.com")
And no matter what variation I try I keep getting:
Cannot assign value of type '()' to type '[Int : Int]'
Any guidance would be greatly appreciated.
dataPostRequest has no return value (aka ()). You can decode the received data in the completion handler and assign it to the dictionary. See the comment line below.
If you need to proceed in another function you have to add a completion handler described here.
Basically don't use NS... classes in Swift at all if there are native counterparts. And don't annotate types the compiler can infer.
The native Swift version is
func dataPostRequest(with url:String, paramString : String)
{
let url = URL(string: url)!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = paramString.data(using: .utf8)
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
print(error)
return
}
let dataString = String(data: data!, encoding: .utf8)!
print(dataString)
// here decode the data to the desired type and assign it to emptyDictionary
}
task.resume()
}

How to grab a specific value from a core data saved array swift

Basically, instead of pulling the most recent saved object, I'd like to pull out previously saved objects. How would I go about doing this? What the code is doing is setting the text of a label depending on the object's text pulled from the array, but I want to pull older saves.
// deleteAllRecords() // ---- uncomment deleteAllRecords() here to delete all records saved.
// FETCH BLOCK
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Tasks")
//request.predicate = NSPredicate(format: "age = %#", "12")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [Tasks] {
print(data.value(forKey: "taskName"))
if let reminders = data.value(forKey: "taskName") as? [Reminder] {
for reminder in reminders {
// Now you have your single object Reminder and you can print his variables
print("Your reminder description is \(reminder.reminderDescription), and his length is \(reminder.reminderLength)")
self.reminderDisplay.text = reminder.reminderDescription
if reminderDisplay.text == reminder.reminderDescription {
self.testLabel1.text = reminder.reminderDescription
reminderCount = 1
}
}
}
}
How would I go about doing this?
Thanks in advance. - Sav.
EDIT:
// SAVE BLOCK
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Tasks", in: context)
let newTask = Tasks(entity: entity!, insertInto: context)
newTask.setValue(reminderList, forKey: "taskName")
do {
try context.save()
} catch {
print("Failed saving")
}
}
EDIT2:
request.predicate = NSPredicate(format: "taskName = %#", "Lock the door.")
EDIT3:
Here's the object code;
public class Reminder: NSObject, NSCoding {
var reminderDescription : String? = nil
var reminderLength : Int? = nil// in days
public required init?(coder aDecoder: NSCoder) {
self.reminderDescription = aDecoder.decodeObject(forKey: "reminderDescription") as? String
self.reminderLength = aDecoder.decodeObject(forKey: "reminderLength") as? Int
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(reminderDescription, forKey: "reminderDescription")
aCoder.encode(reminderLength, forKey: "reminderLength")
}
init (chosenReminderDescription: String, chosenReminderLength: Int) {
reminderDescription = chosenReminderDescription
reminderLength = chosenReminderLength
}
}
Data Model
If possible I'd like to query in relation to when they were made, like the first one, then the 2nd one. Would I have to give the object a date property and query through that?
EDIT4:
request.predicate = NSPredicate(format: "orderNo = %#", "2")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [Tasks] {
print(data.value(forKey: "taskName"))
if let reminders = data.value(forKey: "taskName") as? [Reminder] {
for reminder in reminders {
// Now you have your single object Reminder and you can print his variables
print("Your reminder description is \(reminder.reminderDescription), and his length is \(reminder.reminderLength)")
self.reminderDisplay.text = reminder.reminderDescription
if reminderDisplay.text == reminder.reminderDescription {
self.testLabel1.text = reminder.reminderDescription
reminderCount = 1
}
}
}
}
Your code seems to call a request at entity Task and get the results in an Array correctly.
I would suggest you to look if you are actually saving the previous attempts to store value at your Core Data entity Task before asking for queries like this.
Don't forget that sometimes Core Data decides to postpone actual storing of information on its DB.
So try forcing savings into CoreDB before querying. For this to happen, make sure you are calling ".save()" to guarantee that Core Data sends (and executes) a saving request right away.
A sample code to force saving right away is down below:
do {
try context.save()
} catch {
print("Failure to save context: \(error)")
}
}
–
Edit (24/11/2018 03:07AM GMT+01:00):
By reading your comment, it looks like you just want to filter the queries for a specific value, instead of querying the most recent ones.
To do so, just simply uncomment the code:
//request.predicate = NSPredicate(format: "age = %#", "12")
To:
request.predicate = NSPredicate(format: "age = %#", "12")
Inside the NSPredicate's format method calling is supposed to be what you want as the statement of your filtering. If you want to filter it by age, your example is already done for you.
I'll also attach an example of other codes of mine.
request.predicate = NSPredicate(format: "(time >= %#) AND (time <= %#)", fromDateUnformatted as NSDate, toDateUnformatted as NSDate)
Now if you want to do relationship-related queries (double or more queries at once to dig information further inside Entities' relationships), then there are other methods of doing so.
Let me know if I'm going in the right direction to find an answer.

Load Firestore data to Table view Swift 4

I have a question related to load data from Firestore to table view. Basically, i understand how to do it, but in this case, i kind of confuse if the structure of Firestore as below:
"fund" -> "randomId" -> "agensi: id"
i was able to load the agensi from collection which is "WJ18kBvDLhVrvml2slXB". To get the real agensi name i have to get data from collection "Agensi" as image below:
below is the code that what i have already did:
var agencyname: [String] = []
func getData() {
db.collection("fund").getDocuments()
{
(querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
// var agencyNumber = 0
for document in querySnapshot!.documents {
let data = document.data()
let agency = data["agensi"] as? String ?? ""
let agencyId = document.documentID
print(agency)
print(agencyId)
//MARK get name
let newdocRef = Firestore.firestore().document("Agensi/\(agency)")
newdocRef.getDocument { (docSnapshot, error) in
guard let docSnapshot = docSnapshot, docSnapshot.exists else { return }
let dataDetails = docSnapshot.data()
let agencyNew = dataDetails!["name"] as? String ?? ""
self.agencyname.append(agencyNew)
print("List of the agency: \(self.agencyname.append(agencyNew))")
}
}
self.tableView.reloadData()
}
}
}
i try to print:
self.agencyname.append(agencyNew)
but its display nothing. so, i cannot load the name of the agency into my table view cell. By the way sorry for my bad english. Thanks in advance
There are few things I would like to tell:
1. FireStore queries are asynchronous so there is a callback function when it finishes. Reload your tableView inside the callback instead of end of the loop only then it will load the data properly.
DispatchQueue.main.async {
self.tableView.reloadData()
}
Write above code just below print("List of the agency: \(self.agencyname.append(agencyNew))") line.
2. You're printing "self.agencyname.append(agencyNew)" and it is void by the way so will not print anything so print(\(self.agencyname)) instead.
3. When using a guard in a loop then don't use return because it will break the loop for next iteration if any error occurs. We should use continue here to let the loop execute completely.

Array only contains last value added but count is still the same

I am parsing JSON and appending the data to an array, and while the array contains the correct number of elements, it is just the same element over and over, whatever the last one added was. Here is the code I am using:
if (statusCode == 200) {
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let ns = json as? NSArray{
for ns in ns{
if let name = ns["name"] as? String{
if let number = ns["number"] as? Int{
if let cn = ns["cyclenumber"] as? Int{
if let url = ns["url"] as? String{
self.c.name = name
self.c.number = number
self.c.cycleNumber = cn
self.c.url = url
self.n.array.append(self.c)
}
}
}
}
}
}
}catch {
print("Error with Json: \(error)")
}
}
When I print the array, it just prints however many elements were added, but they are all duplicates of the last element added.
The problem is that you keep appending the sane instance - namely, self.c. Since the type of c is a class, not struct, no copying is going on; the same reference is added to the array over and over again.
You can fix this problem by making c's type a struct, or by assigning a new c on each iteration of the loop:
if let url = ns["url"] as? String {
var c = TypeOfC() // Make a new instance
c.name = name
c.number = number
c.cycleNumber = cn
c.url = url
self.n.array.append(c)
}
Note that c is no longer a member of self. Since you are changing c inside a loop, making it a member was very likely a mistake in the first place.
Answer's already been given, but I thought I should clean up your code a bit :)
guard let data = data where statusCode == 200 else {
return
}
do{
let json = try NSJSONSerialization.JSONObjectWithData(data, options:.AllowFragments)
if let ns = json as? NSArray{
for ns in ns{
if let name = ns["name"] as? String, number = ns["number"] as? Int,
cn = ns["cyclenumber"] as? Int, url = ns["url"] as? String{
self.c.name = name
self.c.number = number
self.c.cycleNumber = cn
self.c.url = url
self.n.array.append(self.c)
}
}
}
}catch {
print("Error with Json: \(error)")
}

Swift - Populating an array with NSDictionary String data

I have successfully set up a session to pull json data from a site - it works. However, when I start to populate my array with the data the array is not populating the information. Please help.
Here is my Person class:
class Person {
var name1 = "name"
var info1 = "info"
init(name1: String, info1: String) {
self.name1 = name1
self.info1 = info1
}
}
Here is my setUpPerson function:
func setUpPerson() {
let url = NSURL(string: "http://www.my-sites-jsondata")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
let urlError = false
if error == nil {
var urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding) as NSString!
var data: NSData = urlContent.dataUsingEncoding(NSUTF8StringEncoding)!
do {
let jsonObject = try (NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSArray)!
var index1 = 0
while index1 < jsonObject.count {
var maindata = (jsonObject[index1] as! NSDictionary)
var nameA = maindata["Name"] as! String
var infoA = maindata["Info"] as! String
var data1 = Person(name1: nameA, info1: infoA)
self.arrayOfPersons.append(data1)
index1++
}
} catch {
print(urlError)
}
}
})
task.resume()
}
}
Your code looks all good to me.
To me your self.arrayOfPersons is also being set (I just tested it with my test app).
You're probably attempting to print it before it's been set in the async dataTaskWithURL block.
An async block performs in the background, so as the code written immediately after your block executes on the main thread, the code within the async block will not yet be complete.
To me, the code has definitely executed. But because the async code hasn't finished executing yet, you are not seeing it set.
You will have to wait until after the async code executes before checking for the new value.
You can try like this:
dispatch_async(dispatch_get_main_queue(), ^{
// Set your data on property here
});
I was able to successfully complete this project. The answer came in two fold...
I needed dispatch_async(dispatch_get_main_queue()
reloadData()

Resources