Found nil when assigning image in UICollectionView - image

As a beginner in writing swift code, I am getting error in the following code:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView?.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell
// Configure the cell
let imageURL = NSURL(string: usersImageArray[indexPath.row])
print("The image url is \(imageURL)")
let imageData = NSData(contentsOf: imageURL as! URL)
cell.userImage.image = UIImage(data: imageData as! Data)
cell.userName.text = usersNameArray[indexPath.row]
return cell
}
The imageURL does contain an image url and the imageData does contain image Data but still I get "fatal error: unexpectedly found nil while unwrapping an Optional value"
I have seen and read other questions and answers and tried but still I can not find the problem. What exactly is causing the error though it does contain the URL and image data?
UPDATED:
My CollectionViewCell Class:
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var userImage: UIImageView!
#IBOutlet weak var userName: UILabel!
override func layoutSubviews() {
super.layoutSubviews()
self.makeImageRound()
}
func makeImageRound(){
self.userImage.layer.masksToBounds = true
self.userImage.layer.cornerRadius = self.userImage.frame.size.width/2.0
}
}

You have given the URL like this : optional(imageurl), it takes as it is , so you should avoid optional(. ) , to avoid this use '!' After userimagearray[indexpath.row]!
Try this and print imageurl and then see what happens
Try this
if imagedata == nil{
//give some image
}
else{
//give imagedata here
}
And take reuseidentifier = "cell"
Not cell whatever you take in a storyboard tableviewcell

Related

Saving UIImageView Locally

Right now I am able to have the user successfully take a picture using the camera and have their picture be uploaded into a imageview. However, if the user leaves that view controller when they eventually return the photo is no longer in that imageview. Is there anyway I am able to save the photo so that once a picture is taken and put into that imageview it is there until the user takes a different picture to replace it?
import UIKit
class ArsenalViewController: UIViewController,
UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var ball1: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addPhoto1(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
ball1.contentMode = .scaleToFill
ball1.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
First you need to save the image data somewhere (i.e. UserDefaults, Core Data, a database) and then retrieve it. UserDefaults is easy, try this:
//Encoding
let imageData:NSData = UIImageJPEGRepresentation(pickedImage!)! as NSData
//Saved image
UserDefaults.standard.set(imageData, forKey: "savedImage")
//Decode
if let data = UserDefaults.standard.object(forKey: "savedImage") as! NSData{
myImageView.image = UIImage(data: data as Data)
}
Encoding and saving image should happen right after updating your image and decoding should be done once the view has loaded all of its elements (viewDidAppear method).
After encoding and saving the image once, you can decode it anytime, even if the user left the VC and came back.

Swift Error: EXE_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

I'm trying to make this posting app similar to instagram but I am getting stuck on a issue once i press my compose button. This button is suppose to post the image but instead its crashing. I'm having an error after I try to upload a caption\image with my app here:
let imageData = UIImagePNGRepresentation(imageToBeUploaded!)!
It is giving me this error:EXE_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Please help!
#IBOutlet weak var captionTextView: UITextView!
#IBOutlet weak var previewImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
captionTextView.delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addImageTapped(sender: AnyObject) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypesForSourceType(.PhotoLibrary)!
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.previewImage.image = image
self.dismissViewControllerAnimated(true, completion: nil)
}
func textViewShouldEndEditing(textView: UITextView) -> Bool {
captionTextView.resignFirstResponder()
return true;
}
#IBAction func composeTapped(sender: AnyObject) {
let date = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
let localDate = dateFormatter.stringFromDate(date)
let imageToBeUploaded = self.previewImage.image
let imageData = UIImagePNGRepresentation(imageToBeUploaded!)!
let file: PFFile = PFFile(data: imageData)!
let fileCaption: String = self.captionTextView.text
let photoToUpload = PFObject(className: "Posts")
photoToUpload["Image"] = file
photoToUpload["Caption"] = fileCaption
photoToUpload["addedBy"] = PFUser.currentUser()?.username
photoToUpload["data"] = localDate
//Get bytes size of image
/* var imageSize = Float(imageData!.length)
//Transform into Megabytes
imageSize = imageSize/(1024*1024)
print("Image size is \(imageSize)Mb")
*/
do{
try photoToUpload.save()
} catch _ {
}
print("Successfully Posted.")
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("postController")
self.presentViewController(vc! as UIViewController, animated: true, completion: nil)
}
It seems that you are unwraping an optional value without actualy checking if it is nil.
Probably the issue is from let file: PFFile = PFFile(data: imageData)!. You must check for nil before you unwrap a variable.

xcode/swift error: could not find member "row"

