I have a custom class "Book" and I am trying to save two books in an array in the following way:
class ViewController: UIViewController, UITableViewDataSource,
{
testBook.setBookTitle(title: "Harry Potter")
testBook.setbookPage(page: 12)
myBookCollection.append(testBook)
// testBook = Book()
testBook.setBookTitle(title: "testing")
testBook.setbookPage(page: 66)
myBookCollection.append(testBook)
for books in myBookCollection
{
print(books.getBookTitle())
}
}
If I run the above I my books in the array are stored as ["testing","testing"] as opposed to ["Harry Potter","testing"].
However If I uncomment testbook = Book() it works fine. Can someone please explain why this is the case ?
thanks,
Reference vs. value type.
If you define Book as a class, when you add it to array, it does not copy our object. testBook and myBookCollection[0] are holding the same object. When you change either one, the other will be affected. If you add testbook = Book(), then testBook is now pointing to a different object in memory and what you do it it has no impact on myBookCollection[0].
You can change Book from a class (reference type) to a struct (value type). In that case, when you add it to an array, it will add a copy to the array so what you do with testBook after doesn't affect it.
Here's a video from WWDC that demonstrates the exact problem you had: Building Better App with Value Types in Swift
the array doesn’t hold a copy of your Book instance , it simply hold the pointer to the object(book). When you change the title and page you are not changing the array contents, you are changing the object which testbook is pointing to.
however if you uncomment the line testBook = Book() . You create a new instance of Book class and you set the pointer testbook to the newly created object and all the changes from this point is done on the new object and that’s why it works as it should.
And all of this is true if your are using a class in your array , if you use struct that’s another story
Related
I am currently in a bit of a bind.
struct sectionWithDatesAsName {
var sectionName : String
var sectionObjects : [SoloTransactionModel]!
init(uniqueSectionName: String?, sectionObject: [SoloTransactionModel]?) {
sectionName = uniqueSectionName ?? "nil"
if let section = sectionObject {
sectionObjects = section.reversed()
}
}
}
I currently have an array of sectionWithDatesAsName. And I can work with it, display in the tableView among other things.
The bind comes up when I want to check some information in the sectionObject before displaying it on the tableView.
I want to check the type of the sectionObject which is saved in the object itself.
How do I check the information in the sectionObject without slowing down the app? Or have a horrible time complexity calculated?
(Note: I can't change the format of the struct has this has already been used by a whole lot of other processes)
Write a function in your sectionWithDatesAsName with the signature filteredSections(type: sectionType) -> sectionWithDatesAsName
(If you don't have the ability to edit the definition of sectionWithDatesAsName you can create an extension that adds the above function)
If the sectionWithDatesAsName is defined elsewhere, define this function in an extension.
When you call it, build a new sectionWithDatesAsName object by filtering the arrays to match the specified type.
Use the resulting filtered sectionWithDatesAsName object as the data model for your table view. It will be built once and used for the lifetime of the tableView, so you will pay an O(n) time cost to filter it once when you create it.
I have an array of objects:
class Person
attr_accessor :email
def initialize(email)
#email = email
end
end
array = [
Person.new('hello#gmail.com'),
Person.new('world#gmail.com')
]
I created a clone from the original array to perform map function, and then I mapped over each element to make its email attribute become uppercase:
clone = array.clone
clone.map { |obj|
obj.email.upcase!
obj
}
puts array.inspect # why is the original being mutated
puts clone.inspect
It mutates the original array. I have experimented with both dup and clone. and I get the same result. Why does map mutate the objects when operating on each element's attribute?
You cloned the array containing Person references, but you did not change the array; you changed the Person instances themselves. clone is so-called "shallow clone", which copies only the receiver object, but none of the objects whose references it may contain.
In real-world logic: you took a piece of paper on which you wrote "Jenny, Timmy". Then you copied it to another piece of paper. You then took the first piece of paper, found the people it refered to, and gave them an apple. Then you took the second piece of paper, found the people on it, and wondered where their apples came from. But there's only one Timmy, only one Jenny: you give the first list's Jenny an apple, the second list's Jenny also has one.
If you want to clone something, clone Jenny.
array.map { |person|
person.clone.yield_self { |clone|
clone.email = clone.email.upcase
}
}
(Note that I didn't use clone.email.upcase!. The reason is the same reason all over again: if you clone an object, they will both use the same string for email. upcase! changes that string, which would uppercase both clone's email and the original's email. Thus, we make a new email string for the clone.)
Things like this are best understood by stepping through the visualisation using this tool. However, the tool runs Ruby 2.2, which doesn't know about yield_self; this code is equivalent:
array.map { |person|
clone = person.clone
clone.email = clone.email.upcase
clone
}
You could also write this, though it won't visualise as clearly:
array.map(&:clone).map { |clone|
clone.email = clone.email.upcase
}
I suppose I need to be able to get the name of the class an object belongs to.
1: I have two classes
CandyBar
BottledWater
2: I put their names in two arrays
var foodArray(CandyBar, BottledWater);
var waterArray();
3: I add children to stage using the array; like this
var foodItem = new foodArray[i];
4: I later try and move the reference for BottledWater to the waterArray, but can't. I'm not creating any new object or anything, just moving the reference from one array to another. Furthermore, I cant remove the reference either.
I suppose I could say I am adding children from an array, then wanting to push a reference to that "class" into another array, while removing the reference from the original array.
The proper way to make an Array variable is:
var foodArray: Array = [CandyBar, BottledWater];
var waterArray: Array = new Array();
than you can do
waterArray.push( new foodArray[0] );
or
var foodItem = new foodArray[i]();
I want to create an array of JEditorPane depending on the size of a String array.
Is there a possibility to create an array of JEditorPane? If yes, how?
Here is an example:
String [] elements = {"0","1","2","3","4"};
JEditorPane ePane [] = new JEditorPane[5];
I want to to put each String element into the certain JEditPane, i.e
JEditorPane[0].setText(elements[0]);
etc. But I get a nullpointerexception when run I run.
Your problem is, that Java initializes a new array with the default value for the given type. In this case it is null, because the JEditorPane inherits from Object.
You cannot call a method on null - that is where the NullPointerException comes from.
The solution: make a loop in which you initialize the JEditorPane-objects in the array.
Then you can do JEditorPane[0].setText(elements[0]);
I've imported several images into an actionScript 3 document. I've turned them all into symbols (movie clips) and given them instance names to reference from ActionScript.
Ok, so I'm putting the instances into an array so I can loop through them easily, but for some reason, whenever I'm putting in the instance name, I do a trace on the value in the array and it's giving me the symbol object back, rather than the instance object.
Basically trying to loop through the array to make each instance's visibility = false
Here's a sample:
var large_cap_extrusion_data: Array = new Array();
large_cap_extrusion_data[0] = large_cap_extrusion_menu_button;
large_cap_extrusion_data[1] = extrusion_border_large_cap
large_cap_extrusion_data[2] = "Large Cap";
large_cap_extrusion_data[3] = large_cap_main_menu_button;
var extrusion_data: Array = new Array();
extrusion_data[0] = large_cap_extrusion_data;
trace(extrusion_data[0][0]);
The traces gives:
[object large_cap_menu_button]
(the parent symbol)
rather than:
"large_cap_extrusion_menu_button"
I'd be very grateful if someone could tell me where I'm going wrong...
when you trace and object, by default it describes it type. What you want is the "name" property of the object.
Try this:
trace(extrusion_data[0][0].name);
that should give you the instance nema of the large_cap_menu_button rather than the class description. Either way, you have the right object I bet.