Swift: Return Backendless to table - arrays

Im having a problem on putting my received data(from backendless) to a tableview.
As you can see on the image i have get data from Backendless and i have checked the data with print and it works.
Now i want to put the data to my tableView, but it does not work as you usually do with making an array in the beginning and then just put return.Sub.count.
Any idea how to do it?

You should declare
var Sub = [String]()
underneath your tableView class declaration (At the very top)
Then, in your function,
fetchingAllUsers()
delete the "var" keyword, and you should be fine.
Also, it'd help if you posted all of your code if you need me to be more specific.

Related

SWIFT Xcode11.5 - array append not working in ViewController

Hi I'm trying to declare a simple array variable inside class ViewController. But when I try to append value to it, Xcode just keep giving me "Consecutive declarations on a line must be separated by ';' ... Invalid redeclaration of 'mylist()'"
var mylist = [String] ()
mylist.append("abc")
I copied it into the Playground and it works just fine. But somehow inside ViewController it just doesn't like it. I only have 1 line that declares mylist in the whole project.
Has any one experienced this? I can't see what's wrong with it.
I'm in XCode 11.5(11E608c)
Thx in advance.
Sorry I got it now.
The problem is inside class ViewController (or any class) you can declare the array variables but you can't append values into it until after the class is initialized.
So append will need to be done inside one of the class's func like func viewDidLoad().
Because at any other time the variable is NOT actually init yet and therefore can't be used.
And thus you can't execute its append function.
So I put the mylist.append("abc") inside func viewDidLoad now and it's all good.
Thank You.

Extracting tableViewCell Widths in an Array?