I keep getting this error: "could not find member row".
Here is my code:
import UIKit
import CoreData
class ListTableViewController: UITableViewController {
var myList: Array<AnyObject> = []
override func viewDidAppear(animated: Bool) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let freq = NSFetchRequest(entityName: "List")
myList = context.executeFetchRequest(freq, error: nil)!
tableView.reloadData()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "update" {
//GETTING ERROR ON THIS NEXT LINE//
var selectedItem: NSManagedObject =
myList[self.tableView.indexPathForSelectedRow()?.row!] as! NSManagedObject
let IVC: ItemViewController =
segue.destinationViewController as! ItemViewController
IVC.item = selectedItem.valueForKey("item") as! String
IVC.quantity = selectedItem.valueForKey("quantity") as! String
IVC.info = selectedItem.valueForKey("info") as! String
IVC.existingItem = selectedItem
}
}
Can anyone please help me get rid of that error.
When you call self.tableView.indexPathForSelectedRow() you are getting back a NSIndexPath instance, not an integer. You then need to ask that NSIndexPath for its row. So the call should read self.tableView.indexPathForSelectedRow().row()
This is of course assuming you only have one section in your table view.
Try this:
var selectedItem = myList[self.tableView.indexPathForSelectedRow()!.row] as! NSManagedObject

Xcode 6.3 Parse SDK 1.7.1 PFTableViewCell Error "has incompatible type"

My code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell{
var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as!
CustomTableViewCell!
if cell == nil {
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomCell")
}
// Extract values from the PFObject to display in the table cell
if let username = object["username"] as? String {
cell.customUser.text = username
}
if let title = object["Title"] as? String {
cell.customTitle.text = title
}
// Display image
var initialThumbnail = UIImage(named: "Swarm_Bee.png")
if let thumbnail = object["imageFile"] as? PFFile {
thumbnail.getDataInBackgroundWithBlock{
(imageData, error) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.customImage.image = image
}}
}
return cell
}
receives the following error
overriding method with selector 'tableView:cellForRowAtIndexPath:object:' has incompatible type '(UITableView,NSIndexPath,PFObject) -> PFTableViewCell'
I have looked up all the compatibility errors (removing !). Another post had a similar issue:
Parse SDK 1.7.1 not working in Xcode 6.3
But only their number 3 error. All other issues in that post were addressed, but this error remains. Any solutions or recommendations of where to look?
I figured it out. Use the following override function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
//...
}
The difference is making the PFObject and the PFTableViewCell optionals.

TableViewController and CustomCell using Swift

I'm trying to populate a TableViewController with data and display it using a CustomCell so I can have two labels and a button on each row.
I have placed the two labels and the button in the PrototypeCell within the Main Storyboard.
I have created a CustomCellTableViewCell class:
import UIKit
class CustomCellTableViewCell: UITableViewCell {
#IBOutlet var customCellLabel1: [UILabel]!
#IBOutlet var customCellLabel2: [UILabel]!
#IBOutlet var CustomCellButton: [UIButton]!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
and within my UITableViewController I have:
var DevicesList: Array<AnyObject>=[]
var ii: Int = 1
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID : NSString = "DeviceCell"
var cell : CustomCellTableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as CustomCellTableViewCell
if DevicesList.count > 0 {
var data: NSManagedObject = DevicesList[indexPath.row] as NSManagedObject
cell.customCellLabel1[indexPath.row].text = data.valueForKeyPath("name") as? String
println("loading row \(ii) loaded!")
ii++
} else {
println("nothing loaded...?")
}
println("cell loaded")
return cell
}
when I run it though the first row is loaded but then I get a:
loading row 1 loaded!
cell loaded
fatal error: Array index out of range
The guilty line is shown as this one:
cell.customCellLabel1[indexPath.row].text = data.valueForKeyPath("name") as? String
I have 7 rows to load so somewhere I need to append the labels/button array and if so where/how do I do it?
Thanks!
Kostas
Just for future searches here is how it was solved:
Created new class:
import UIKit
class DeviceCustomCell: UITableViewCell {
#IBOutlet var myLabel1: UILabel!
#IBOutlet var myLabel2: UILabel!
#IBOutlet var myButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func PressButton(sender: AnyObject) {
myButton.setTitle("OFF", forState: UIControlState.Normal)
}
}
Linked the labels and button from the Main storyboard to the two variables (New Reference Outlet).
Important to have the Identifier as "DeviceCustomCell" for the Prototype Cell and then modify the function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID : NSString = "DeviceCustomCell"
var cell = tableView.dequeueReusableCellWithIdentifier("DeviceCustomCell") as DeviceCustomCell
if DevicesList.count > 0 {
var data: NSManagedObject = DevicesList[indexPath.row] as NSManagedObject
var devicename : String = data.valueForKeyPath("name") as String
var lastchanged: String = data.valueForKeyPath("lastChangedRFC822") as String
cell.myLabel1.text = devicename
cell.myLabel2.text = lastchanged
println("loading row \(ii) loading...")
ii++
return cell
} else {
println("nothing loaded...?")
}
return cell
}
This now works nicely!
Important is to understand this line:
var cell = tableView.dequeueReusableCellWithIdentifier("DeviceCustomCell") as DeviceCustomCell
as it holds the key to success! :)
Kostas

Resources