Why can't I add items to an array if it is inside a singleton class? - arrays

I have a singleton class which looks like this:
class DataAccess {
var teamUrl = NSArray()
}
let sharedData = DataAccess()
This is saved as a .swift file.
I am trying to add an item to that array from one of my view controllers. The code I am using to try and add the item to the array is this:
sharedData.teamUrl.append(teamUrl.text)
I am receiving an error message though. The error message is:
'NSArray' does not have member names 'append'
I know that it is something to do with my singleton because I created an array in the view controller and changed the code correspondingly and it worked.
I also tried to change the Singleton class to this:
class DataAccess {
var teamUrl = []
}
let sharedData = DataAccess()
I received the same error though.
I'm not sure why this isn't working. Please would somebody be able to explain where I have gone wrong?
Just to add, although I have referred to these as singletons, I'm not 100% sure that they are - its just the name they were referred to on a tutorial when I was learning about transferring data between different views.

Instead of var teamUrl = [], try var teamUrl: [String] = []. This will create a native Swift array, instead of an NSArray, and that has a .append method.

Related

Swift: Cannot add element in Array from another object

I am struggeling with swift syntax . I want to add objects to an array but I have syntax errors.
The array is located in class Document, and the class that should add objects is in class Viewcontroller.
The array is of type Content:
public class Content: NSObject {
#objc var bankAccSender: String?
#objc var bankAccReceiver: String?
Declaration snippest in Document:
class Document: NSDocument {
var content=[Content]()
override init() {
super.init()
self.content = [Content]()
// force one data record to insert into content
content += [Content (… )] // checked with debugger
The ViewController has assigned the represented Object
contentVC.representedObject = content
But adding data in ViewController gives a compiler error „Type of expression is ambiguous without more context“:
var posting = Content(…)
self.representedObject.append(posting)
Hope you can help..
You can't append an element to an object of type Any. What you need is to replace the existing value with a new collection:
representedObject = (representedObject as? [Content] ?? []) + CollectionOfOne(posting)
representedObject is of type Any?, which is a very difficult type to work with in Swift. Since you already have a content property, I would probably adjust that, and then re-assign it to representedObject.
You can also try this (untested), as long as you are certain that the type is always [Content]:
(self.representedObject as! [Content]).append(posting)
It's possible you'll need some more complex like this:
(self.representedObject as! [Content]?)!.append(posting)
As I said, Any? is an incredibly obnoxious type. You probably want to wrap this up into a function. Or I you can avoid using representedObject, then I would recommend that. In many cases you don't need it. It's often just a convenience (in ObjC; in Swift, it's very hard to use).

Is there a way to populate an object instance using AutoFixture?

Here is a sample of what I'm trying to do
var foo = CreateFoo(); // I don't have access to the internals of CreateFoo
fixture.Populate(foo); // foo should now have random property values
Obviously, there is no Fixture.Populate method. But how should I solve this problem?
Thanks!
AutoFixture indeed doesn't provide API to fill writable properties of an existing object. However, you can use the following snippet to achieve the desired behavior:
var fixture = new Fixture();
var objectToFill = new TypeWithProperties();
new AutoPropertiesCommand().Execute(objectToFill, new SpecimenContext(fixture));
Assert.NotNull(objectToFill.Value);
If you need that often, you can create an extension method for the IFixture in your test project.

SWIFT - How to get the type of an Array?

i'm writing a generic method who take a Dictionary and a given type in parameters for build an object.
For example, if you make a SOAP request for get a movie and put away the response in Dictionary you can make:
var movie : Movie = myGenericMethod(dic : Dictionary, objectToIntrospect : Movie()) as Movie
It's work with:
Simple Object
Complex Object
But i have a problem if you have an array of object.
So imagine your movie object contains an Array of Actors...
With reflection, i get all type of my class's attributes.
With this, i build an Array of Any object which contains my types.
For example, an object contained in other object (Actor in a Movie):
//All type of attributes of my movie object, at index [i] i have my "Actor" object
var anyType : Any = typesOfProperties[i]
//I cast it in object
var objectType : NSObject = anyType as NSObject
//Dont worry about this method, it's just for get the dictionary
var otherDico : NSDictionary = ConverterUtilities.extractDictionaryFromOtherDictionary(dict, dicoName: property, soapAction: soapAction) as NSDictionary
//I build the Actor object with the data of the dictionary. objectType.self give the Actor type
var propertyObject: NSObject = self.buildAnyObjectWithDictionary(otherDico, soapAction: "", objectToIntrospect:objectType.self) as NSObject
//I set the property Actor in my Movie object (myObjectToReturn)... The "property" parameter is the key
ConverterUtilities.setPropertyValue(property, value: propertyObject, objectToReturn : myObjectToReturn, isObject : true)
It's work perfectly... If i have just one actor in my movie object, the "propertyObject" will be an Actor type, and this cause objectType is an Actor object.
But, if i have an array, i'm redirect in method who treat Array, and my objectType return "Swift._NSSwiftArrayImpl" and my anyType object return "([myproject.Actor])".
I dont need to know this is just an Array, cause i know it. But i need to know that's an Array of Actor for build some Actor object dynamicly !
This is what i have for the moment:
var objToAdd: NSObject = self.buildAnyObjectWithDictionary(newDic, soapAction: "", objectToIntrospect: Actor()) as NSObject
arraySpecific.append(objToAdd)
As you can see, this work perfectly if i hardcode the type. But i need to make it like the previous example ! Like that:
var objToAdd: NSObject = self.buildAnyObjectWithDictionary(newDic, soapAction: "", objectToIntrospect: anObjectWithActorType) as NSObject
arraySpecific.append(objToAdd)
(Difference between first and second version is the objectToIntrospect parameter)
Do you know how can i use my Any object (contains: ([myproject.Actor]) for build an instance of one Actor ?
I really need ur help for this ! Regards !
PS: sorry for my bad english, i hope u understand me :)
Ok guys, i come back on my post cause i found a solution:
i create a master class, and all of my classes herit of this class.
This super-class have a method name getArrayType.
If one of my children-class need to be used with my generic method and if she contain a Array, they need to override the getArrayType.
Like that:
override func getArrayType(anyType : Any) -> String {
var className = " "
if(anyType as? NSObject == rows){
className = Properties.PROJECT_NAME + ".SimpleRow"
}
return className
}
And i call this method like that (TObject is my super-class):
var className = (objectToIntrospect as TObject).getArrayType(anyType)
var obj: AnyClass! = NSClassFromString(className)
This work perfectly, but you need to override a method. I hope this help u if u got the same problem !

An Array to Backbone Collection

I think this is a simple question. It is based of this question.
Filter and sort backbone collection with array of ids
router.on('route:reportCollection', function(assetid) {
var asset = assets.get(assetid);
var reportpointers = asset.get('reportsid');
var filteredReportCollection = new dilzeemQ.Collections.FilteredReportCollection({
});
ohhyearh = filteredReportCollection.filterById(reportpointers);
var reportCollectionView = new dilzeemQ.Views.ReportCollection({
collection: ohhyearh
});
console.log(ohhyearh);
console.log(reports);
$('#pagecontent').html(reportCollectionView.render().$el);
});
I have gotten it to work as I would like except the passing of the collection : ohhyearh
ohhyearh is something like this [child,child] where as I think it is expecting something along the lines of this {child,child}
At the point where you pass ohhyearh to the view, it should be an instanceof Backbone.Collection. That is what the view is expecting, not an array or an object with a property for each child.
Based on the code in the snippet, I would say that your filterById function is probably doing something unexpected and not returning an actual collection. You can either modify it to return new dilzeemQ.Collections.FilteredReportCollection(models) or you can leave it as is, and create a new collection when you pass it to the view:
collection: new dilzeemQ.Collections.FilteredReportCollection(ohhyearh)
This is assuming that your ohhyearh object is an array with Backbone.Model instances. You can pass an array of models to a collection constructor to get a collection of those models.

How can I return a Dictionary<string, Object> as JsonResult, AND get the proper result in JavaScript?

I'm constructing my JsonResult in Controller by adding some extra information to an already existing JsonResult (returned from a different method). In order to add more properties, I converted the initial JsonResult into a Dictionary:
IDictionary<string, object> wrapper = (IDictionary<string, object>)new
System.Web.Routing.RouteValueDictionary(json.Data);
Then I just add data by writing wrapper["..."] = "value".
The method returns a new JsonResult, with wrapper as .Data:
new JsonResult() { wrapper, JsonRequestBehavior.AllowGet };
and that's where the troubles start; while communication happens perfectly, and the success function gets called, the resulting array which I use in JavaScript doesn't have the clean structure I expect: instead of accessing values as val = ret.PropName1; I end up having to access a simple indexed array, which contains in turn a dictionary with two pairs: { "Value"="val, "Key"="PropName1" }; (so something like o[0].Key would give me the property name)
I'd like to know if there's a smart, fast way to rewrite the JsonResult creation in the Controller, to get a nice clean dictionary in the View.
There are a couple of ideas I have, but they aren't particularly clean: I could throw away JsonResult reuse on the server side, and just make an anonymous object with all the right properties; or, I could make a translation function in Javascript which could translate the result into a new Array(). I'm looking for better solutions.
[Later Edit] The array comes the way it does because the dictionary was defined as <string, object>. If it were <string, string>, it would be sent the way I'd originally expect it. But since I actually use objects from that bag, I'll just leave it the way it is, and pass the json response through the below function.
Addendum: while writing the above question, it occurred to me that the translation between 'bad' array and 'good' array is indeed very simple:
function translateAjaxResult(ret) {
var result = new Array();
if (ret == null) return result;
for(var i = 0; i < ret.length; i++)
result[ret[i].Key] = ret[i].Value;
return result;
}
Nonetheless, it's still a patch to a problem and not a fix to a problem, so I'd still like a more elegant solution.

Resources