I woukld like to form an Array which contains the widths of each label inside the customTableCell. As illustrated in the attached image, I managed to extract all the widths I am interested in but they are not all in the same array. Any idea how can I extrac t all the widths in ONE array?
#BrunoPastre is correct, but appending is also not the way to assign the values in the array. This function will be run many times for some cells, as you scroll up and down. You will end up with the same widths listed many times at different places in the array.
You should create the array with the right dimension, then assign them as cellsWidthsArray[indexPath.row] = cell.cellTextLabel.frame.size.width.
You should create your array only once, not every time tableView(_: UITableView, cellForRowAt: IndexPath) -> UITableViewCell is called. This can be achieved by moving the declaration of your array, on line 83, to somewhere outside of the function scope, but inside the class scope, like line 92. When you do that, cellsWitdhsArray will become a class variable, or an attribute, that can be accessed from anywhere inside the class
That method is called once per cell, if you declare a local variable cellsWidthArray its not going to persist across multiple calls of that function.
What you need is to "save" this array somewhere that isn't a local, temporary scope. The best way to do this is to save it as a property on the class.
I can see in your code you already have another array thats a property: tableViewRowsInsideSectionsArray. Scroll up to (hopefully) the very top of the class declaration in the same scope add your own cellsWidthArray.
It should look something like
class MyViewController {
...
private var cellsWidthArray: [CGFloat] = []
...
That way that local array isn't lost every time the function ends - it's owned by the view controller and is available anywhere within that class as long as that class exists.
HOWEVER, it may not work as you expect because another issue with that method (tableView(cellForRowAt:) is that it's only called when a cell is being displayed (visible on the screen). And it will be called multiple times if you scroll a cell off and back on the screen.
You can solve potential duplication by creating a dictionary where the key is something uniquely identifying the cell (it seems like its just going to be the text here) and the value is the width. Something like:
class MyViewController {
...
private var cellsWidthDictionary: [String: CGFloat] = [:]
...
func tableView(cellForRowAt:) { // I didn't feel like typing it all out
...
cellsWidthDictionary[theTextYouAreUsing] = width
But you now have another issue, the way you are getting the width, accessing the frame of the label just after you set the text, might not actually be correct. This function just prepares the cell, auto layout and frame adjustments might happen later.
A simple one line solution one might be tempted to do is to force a layout on the cell, after setting the text on the label, something like:
cell.cellTextLabel.sizeToFit() or cell.layoutIfNeeded()
that will just adjust the frame of the label to perfectly wrap the existing content.. but a much better solution would be to actually calculate it..
You could use https://developer.apple.com/documentation/foundation/nsstring/1531844-size
something like
let labelSize = (label.text?.size(attributes: [NSFontAttributeName: UIFont(name: label.font.fontName , size: label.font.pointSize)!]))
then accessing labelSize.width
You're still left with the problem of only having that function called when a cell is about to be displayed on the screen. You can either manually scroll through every cell to build that table if you're using it for debugging/testing/informative purposes. But otherwise you would need to do something else...
Fortunately, Swift has a function that calculates the size a string would take - you just have to make sure you specify the text/font/size/any other styling elements. I pointed it out above... you can just iterate through all the strings that you're feeding into the cells and generate the dictionary right then and there as soon as you get the data.
Keep in mind this assumes a single line, if you have a max width for the label or other constraints that would cause the text to be cut off you would need to be even more explicit - I encourage you to google how to calculate the size of a label based off your needs if so.

Angular copy not working on copying array

It seems that angular.copy() is not properly working on one of the items that I am using it on. Here's the sample code and the screenshot that follows.
console.log("Copy");
$scope.traffic_data = traffic_data;
$scope.total_data = total_data;
console.log($scope.traffic_data);
console.log($scope.total_data);
console.log("Original");
$rootScope.original_traffic_data = angular.copy($scope.traffic_data);
$rootScope.original_total_data = angular.copy($scope.total_data);
console.log($rootScope.original_traffic_data);
console.log($rootScope.original_total_data);
console.log("Variable data");
console.log(total_data);
console.log("=============");
The problem I am facing is that the
$rootscope.original_total_data
is not copying the contents of the
$scope.total_data
as seen on the screenshot. I have highlighted the different console logs to differentiate them from one another.
The line
console.log($rootScope.original_total_data);
shows no contents even though I have used angular.copy on that variable.
What am I missing here? Please help. Thanks.
Also $rootScope is already declared in the controller and it is working for the
$rootScope.original_traffic_data
so why is it not working for
$rootScope.original_total_data?
Thanks.
total_data is an array, whereas traffic_data is an object.
angular.copy() distinguishes between arrays and objects. For objects it will copy all the keys (properties). For arrays, it will only copy the array elements and not any custom properties attached to it - see source code.
If you want to set properties on total_data, you should make it into an object instead. It does not appear to have any indexed values, so this should not be a problem, and it probably should have been an object in the first place.

Array (class) filled with non nil values stays empty

I am currently having trouble filling up an array of customClass.
I try to fill it with a jsonFile. During my json parsing (using swiftyJSON) i loop and fill my array.
The problem is, at the end of my loop, it is still empty. I tested it in different ways, and here is my code:
That's the file where the problem is. In my loop I fill an Annotation, that I add with append to my array. The problem is what my print return. Here is a part of it:
It's just a small part of a huge jsonfile. And, my tmpAnnot.name is correctly printed every iteration. But when it comes to my Array, nothing.
So I'm completly lost and hope you could help me ^^
(And for the information, here is my custom class) :
And btw, I tried to print my array.count, and it's nil too
Im so sorry if the question has been posted. I couldn't find it in the entire website.
Change your JSONAnnotationList declaration to be an non-optional and assign it an empty array
var JSONAnnotationList: [UGOAnnotation] = []
You see, you have never created an array so there was nothing to be printed.
The whole point of optionals is to use them sparingly, not everywhere.

Accessing variable from other class returns null

I did a separate levelData class to be able to flexibly add levels. I was happy with it until my supervisor ordered me to convert my levelData into XML. I did an XML version of the levelData's data (question, answers, correct answer...). I used the old class and converted it so that it fetches the XML.
All seems well, I did traces of my answers array and it printed nicely...
But the headache started when I tried this.
// This code appears in a different class with
// currentLvl:LevelData initialized in the constructor.
quizHolder.ansA.ansHud.text = currentLvl.choices[1];
quizHolder.ansB.ansHud.text = currentLvl.choices[2];
quizHolder.ansC.ansHud.text = currentLvl.choices[3];
quizHolder.ansD.ansHud.text = currentLvl.choices[4];
// BTW, I can't make a for loop to do the same function as above. So wierd.
I tried to run it. it returned:
TypeError: Error #2007: Parameter text must be non-null.
at flash.text::TextField/set text()
at QuestionPane/setQuiz()
at QuestionPane/setQuestion()
at QuestionPane()
at LearningModule()
Where did I go wrong? I tried making a custom get function for it, only to get the same error. Thanks in advance. If I need to post more of the code, I will gladly do so =)
LevelData Class in PasteBin: http://pastebin.com/aTKC1sBC
Without seeing more of the code it's hard to diagnose, but did you correctly initialize the choices Array before using it? Failing that I think you'll need to post more code.
Another possible issue is the delay in loading the XML data. Make sure your data is set before QuestionPane tries to access it.
When did you call
quizHolder.ansA.ansHud.text = currentLvl.choices[1];
quizHolder.ansB.ansHud.text = currentLvl.choices[2];
quizHolder.ansC.ansHud.text = currentLvl.choices[3];
quizHolder.ansD.ansHud.text = currentLvl.choices[4];
these? You load the XML and on complete you fill the array, what is correct. but is the XML loaded and parsed to the time when you access (fill the TextFields) the choices array already?

Resources