Using iOS6's awesome new UICollectionView how am I able to delete all of the UICollectionViewCell objects in a big loop?
Say I've loaded all my data into it already, I hit refresh, I want to delete everything currently in there, then just call my stuff again.
I've found deleteItemsAtIndexPaths which takes an NSArray, so how can I get all items into it?
The proper way of clearing out a UICollectionVew is to simply clear the data source and then reload the collection view.
So if your data source was an array:
self.dataArray = nil;
[self.collectionView reloadData];
Boom, you're cleared out.
Turns out I can use deleteSections and pass a NSIndexSet through to it, making a range of 0,0 and it'll delete the one and only section.
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 0)];
[self.collectionView deleteSections:indexSet];
I could probably just use indexSetWithIndex but when I did my app crashed.
Related
I apologize in advance because I am very new to swift. I have an array of strings (answerSet) that pop up randomly and without repeating when a view controller is tapped. I did this through a while loop and added an if statement so once the last string in the array pops up the user can tap the screen and it triggers a segue to go to the next view controller (toEnd). This doesn't work properly as a couple strings occur when the screen is tapped but then the segue is triggered before all the strings in the array have been shown. I have provided the code. Please let me know how to fix this and thanks so much! PM.pngmy code
You need to remove the element in answerSet rather than setting it to an empty string.
answerSet.remove(at: randomIndex)
Without this, it can trigger the segue if on the next loop the randomIndex gets an empty string.
I have an array with a few items in it. Every x seconds, I receive a new array with the latest data. I check if the data has changed, and if it has, I replace the old one with the new one:
if (currentList != responseFromHttpCall) {
currentList = responseFromHttpCall;
}
This messes up the classes provided by ng-animate, as it acts like I replaced all of the items -- well, I do actually, but I don't know how to not.
These changes can occur in the list:
There's one (or more) new item(s) in the list - not necessaryly at the end of the list though.
One (or more) items in the list might be gone (deleted).
One (or more) items might be changed.
Two (or more) items might have been swapped.
Can anyone help me in getting ng-animate to understand what classes to show? I made a small "illustation" of my problem, found here: http://plnkr.co/edit/TS401ra58dgJS18ydsG1?p=preview
Thanks a lot!
To achieve what you want, you will need to modify existing list on controller (vm.list) on every action. I have one solution that may work for your particular example.
you would need to compare 2 lists (loop through first) similar to:
vm.list.forEach((val, index)=>{
// some code to check against array that's coming from ajax call
});
in case of adding you would need to loop against other list (in your case newList):
newList.forEach((val, index)=>{
// some code to check array on controller
});
I'm not saying this is the best solution but it works and will work in your case. Keep in mind - to properly test you will need to click reset after each action since you are looking at same global original list which will persist same data throughout the app cycle since we don't change it - if you want to change it just add before end of each function:
original = angular.copy(vm.list);
You could also make this more generic and put everything on one function, but for example, here's plnkr:
http://plnkr.co/edit/sr5CHji6DbiiknlgFdNm?p=preview
Hope it helps.
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.
Ok so I have been trying to figure this out for ages to no avail!!!
I have a list of 10 buttons, the user picks 1 of these buttons and I need to save that result to my users profile which is on a different View Controller. I was trying to put the buttons in an array but was not able to. Any help would be appreciated, I am very new to swift and xcode!
I tried adding them to a outlet collection but it didn't work either.
var genreArray = ["rockGenreButton", "bluesGenreButton","funkGenreButton", "indieGenreButton", "metalGenreButton", "popGenreButton", "altGenreButton","electronicGenreButton", "countryGenreButton", "tradGenreButton"]
Above is the array I created I am lost on which step to take next how do I call which [0] of the array was selected and save to currentUser?
Sorry if this is a really stupid question but I can't find a relevant answer anywhere!
You can add button tag and find which button has been clicked.
once you have created outlet for all buttons (same function)
#IBAction func btnClick(sender: AnyObject) {
print(sender.tag.description)
}
just ctrl click each button to same action
to get the tag of the pressed button
Please let me know if you need more explanation.
Using the tag property of views encourages lazy/bad design in software. It is storing data in views.
Not only that but how is any other developer (including yourself in 6 months time) going to know what if(btn.tag == 4) actually means? It hides the actual purpose of what you're doing.
One of the simplest ways to do something like this in a much better design approach is to create separate functions. One for each button. There is no reason for all your buttons to run the same function.
The first improvement would be to have functions like buttonOnePressed, buttonTwoPressed and so on.
#IBAction func buttonOnePressed {
// do something
}
Again though you are hiding the actual meaning of your app.
You could give them names like...
#IBAction func rockGenreButtonTapped {
// do something
}
#IBAction func bluesGenreButtonTapped {
// do something
}
That's much better. I now know just by looking at the function when it will run.
Maybe a better approach is to name the function as to what it's actually going to do...
#IBAction func showRockGenreDetails {
// present Rock Genre screen
}
#IBAction func showBluesGenreDetails {
// present Blues Genre screen
}
This time I not only know that it's an action (IBAction) I also know just by reading the function name what it is going to be doing.
As was mentioned in the comments. You could also do things like using a UITableViewController to present a list of genres. This is actually a much better approach than what I have shown here but is much more difficult to explain easily.
Can anybody point me in the right direction to how I could use UICollectionViewLayout to create an interface similar to the Pinterest column layout?
I tried searching online, but it looks like there are not many examples out there yet.
The 1000memories "Quilt" view is pinterest-like and open source: http://blog.1000memories.com/168-opensourcing-quilt, and you can dig through that to see how it works.
If you're looking for a more conceptual overview, here's the basic idea of what you're going to want to do. The easiest thing by far, if you just need a Pinterest-style layout, is to subclass UICollectionViewFlowLayout. You get a lot of layout help from this class, and Pinterest style is within its capabilities. You only need to override one method.
Set up a normal UICollectionView using UICollectionViewFlow layout. A quick way to do this is:
Drag a UIViewController onto a storyboard, drop a UICollectionView on that. Set the classes to match your custom classes, etc. You can use a delegate and create a delegate class here but strictly speaking that is not necessary to achieve JUST the Pinterest flow layout (you will almost definitely want to break the selection responsibility stuff into a delegate class in reality though).
Stub out a data source. Implementing the data source protocol for UICollectionView (http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewDataSource_protocol/Reference/Reference.html) is trivially simple. Make sure you set a reuse identifier on your UICollectionViewCell. You need:
(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
just return 1 for now;
(NSInteteger)collectionView:numberOfItemsInSection:
hardcode a number for now, make it 20.
– (UICollectionViewCell *)collectionView:cellForItemAtIndexPath:
This is one of the places where subclassing the flow layout's gonna do you a favor. All you really need to do here is call dequeueReusableCellWithReuseIdentifier:forIndexPath: with the index path. If you added a UIImageView or some labels to the cell, this would be a great place to actually assign the image, text, etc.
In the viewController's viewDidLoad instantiate a UICollectionViewFlowLayout and set the UICollectionView's datasource to yours and layout to flowlayout. Remember, this class is a subclass of UICollectionViewViewController.
self.collectionView.dataSource = [[YourDataSource alloc] init];
self.collectionView.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
Ok. At this point you should be able to run your app and see some stuff on the screen. This is a whirlwind overview. If you need more details about how to set up ViewControllers and so on there's tons of stuff available about that.
Now comes the important part, Pinterest-izing the flow layout.
First, add a new class that is a subclass of UIViewControllerFlowLayout. Change your ViewController's viewDidLoad to instantiate this class and assign as the UICollectionView's collectionViewLayout.
The method you are going to need to implement is - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect.
Here's the thing: The superclass is going to do almost all the work for you. Your code is going to look something like this:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
[attributes enumerateObjectsUsingBlock:^(id attr, NSUInteger idx, BOOL *stop) {
float newYCoord = [calculationMethodYouHaveToWriteFor:attr.frame];
attr.frame = CGRectMake(attr.frame.origin.x, newYCoord, attr.size.width, attr.size.height];
}];
}
Pinterest uses fixed-width columns, all you need to do in your calculation method is figure out what column you are in (`attr.origin.x / _columnWidth), and look up the total height in that column from the ivar you've been saving it in. Don't forget to add it to the new object's height and save it back for the next pass.
The flow layout superclass handles: making cells, determining which cells are visible, figuring out the contents size, figuring out the arrangement of the rows in the x direction, assigning index paths to cells. Lots of junk. And overriding that one method lets you fiddle with the y-pos to your heart's desire.
Heres two from github
https://github.com/jayslu/JSPintDemo
https://github.com/chiahsien/UICollectionViewWaterfallLayout
I've used a modified version of Waterfall in a project now, and I'm investigating JSPint now.
I have created a custom uicollectionviewlayout which is used in my personal project. Here is the link. Hope it helps.
https://github.com/johnny0614/YJZAlbumCollectionViewLayout
You can get anything you want from here:
https://github.com/ParsifalC/CPCollectionViewKit
For example(Both these two layouts are custom UICollectionViewLayout):