Create folders in UITableView from saved images - ios

I have an iOS Xcode 7 project written in Swift2. I'm saving photos to the app using NSCoding:
class UserImages: NSObject, NSCoding {
// MARK: Properties
var name: String
var photo: NSData // UIImage
...
}
These images currently are shown in a UITableView:
class ImagesTableViewController: UIViewController, UITableViewDelegate {
// MARK: Properties
var photos = [UserImages]()
...
// MARK: TableView Details
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return photos.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ImageTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ImageTableViewCell
let photo = photos[indexPath.row]
var image: NSData = photo.photo as NSData
cell.nameLabel.text = photo.name
cell.photoImageView.image = UIImage(data: image)
return cell
}
}
Works great, and in my custom cell, I have a UILabel and UIImageView for the name and photo.
My question is, how can I allow the user to create folders within the UITableView and allow the photos to be moved/organized in the folders? I'd like to try and keep the NSCoding unless it's impossible to implement folders and still use NSCoding. Thank you.

I ended up not using NSCoding and instead saving everything with CoreData. I setup an Entity called Photos and gave it attributes of:
name // Set as String
imageData // Set as Binary Data
folder // Set as String
The user then can add a new image and set the name of the photo and folder they want to put it in using UITextFields.
I then setup a FolderTableViewController displaying the folders from a request and in the didSelectRowAtIndexPath captured the image name from the selected cell and transferred it to a new ViewController which has a UITableView and displays the images from FolderTableViewController performing a request.predicate.
Works well for what I needed it to do. May not be the most glamorous but it made sense and did what I needed it to.

Related

Issue fetching data in custom cell class from firebase using Swift

