Append to array in swift - has no member append? - swift

What am I doing wrong in this code?
and why do I get the error ?
"Value of type 'NSMutableArray' has no member 'append'"
static func saveUserData()
{
let item:NSDictionary = ["TIME":"12:00","LOCATION":"here"]
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
let filePath = documentsDirectory + "/datafile.dat"
var readArray:NSMutableArray? = NSMutableArray(contentsOfFile: filePath)
if var array = readArray {
print("loaded array - appending..." )
// PROBLEM IS HERE
var damnArray:NSMutableArray = array
damnArray.append(item)
} else {
//
}
}

Because you are using NSMutableArray, you need to use addObject
damnArray.addObject(item)
append is used with swift array like this way
var arr = [Int]()
arr.append(5)
For more detail about swift array check this apple documentation or this tutorial.

Your had declared dammArray as NSMutableArray. So there is no method append is available. Append is available in swift array object.
var damnArray:NSMutableArray
damnArray.addObject(item)
or
var damnArray = [NSDictionary]()
damnArray.append(item)

As per your answer and syntax this worked for me thanks, in my code which is:
#IBAction func btnSend(_ sender: UIButton)
{
//data.append(tfData.text!)
data.add(tfData.text!)
tblViewList.reloadData()
tfData.resignFirstResponder()
}

Related

Swift macOS - find all files of a specific extension

I need to find the names of all files that have the extension .pub in the path ~/.ssh.
So in the end I need to have an array of names.
I solved it like this, I wonder if there is a possibility to write it in a better and more compact way as code.
func arrayFile(path: String, ext: String) -> [String] {
guard let desktopPath = NSSearchPathForDirectoriesInDomains(.desktopDirectory,.userDomainMask,true).first else { return [] }
let pathConfig = desktopPath.replacingOccurrences(of: "Desktop", with: path)
let filemanager: FileManager = FileManager()
let files = filemanager.enumerator(atPath: pathConfig)
var array = [String]()
while let file = files?.nextObject() as? String {
if file.hasSuffix(ext) {
let name = file.replacingOccurrences(of: ext, with: "")
array.append(name)
}
}
return array
}
let array = arrayFile(path: ".ssh/", ext: ".pub")
print(array)
Can you give me some suggestions?

Ambiguous use of 'init(contentsOfURL:)' in swift 4.1

I use Swift 4.1 and XCode 9.3
var upsList = [Any]()
func loadUpsValues () {
print("loadUpsValues")
let upsFileAsURL = URL(string: "Upslist.txt")
// Original Objective C Call was: NSMutableArray *ListUpsArray = [NSMutableArray arrayWithContentsOfURL:upsFile];
//
let upsList = NSArray(contentsOfURL:upsFileAsURL! )
}
I get an error: Ambiguous use of 'init(contentsOfURL:)'
and it seems that the source for NSArray comes from the same foundation definition:
I have twice:
1 Found this candidate (Foundation.NSArray)
2 Found this candidate (Foundation.NSArray)
Thanks for your help
This error is because [NS(Mutable)Array arrayWithContentsOfURL:]; does not exists in Swift.
For swift the NSArray initialiser has been changed to be more 'swifty' so it became:
NSArray(contentsOf:)
As seen here.
So changing your last line, the code should run as expected, i.e:
let upsList = NSArray(contentsOf: upsFileAsURL!)
Edit:
Going with the comment from #nayem. Assuming your text file is a collection of lines, you could change your code to work without relying on NS based objects like so:
func loadUpsValues () {
do {
guard let url = Bundle.main.url(forResource: "Upslist", withExtension: "txt") else { return }
let data = try String(contentsOf: url)
let upsList = data.components(separatedBy: NSCharacterSet.newlines)
...
} catch {
/* handle error */
}
}
Look at this solution:
You have declared once the upsList, why do you declare it again as a let
This solution works.
var upsList = NSArray()
func loadUpsValues () {
print("loadUpsValues")
let upsFileAsURL = URL(string: "Upslist.txt")
// Original Objective C Call was: NSMutableArray *ListUpsArray = [NSMutableArray arrayWithContentsOfURL:upsFile];
//
upsList = NSArray(contentsOf: upsFileAsURL! ) ?? NSArray()
}

How to get some data out of an array in swift?

Here is my problem: I have an plist file, which have a simple strut:
root object is an array, and there are 2 sections in the array, each of them are dictionary including 2 pair key-value data:
and I'm going to create a tableView to show the datas, but I can't get the content out of the array :
here is how i declared my dataArray:
var plistArray = [AnyObject]()
can some one help me?
You need to properly cast at each level:
if let innerArray = plistArray[0] as? [AnyObject] {
if let dataDic = innerArray[indexPath.row] as? [String:String] {
if let imageName = dataDic["Pic"] {
cell?.imageView?.image = UIImage(named: imageName)
}
}
}
But why are you using AnyObject when you know what the plist contains? Use proper types. You know it's an array of arrays of dictionaries with String keys and String values.
var plistArray = [[[String:String]]]()
Then all you need is:
if let imageName = plistArray[0][indexPath.row]["Pic"] {
cell?.imageView?.image = UIImage(named: imageName)
}

Swift: Unable to get array values from singleton class

Hi I retrived value from JSON and stored in NSMutableArray. I have tried this like Singleton. I have used empty swift file for this. Datas successfully retrieved and stored in NSMutableArray which is already declared in mainViewController. Then, if I use that NSMutableArray value in mainViewController, it shows empty array.
My coding is below. Kindly guide me.
Empty Swift File
public class json_file{
var prod_Obj = product_mainVC()
class var shared: json_file
{
struct Static
{
static let instance: json_file = json_file()
}
return Static.instance
}
func dataFromJSON()
{
let url = NSURL(string: "http://........--...4900a20659")!
var data : NSData = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingMapped, error: nil)!
var dict: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
let dataArray = dict["data"] as [[String:AnyObject]] // The array of dictionaries
for object in dataArray {
let category_name = object["category_name"] as String
prod_Obj.ct_name_arr.addObject(category_name)
let category_child = object["category_child"] as [[String:AnyObject]]
for child in category_child {
let sub_category_name = child["sub_category_name"] as String
prod_Obj.sub_ct_name_arr.addObject(sub_category_name)
}
}
println(prod_Obj.ct_name_arr) //Here value is Getting
println(prod_Obj.sub_ct_name_arr) //Here value is Getting
}
}
viewDidLoad
{
json_file.shared.dataFromJSON()
println(ct_name_arr) //Prints Empty Array [Intially Declared as NSMutableArray]
println(sub_ct_name_arr) //Prints Empty Array [Intially Declared as NSMutableArray]
}
I was trying understand the problem, but I can't see the product_mainVC. Because this I remake your class with little modifications.
class JsonFile
{
private(set) var categoryNames:[String];
private(set) var subCategoryNames:[String];
class let shared:JsonFile = JsonFile();
private init()
{
self.categoryNames = [];
self.subCategoryNames = [];
}
func dataFromJson()
{
let url = NSURL(string: "http://........--...4900a20659")!
if let data : NSData = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingMapped, error: nil)
{
if let dict: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary
{
if let dataArray = dict["data"] as? [[String:AnyObject]] // The array of dictionaries
{
for object in dataArray {
let category_id = object["category_id"] as Int
let category_name = object["category_name"] as String
categoryNames.append(category_name);
let category_child = object["category_child"] as [[String:AnyObject]]
for child in category_child {
let sub_category_id = child["sub_category_id"] as Int
let sub_category_name = child["sub_category_name"] as String
subCategoryNames.append(sub_category_name);
}
}
}
}
}
println(categoryNames);
println(subCategoryNames);
}
}
I did
Modify your way to do Singleton to a safe and more simple mode, create the arrays categoryNames and subCategoryNames internal in class because this is better to manipulate, and protect your fetch data to safe from possibles crash.
Implementation
JsonFile.shared.dataFromJson();
println("count categoryNames");
println(JsonFile.shared.categoryNames.count);
println("count subCategoryNames");
println(JsonFile.shared.subCategoryNames.count);
You need think about
This code is sync, and because this if you have a big data or request slow, the main thread from your application will freeze waiting return and it is bad for your user. Think if is necessary be sync.
let category_id = object["category_id"] as Int is never used. Why do you stay with this in code?

Saving an array of NSURL to NSUserDefaults

I have an array of NSURL items like this:
var array = [NSURL]()
I'm trying to save this to NSUserDefaults:
let defaults = NSUserDefaults(suiteName: "group.a.project")
defaults?.setObject(array, forKey: "NSURLarray")
Will result in it crashing as NSURL can't be stored in NSUserDefaults.
How can I save this array of NSURL's to NSUserDefaults, so that I can then access it and use the NSURL's in the array as required (saving an array of strings and then trying to use them as NSURL's will result in an error from xcode)?
You could archive your URL array to an instance of NSData and store that in user defaults. To save:
let urls = [ NSURL(string: "http://www.google.com")!, NSURL(string: "http://www.stackoverflow.com")! ]
let defaults = NSUserDefaults(suiteName: "group.a.project")
let data = NSKeyedArchiver.archivedDataWithRootObject(urls)
defaults?.setValue(data, forKey: "myUrls")
To load:
if let data = defaults?.valueForKey("myUrls") as? NSData {
if let urlsArray = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? [NSURL] {
println(urlsArray)
}
}
when saving, save the absolute strings of the urls. when loading use NSURL(URLString:) to make the strings into urls again
import UIKit
class ViewController: UIViewController {
var urlsArray : [NSURL]?
func load () {
var urls : [NSURL] = []
let stringsArray = NSUserDefaults.standardUserDefaults().objectForKey("stringsArray") as [String]?
if let array = stringsArray {
for string in array {
var url = NSURL(string: string)
urls.append(url!) //no null check
}
}
self.urlsArray = urls
}
func save () {
var strings : [String] = []
if let array = self.urlsArray {
for url in array {
var string = url.absoluteString
strings.append(string!) ////no null check
}
}
NSUserDefaults.standardUserDefaults().setObject(strings, forKey: "stringsArray")
}
}
saving can be reduced with KVC.
func save () {
var strings : [String] = []
if let array = self.urlsArray as NSArray? {
strings = array.valueForKeyPath("absoluteStrings")
}
NSUserDefaults.standardUserDefaults().setObject(strings, forKey: "stringsArray")
}
This could be a bit more swifty:
func load () {
if let stringsArray = NSUserDefaults.standardUserDefaults().objectForKey("stringsArray") as? [String] {
self.urlsArray = stringsArray.compactMap { URL(string: $0) }
}
}
func save () {
NSUserDefaults.standard.setObject(self.urlsArray.map { $0.absoluteString }, forKey: "stringsArray")
}