I have made a custom cell class which fetches data from firebase. Everything's working fine but what happens is when new data is added, is gets displayed at the bottom not the top. In the code i have mentioned to insert new item to index path 0. Still the code is not working
Here's the code..
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
#IBOutlet weak var save: UIButton!
#IBOutlet weak var table: UITableView!
var firebase = Firebase(url: "https://meanwhile.firebaseio.com")
var messages = [String]()
var uid:String = ""
override func viewDidLoad() {
super.viewDidLoad()
var localArray = [String]()
firebase.observeEventType(.ChildAdded, withBlock: { snapshot in
//print(snapshot.value)
let msgText = snapshot.value.objectForKey("text") as! String
localArray.insert(msgText, atIndex: 0)
self.messages = localArray
self.table.reloadData()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.table.dequeueReusableCellWithIdentifier("Vish", forIndexPath: indexPath) as! CustomTableViewCell
let fdata = self.messages[indexPath.item]
cell.data.text = fdata as? String
return cell
}
}
I don't see the code here, but you mention you are using a custom table cell to load data.
If you are loading data inside of your CustomTableViewCell class, you either have to be very careful about how you do it, or move the data loading for the cells elsewhere.
This is because of dequeueReusableCellWithIdentifier. UITableView does not create a UITableViewCell for ever row of the table, but instead it maintains a smaller queue of cells that it reuses to reduce memory usage and increase performance.
The returned UITableViewCell object is frequently one that the application reuses for performance reasons.
Check if you are sharing state (that you didn't expect to be) and/or have race-conditions inside of your CustomTableViewCell.
These bugs often manifest as table view data appearing in the wrong cell.
Source: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/index.html#//apple_ref/occ/intfm/UITableViewDataSource/tableView:cellForRowAtIndexPath:

Trouble Loading Images in UITableView

I'm trying to put images into my UITableView. The Table is set up with a custom subclass cell. In the Subclass I have outlets:
#IBOutlet var titleLabel: UILabel!
`#IBOutlet var pillarIcon: UIImageView!`
In the Superclass I created a NSMutableArray for both:
var objects: NSMutableArray! = NSMutableArray()
var imageObjects: NSMutableArray! = NSMutableArray()
I place things into the Arrays within the viewDidLoad Method Each array has 4 items.
So when I call the Items:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.objects.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
cell.titleLabel.text = self.objects.objectAtIndex(indexPath.row) as? String
cell.pillarIcon.image = self.imageObjects.objectAtIndex(indexPath.row) as? UIImage
return cell
}
The cell.titleLabel.text items come up but the images in the cell.pillarIcon.image do not come show up in the table.
I have been working on this for a couple hours now and am going in circles it feels like. Also the image files have been loaded into the main file so that is not the problem.
Thanks in advance.
Make sure that your images are loaded into your Images.xcassets and then use the UIImage(name:) method to load the images.
Currently, you are loading your images into your imageObjects array as follows:
self.imageObjects.addObject("book.jpg")
You are not using the UIImage to load the image.
Once your images are a part of your project's image assets (Images.xcassets), load your images like so:
self.imageObjects.addObject(UIImage(named: "book"))
(The above example assumes that book is the name of the image asset group.)
Note, this Adding Image Assets web page has instructions on how to set up an image asset group.
It seems like you are loading images incorrectly, like #whyceewhite said in his answer.
I will try to make it clear to you:
open Assets.xcassets
Drop all images you want to use under AppIcon
Add images to your array this way:
imageObjects.addObject(UIImage(named: "whiteboardapp")!)
Use the same name displayed on Assets.xcassets folder

Populate cell in TableView from array and save the data in the cell

I need to load an array into the first only cell of my TableView, that means that I want the data in a single line. Afterwords I need these data to persist be saved so that they remain after I close and reopen the app.
Here is my TableView class that loads the array's data in each cell though instead only in the first one:
import UIKit
class ScoreboardViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let info = ["\(name01) ", "\(name02) ", "\(name03) ", "\(name04) ", "\(myCategory) ", "\(displayTime)"]
#IBOutlet weak var myTv: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.setHidesBackButton(true, animated: false)
myTv.delegate = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return info.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Allocate a table view cell
let cell = myTv.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = info[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Since I do not use Core Data in my app, would be better to save everything in a file or use NSUserDefaults?
You should divide data and visual output of data - so saving data for the app next launch shouldn't be related to UITableView at any way - use some nice patters, like MVVM or MVC. You can use some storage mechanisms like CoreData, NSUserDefaults as key-value data, SQL-base, output to file and many others.
In you case, i think NSUserDefaults is quite enough.
If you just want to store the Array then use an NSArray and store it using the convenient methods writeToFile and arrayWithContentsOfFile.
For limited amount of data you could also abuse the NSUserDefaults.
For larger amounts of data (lets say, if you don't know whether the number of rows is anyhow limiete) I strongly suggest to user Core Data for it.

Images not appearing in PFQueryCollectionViewController

I'm working on an iPhone app that should display images in a UICollectionView. The images are saved on the Parse cloud, and I'm using a subclass of PFQueryCollectionViewController to make the query and display the images.
Tapping on a MKMapView callout triggers the segue that shows the CollectionViewController. The images do not appear in the cells the first time the CollectionViewController is presented. However, if I go back to the MapView, and then return to the CollectionViewController, the images appear in the cells.
How can I get the images to appear the first time the PFQueryCollectionViewController is presented?
Here's my code:
class PhotoGridCollectionViewController: PFQueryCollectionViewController {
override func viewDidAppear(animated: Bool) {
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
//#warning Incomplete method implementation -- Return the number of sections
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//#warning Incomplete method implementation -- Return the number of items in the section
return self.objects.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFCollectionViewCell? {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("venuePhotoThumb", forIndexPath: indexPath) as! PhotoGridCollectionViewCell
if let pfObject = object {
cell.imageView.file = pfObject["imageFile"] as? PFFile
cell.imageView.loadInBackground({ (img, err) -> Void in
println("Download complete")
})
}
return cell
}
}
Since I'm using Storyboards, I pass my custom class the parseClass by setting it in the Attribute Inspector:
As you can see, I'm using the loadInBackground method of the PFImageView to load the images asynchronously, and I think this the problem might be caused by the images being downloaded after the cell is returned, but I don't have any other ideas. Does anyone know why the images are not appearing the first time the view is presented?
My co-developer finally found the answer to this. We had to set a placeholder image for the PFImageViews when configuring the cells in cellForItemAtIndexPath. The code examples on Parse do include setting the placeholder image, but they don't say that it is required for the PFQueryCollectionViewController to work properly. We considered it an aesthetic touch that we could come back to later.
So the answer is: in order for images to load properly in the cells of a PFQueryCollectionViewController you MUST provide a placeholder image when configuring the cells in cellForItemAtIndexPath.
Here's the code that worked:
let placeholder = UIImage(named: "myPlaceholderImage") //an image from images.xcassets in your xcode project
cell.imageView.image = placeholder
if let pfObject = object {
cell.imageView.file = pfObject["image"] as? PFFile
cell.imageView.loadInBackground()
}

How to populate UITableView with Data from Core Data

I created a function wich should save single elements of text the user types in a textField as Strings to a Entity in the CoreData:
#IBAction func tappedAddButton(sender: AnyObject) {
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var newExercises = NSEntityDescription.insertNewObjectForEntityForName("Exercises", inManagedObjectContext: context ) as NSManagedObject
newExercises.setValue(textField.text,forKey:"exercises")
context.save(nil)
}
No I wonder how to load the information back right to populate a tableView Cell with it.
In the past I used NSUserDefaults where I could load back a variable an use it without any further code in the functions for displaying them - I just have to call the variables.
How does this work while working with CoreData?
I want the data to be displayed after clicking the button and while the View is loading. Every String should be displayed in another Cell using the reuseIdentifier "Cell".
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exercises.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier) as UITableViewCell
...
return cell
}
I also would be really thankful for any further informations / links / videos - since I'm new to Swift.

Resources