While reloading a tableView the app crashes and I am getting error
malloc:
error for object 0x7f8c7b99be80: pointer being freed was not allocated
set a breakpoint in malloc_error_break to debug
I have set the Symbolic breakpoint for
malloc_error_break
Also try to find memory leakage with "Instruments" but it just showing same error in console but here is no any memory leakage.
How to solve this issue.
(I am using 8.3 SDK and 6.3.1 Xcode)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var ResultCellIdentifier = "placementID"
var LoadCellIdentifier = "LoadingCell"
var count = self.arrayOfAllData.count as NSInteger
if count == 0 && indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("LoadingCell") as! UITableViewCell
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
indexPATH = indexPath
var tweet = self.arrayOfAllData.objectAtIndex(indexPath.row) as! NSDictionary
let created_at = tweet.valueForKey("created_at") as? NSString
var dateArray : NSArray = created_at!.componentsSeparatedByString(" ")
if dateArray.count != 0 {
let month = dateArray.objectAtIndex(1) as! String
let date = dateArray.objectAtIndex(2) as! String
cell.timeLabel.text = String(format: "%# %#", date,month)
}
///////////any url present in tweet text
var entities = NSDictionary()
entities = tweet.valueForKey("entities") as! NSDictionary
var urlsArray = entities.valueForKey("urls") as! NSArray
if urlsArray.count == 0 {
}else {
for item in urlsArray as! [NSDictionary] {
let expanded_url = item.valueForKey("expanded_url") as? String
}
}
///////////
var tweet_id_str = NSString()
var user_id_str = NSString()
var data = NSData()
// var name = NSString()
///////////count of retweets
var retweet_count = tweet.valueForKey("retweet_count") as! NSInteger
var retweeted_status = tweet.valueForKey("retweeted_status") as! NSDictionary
var favorite_count = retweeted_status.valueForKey("favorite_count") as! NSInteger
///////////tweet id
tweet_id_str = retweeted_status.valueForKey("id_str") as! NSString
if retweeted_status.isEqual(nil) {
}
else {
var user = retweeted_status.valueForKey("user") as! NSDictionary
///////////last update
let created_at = retweeted_status.valueForKey("created_at") as! NSString
///////////
///////////user name who added this tweet
cell.titleLabel.text = user.valueForKey("name") as? String
///////////user id who added this tweet
user_id_str = user.valueForKey("id_str") as! NSString
///////////screen name
let screen_name = user.valueForKey("screen_name") as! NSString
var followers_count = user.valueForKey("followers_count") as! NSInteger
///////////profile image of the tweet
cell.avatarImageView.image = UIImage(named: "Twitter Avatar.jpg")
let profile_image_url = user.valueForKey("profile_image_url") as! NSString
var imageUrl = NSURL(string: profile_image_url as String)
let request: NSURLRequest = NSURLRequest(URL: imageUrl!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
if data != nil {
var image = UIImage(data: data)
cell.avatarImageView.image = image
}
}
})
if retweet_count >= 5 || favorite_count >= 15 || followers_count >= 30000 {
cell.featuredImageView.hidden = false
cell.featuredImageView.image = UIImage(named: "new feature star")
}
else {
cell.featuredImageView.hidden = true
}
}
cell.mailLabel.text = ""
let tweetText = tweet.valueForKey("text") as? NSString
cell.beattypeLabel.text = tweetText as? String
if tweetText?.containsString("#gmail") == true{
NSLog("Mail id is present at index : %d", indexPath.row)
var words = NSArray()
words = NSArray(array: tweetText!.componentsSeparatedByString(" "))
var mailAddress = NSString()
for var i = 0; i < words.count; i++ {
var mailAdd = words.objectAtIndex(i) as! NSString
if mailAdd.rangeOfString("#gmail").location != NSNotFound {
NSLog("mail Address : %#", mailAdd)
if mailAdd.rangeOfString(".com").location == NSNotFound {
var lastChar = mailAdd.characterAtIndex(mailAdd.length-1)
var lastCharStr:NSString = NSString(format: "%ch", lastChar)
mailAddress = mailAdd.stringByAppendingString(".com")
}
}
}
}
return cell
}
}
at the same time Thread 1 showing this
http://i.stack.imgur.com/2YoQp.jpg
(please go through this image)
use
var cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
if cell.isEqual(nil) {
cell = PlacementsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "placementID")
}
instead of
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
and change downloading image in other thread like follow
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
println("This is run on the background queue")
var imageData = NSData(contentsOfURL: imageUrl!)
var image = UIImage(data: imageData!)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("This is run on the main queue, after the previous code in outer block")
cell.avatarImageView.image = image
})
})
Related
I have used tableView to show the post and when I am scrolling my page sometimes it crashes and throws error as: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (119) must be equal to the number of rows contained in that section before the update (105), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' I am unable to find out the reason why it's happening
func getFeeds(){
DispatchQueue.main.async {
if(self.isCommentsOpened == false && self.spinner == nil && !self.isPaginating && self.isScrollingUp == false){
self.spinner = CommonUtils.showLoader(view: self)
}
}
var paramsDictionary = [String:Any]()
let xAuthToken:String=UserDefaults.standard.string(forKey: JsonContants.X_AUTH_TOKEN)!
let entityId:String=UserDefaults.standard.string(forKey: JsonContants.ENTITY_ID)!
var apiUrl=domains.global+Apis.feedQueryApi
apiUrl=apiUrl.replacingOccurrences(of: "{entity_id}", with: entityId)
if(isPaginating && pageNo<totalPages){
paramsDictionary[JsonContants.PAGE_NO] = pageNo+1
paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
}else{
paramsDictionary[JsonContants.PAGE_NO] = 1
paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
}
HttpClientApi.instance().makeAPICall(token: xAuthToken,refreshToken: "",url: apiUrl, params:paramsDictionary, method: .POST, success: { (data, response, error) in
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
let httpStatus=response as HTTPURLResponse!
let statusCode=httpStatus?.statusCode
let pageDetails = json[JsonContants.PAGE_DETAILS] as! [String:Any]
if(pageDetails.count>0){
self.pageNo = pageDetails[JsonContants.PAGE_NO] as! Int
self.pageSize = pageDetails[JsonContants.PAGE_SIZE] as! Int
self.totalPages = pageDetails[JsonContants.TOTAL_PAGES] as! Int
}
let feedsArray = json[JsonContants.FEEDS] as! Array<Dictionary<String, Any>>
if(!self.isPaginating){
self.feedsJsonArray = feedsArray
self.feedIdsArray = [String]()
self.feedIdUserIdDict = [String:String]()
self.userIdUserJsonDict = [String:[String:Any]]()
self.imagesJsonArray = []
self.feedIdActivityJsonDict = [String:[[String:Any]]]()
}else{
self.paginationFeedIdsArray = [String]()
self.feedsJsonArray.append(contentsOf: feedsArray)
}
var paginationUserIdDict = [String]()
for object:Dictionary<String,Any> in feedsArray{
let feedId=object[JsonContants.FEED_ID] as? String
self.feedIdsArray.append(feedId!)
let userId = object[JsonContants.USER_ID] as? String
self.feedIdUserIdDict[feedId!] = userId
if(self.isPaginating){
paginationUserIdDict.append(userId!)
self.paginationFeedIdsArray.append(feedId!)
}
}
DispatchQueue.main.async {
if(!self.isPaginating){
self.getUserList(userIds: Array(self.feedIdUserIdDict.values))
self.dismissLoader()
}else{
self.getUserList(userIds: paginationUserIdDict)
self.dismissLoader()
}
}
}
} catch let error {
print(error.localizedDescription)
DispatchQueue.main.async {
if(self.spinner != nil){
self.spinner!.dismissLoader()
self.spinner = nil
}
if((self.topScrollSpinnerContainerView.isHidden == false) || (self.downScrollSpinnerContainerView.isHidden == false)){
self.scrollSpinner!.dismissLoader2()
self.topScrollSpinnerContainerView.isHidden = true
self.downScrollSpinnerContainerView.isHidden = true
}
}
}
}, failure: { (data, response, error) in
DispatchQueue.main.async {
if(self.spinner != nil){
self.spinner!.dismissLoader()
self.spinner = nil
}
if((self.topScrollSpinnerContainerView.isHidden == false) || (self.downScrollSpinnerContainerView.isHidden == false)){
self.scrollSpinner!.dismissLoader2()
self.topScrollSpinnerContainerView.isHidden = true
self.downScrollSpinnerContainerView.isHidden = true
}
}
print(error?.localizedDescription as Any)
})
}
func showSmallLoaderAtBottom(view: UIView) -> UIView {
var spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height:50))
let spinner = MDCActivityIndicator(frame: CGRect(x: 0, y: 0, width: 50, height:50))
spinner.cycleColors = [UIColor(named: AppColors.appSkyBlue.rawValue)!, UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!]
spinnerView.addSubview(spinner)
view.addSubview(spinnerView)
spinner.startAnimating()
return spinnerView
}
func getMoreData(){
if(self.pageNo < self.totalPages){
scrollSpinner = showSmallLoaderAtBottom(view: downScrollSpinnerContainerView)
downScrollSpinnerContainerView.isHidden = false
isPaginating = true
self.getFeeds()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
self.currentRow = indexPath.row
let cell=tableView.dequeueReusableCell(withIdentifier: "feed_tvcell", for: indexPath) as! FeedTableViewCell
cell.selectionStyle = .none
cell.feedViewController = self
cell.feedsStackView.translatesAutoresizingMaskIntoConstraints = false
let feedJson = self.feedsJsonArray[indexPath.row]
cell.messageTextLabel.numberOfLines = 0
cell.messageTextLabel.lineBreakMode = .byWordWrapping
cell.messageTextLabel.sizeToFit()
if(feedJson[JsonContants.CONTENT] != nil && !(feedJson[JsonContants.CONTENT] as! String).elementsEqual(JsonContants.NA)){
cell.feedMessageView.isHidden = false
cell.messageTextLabel.text = (feedJson[JsonContants.CONTENT] as! String).decodeEmoji
}else{
cell.feedMessageView.isHidden = true
}
let feedId = feedJson[JsonContants.FEED_ID] as! String
let userId = feedIdUserIdDict[feedId] as! String
let userJson = userIdUserJsonDict[userId] as? [String:Any]
var userTitle:[[String:Any]]?
var lastName:String?
var firstName:String?
if(userJson != nil){
userTitle = userJson![JsonContants.USER_TITLE] as? [[String:Any]]
lastName = userJson![JsonContants.LAST_NAME] as? String
firstName = userJson![JsonContants.FIRST_NAME] as? String
}
var roles = self.appDefaults.value(forKey: JsonContants.ROLE) as! [String]
if(firstName != nil){
cell.feeUserName.text = (firstName as! String)
}
if(lastName != nil){
cell.feeUserName.text = cell.feeUserName.text!+" "+(lastName as! String)
}
hideAndShowFeedDeleteButton(roles, cell, userId)
addActionTargetsToCellButtons(cell)
var time = feedJson[JsonContants.LAST_ACTIVITY_TIME] as! Int64
var timeDiff = CommonUtils.getSystemTimeInMillis() - time
cell.feedTime.text = CommonUtils.getStringValueOfTimeDiff(timeDiff: timeDiff)
setCountZero(cell)
setLikeCount(feedId, cell, feedJson)
var feedType = feedJson[JsonContants.TYPE] as! String
let feedCommentCount = feedJson[JsonContants.FEED_COMMENT_COUNT] as! Int
cell.commentCountLabel.text = String(feedCommentCount)
if(userJson != nil){
let userId = userJson![JsonContants.USER_ID] as? String
var cachedMediaId:UIImage?
let userJsonFromDb = CoreDataDatabaseManager.coreDataDatabaseManager.getUser(id: userId!)
if(userJsonFromDb != nil && userJsonFromDb.count>0){
let imageId = userJsonFromDb[JsonContants.IMAGE_ID] as? String
if(userId != nil && imageId != nil){
cachedMediaId = self.getSavedImage(named : imageId!+"."+"png")
}
}
if(cachedMediaId == nil){
cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
getUserImages(userIds: [userId!],cell: cell)
}else{
cell.feedUserImage.image = cachedMediaId
}
}else{
cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
}
if(userJson != nil && userJson![JsonContants.RESIDENT_DETAILS] != nil){
let residentDetails = userJson![JsonContants.RESIDENT_DETAILS] as! [String:Any]
let buildingName = residentDetails[JsonContants.BUILDING_NAME] as! String
let flatName = residentDetails[JsonContants.FLAT_NAME] as! String
let feedUserName:String = cell.feeUserName.text!
if(buildingName.count>0 && flatName.count>0){
cell.feeUserName.text = feedUserName+" - "+buildingName+"("+flatName+")"
}
}else if(userTitle != nil && userTitle!.count>0) {
let titleDict = userTitle![0]
let name = cell.feeUserName.text
if(titleDict.count>0){
var title = titleDict[JsonContants.TITLE] as! String
if(title.elementsEqual(JsonContants.ADMINISTRATOR)){
cell.feeUserName.text = name!+" - "+"Admin"
}
}
}
if(feedType.elementsEqual(JsonContants.SURVEY)){
let options = feedJson[JsonContants.OPTIONS] as! [[String:Any]]
setSurveyData(cell, options, feedId, feedJson,indexPath: indexPath)
}else{
if(feedJson[JsonContants.MEDIA_INFO] != nil && (feedJson[JsonContants.MEDIA_INFO] as! [String:Any]) != nil &&
(feedJson[JsonContants.MEDIA_INFO] as! [String:Any]).count>0){
let mediaJson = feedJson[JsonContants.MEDIA_INFO] as! [String:Any]
let mediaType = mediaJson[JsonContants.MEDIA_TYPE] as! String
cell.optionsTableView.isHidden = true
cell.surveyTotalVotesLabel.isHidden = true
cell.surveyTotalVotesLabelContainer.isHidden = true
cell.feedVideoView.isHidden = true
cell.feedImageView.isHidden = true
if(mediaType.elementsEqual(JsonContants.IMAGE)){
configureFeedImageViewAndSetImage(cell, mediaJson, feedId,indexPath)
}else{
configureFeedMediaViewAndSetVideo(cell, mediaJson, indexPath)
}
}else{
cell.mediaType = "TEXT"
hideFeedMediaViews(cell)
cell.layoutIfNeeded()
}
}
if(indexPath.row == (self.feedsJsonArray.count-2)){
DispatchQueue.main.async{
self.getMoreData()
}
}
cell.layoutIfNeeded()
return cell
}
This kind of error is seen when you explicitly insert or delete cells or sections into or from a TableView and do not simultaneously readjust your row or section counts to match. In your case the error message is telling you exactly what the count mismatch is. The code you posted is not showing any inserts or deletes of rows from the TableView so it must be happening somewhere else in your code, maybe in your getFeeds() method?
I have got the response data in the log window but I am not able to populate on the tableView dynamically. I have tried many methods but not working
// send request to URL
let urlPath:String = "http://api.androidhive.info/contacts/"
var url:NSURL = NSURL(string: urlPath)!
var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request1.HTTPMethod = "POST"
var stringPost = "msg=123" ///key and value
let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)
request1.timeoutInterval = 60
request1.HTTPBody = data
request1.HTTPShouldHandleCookies = false
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler: {(response:NSURLResponse!, data:NSData!, error:NSError!) -> Void in
//print object response
println("response = \(response)")
//print response body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("response data = \(responseString)")
The data is coming from the url. I can see it.
// Extract JSON
var err: NSError?
let json : NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
if let items = json["contacts"] as? [[String:AnyObject]]
{
for item in items {
// construct your model objects here
self.contactList.append(Person(dictionary:item))
}
// dispatch_async(dispatch_get_main_queue()) {
// self.tableView.reloadData()
}
The above code line is not appending data (not working).
Table view code
//how many sections
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//how many rows
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contactList.count
//return cellCount
}
//contents
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// var cell = UITableViewCell()
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
// cell.textLabel?.text = "aaa"
let person = contactList[indexPath.row]
cell.textLabel?.text = person.name
return cell
}
Please tell me where the problem is.
That's a good example to create a custom class
class Person { // can be also a struct
let id : String
let name : String
let email : String
let address : String
let gender : String
let phone : String
init(dictionary : [String : AnyObject]) {
id = dictionary["id"] as? String ?? ""
name = dictionary["name"] as? String ?? ""
email = dictionary["email"] as? String ?? ""
address = dictionary["address"] as? String ?? ""
gender = dictionary["gender"] as? String ?? ""
phone = dictionary["id"] as? String ?? ""
}
}
Then create contactList as
var contactList = [Person]()
and populate the list with
if let items = json["contacts"] as? [[String:AnyObject]]
{
for item in items {
// construct your model objects here
self.contactList.append(Person(dictionary:item))
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
and display the name in each cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// var cell = UITableViewCell()
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
let person = contactList[indexPath.row]
cell.textLabel?.text = person.name
return cell
}
If all values of the dictionary containing the person data are of type String you can change the following lines to be still more specific
in Person
init(dictionary : [String : String]) {
id = dictionary["id"] ?? ""
...
phone = dictionary["id"] ?? ""
}
in the view controller
if let items = json["contacts"] as? [[String:String]]
Create NSObject class
public class Global: NSObject
{
let name : String!
.
.
}
Within for item in items
var object: ObjectClass = ObjectClass()
object.id = item["id"]!
.
.
self.contactList.append(object)
In cellForRowAtIndexPath
var object: ObjectClass = self.contactList [indexPath.row] as! ObjectClass;
///get the values as
cell.label.text = object.name;
Instead create model. you can create Class for Contact.
class Contact {
var id : String?
var name : String?
}
Create a Sample responses.
// Contact1
let cont1 : NSMutableDictionary = NSMutableDictionary.init(object: "7", forKey: "id");
cont1.setValue("vignesh", forKey: "name");
// Contact2
let cont2 : NSMutableDictionary = NSMutableDictionary.init(object: "8", forKey: "id");
cont2.setValue("karthi", forKey: "name");
let contactArray :NSArray = NSArray.init(array: [cont1,cont2]);
// Response Dictionary
let responseDic : NSMutableDictionary = NSMutableDictionary.init(object: contactArray, forKey: "contacts");
Parse Response value.
// Create Contact list Array.
var contactList : Array<Contact> = []
if let items = responseDic["contacts"] as? NSArray
{
for item in items {
// construct your model objects here
let id: NSString = item["id"] as! NSString
let name: NSString = item["name"] as! NSString
let contUser : Contact = Contact.init();
contUser.id = id as String;
contUser.name = name as String;
contactList.append(contUser)
}
}
List item
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var tableViewCountry: UITableView!
var names: [String] = []
var contacts: [String] = []
var gender: [String] = []
var mob:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
tableViewCountry.dataSource = self
tableViewCountry.delegate = self
self.tableViewCountry.register(UINib(nibName: "ContactTableViewCell", bundle: nil), forCellReuseIdentifier: "ContactTableViewCell")
let url=URL(string:"http://api.androidhive.info/contacts/")
do {
let allContactsData = try Data(contentsOf: url!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = allContacts["contacts"] {
for index in 0...arrJSON.count-1 {
let aObject = arrJSON[index] as! [String : AnyObject]
names.append(aObject["name"] as! String)
contacts.append(aObject["email"] as! String)
gender.append(aObject["gender"] as! String)
let phone = aObject["phone"]
mob.append(phone?["mobile"] as! String)
}
}
print(allContacts)
print(names)
print(contacts)
self.tableViewCountry.reloadData()
}
catch {
print("error")
}
}
I want to be able to load images and video to my UICollectionView.
This is my parse query code:
var arrayOfDetails = [Details]()
func queryFromParse(){
let query = PFQuery(className: "currentUploads")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil
{
if let newObjects = objects as? [PFObject] {
for oneobject in newObjects {
let text = oneobject["imageText"] as! String
let username = oneobject["username"] as! String
let objID = oneobject.objectId!
let time = oneobject.createdAt!
let likedBy = oneobject["likedBy"] as! NSArray
let comments = oneobject["comments"] as! NSArray
if let userImage = oneobject["imageFile"] as? PFFile {
let userImage = oneobject["imageFile"] as! PFFile
let imageURL = userImage.url
let OneBigObject = Details(username: username, text: text, CreatedAt: time, image: imageURL!, objID: objID, likedBy: likedBy, comments: comments)
self.arrayOfDetails.append(OneBigObject)
dispatch_async(dispatch_get_main_queue()) { self.collectionView.reloadData() }
}
}
}
}
}
}
My struct details:
struct Details {
var username:String!
var text:String!
var CreatedAt:NSDate!
var image:String!
var objID:String!
var likedBy:NSArray
var comments:NSArray
init(username:String,text:String,CreatedAt:NSDate,image:String,objID:String,likedBy:NSArray,comments:NSArray){
self.username = username
self.text = text
self.CreatedAt = CreatedAt
self.image = image
self.objID = objID
self.likedBy = likedBy
self.comments = comments
}
}
In my cellForItemAtIndexPath i use let post = self.arrayOfDetails[indexPath.row] to get the current object, but i have a little problem here. In parse i store the images as File with name "uploaded_image.png", and the videos as File with name "uploaded_video.mp4". How can i make a UIImageView in the UICollectionViewCell if the file is a "uploaded_image.png" and a video player if the file is a "uploaded_video.mp4"?
Or any other suggestions?
I'm building an app for creating events which uses parse as a back end. The main interface is a collection view with a custom cell, which when flipped displays an array of UIImageViews added to the cell file as an IBOutlet collection.
#IBOutlet var imageViewArray: [UIImageView]!
Inside the event.getDataInBackground block I have this code, which doesn't get called for some reason, I think it will work once it is but does anyone know what's up? Thanks!
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
if let picture = usr.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
}
}
The whole cell for row at index path method (The creator image shows up and is called but the attendee array part is not).
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//sets up cell
let cell : EventCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! EventCell
//adds attend action
cell.attendButton.addTarget(self, action: "buttonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
//queries parse for events
let event = events?[indexPath.row]
event?.eventImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let data = data, image = UIImage(data: data) {
cell.eventBackgroundImage.image = image
cell.eventTitleLabel.text = event?.eventTitle
//gets profile picture of events creator
if let eventCreator = event?.objectForKey("user") as? PFUser {
if let creatorImage = eventCreator.objectForKey("profilePicture") as? PFFile {
creatorImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
cell.creatorImageView.image = UIImage(data: data!)
})
}
}
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
if let picture = usr.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
}
}
//sets correct category for cell image
if event?.category == "" {
cell.categoryImageView.image = nil
}
if event?.category == "The Arts" {
cell.categoryImageView.image = UIImage(named: "Comedy")
}
if event?.category == "The Outdoors" {
cell.categoryImageView.image = UIImage(named: "Landscape")
}
if event?.category == "Other" {
cell.categoryImageView.image = UIImage(named: "Dice")
}
if event?.category == "Sports" {
cell.categoryImageView.image = UIImage(named: "Exercise")
}
if event?.category == "Academics" {
cell.categoryImageView.image = UIImage(named: "University")
}
if event?.category == "Science" {
cell.categoryImageView.image = UIImage(named: "Physics")
}
if event?.category == "Entertainment" {
cell.categoryImageView.image = UIImage(named: "Bowling")
}
if event?.category == "Food & Drinks" {
cell.categoryImageView.image = UIImage(named: "Food")
}
if let date = event?.eventDate {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
cell.eventDescriptionLabel.text = event?.eventDescription
cell.eventDateLabel.text = dateFormatter.stringFromDate(date)
}
}
})
cell.layer.cornerRadius = 20
return cell
}
EDITED:
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
usr.fetchIfNeededInBackgroundWithBlock({ (object: PFObject?, error: NSError?) -> Void in
if let picture = object!.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
})
}
}
You need to fetch the usr before you can get picture
usr.fetchIfNeededInBackgroundWithBlock({ (object: PFObject?, error: NSError?) -> Void in
if let picture = object.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
})
I'm working with a collectionView right now and when I activate the refresh control, it adds a duplicate picture to the data source set for every picture in the set, and then makes it disappear and things go back to normal by the time the refresh control is done. Here's a YouTube video I uploaded to clearly show you what is going on.
https://youtu.be/Q9ZFd-7tSRw
It would seem logical that the data source set would be getting the same data from the API I am using, then displaying it, the duplicate data then getting deleting from the array, and then the collection view being reloaded once more before the refresh control goes away. That's not how I want it to work obviously, but perhaps I have coded it wrong.
viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)
self.cellLoadingIndicator.backgroundColor = goldenWordsYellow
self.cellLoadingIndicator.hidesWhenStopped = true
if self.revealViewController() != nil {
revealViewControllerIndicator = 1
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.revealViewController().rearViewRevealWidth = 280
collectionView!.delegate = self
collectionView!.dataSource = self
goldenWordsRefreshControl = UIRefreshControl()
goldenWordsRefreshControl.backgroundColor = goldenWordsYellow
goldenWordsRefreshControl.tintColor = UIColor.whiteColor()
self.collectionView!.addSubview(goldenWordsRefreshControl)
navigationController?.setNavigationBarHidden(false, animated: true)
navigationItem.title = "Pictures"
setupView()
populatePhotos()
self.dateFormatter.dateFormat = "dd/MM/yy"
self.cellLoadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
self.cellLoadingIndicator.color = goldenWordsYellow
self.cellLoadingIndicator.center = (self.collectionView?.center)!
self.collectionView!.addSubview(cellLoadingIndicator)
self.collectionView!.bringSubviewToFront(cellLoadingIndicator)
/*
self.dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
self.dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
let currentDateAndTime = NSDate()
let updateString = "Last updated at " + self.dateFormatter.stringFromDate(currentDateAndTime)
self.goldenWordsRefreshControl.attributedTitle = NSAttributedString(string: updateString)
*/
}
populatePhotos:
func populatePhotos() {
if populatingPhotos {
return
}
populatingPhotos = true
self.cellLoadingIndicator.startAnimating()
self.temporaryPictureObjects.removeAllObjects()
Alamofire.request(GWNetworking.Router.Pictures(self.currentPage)).responseJSON() { response in
if let JSON = response.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)) {
var nodeIDArray : [Int]
if (JSON .isKindOfClass(NSDictionary)) {
for node in JSON as! Dictionary<String, AnyObject> {
let nodeIDValue = node.0
var lastItem : Int = 0
self.nodeIDArray.addObject(nodeIDValue)
if let pictureElement : PictureElement = PictureElement(title: "Picture", nodeID: 0, timeStamp: 0, imageURL: "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png", author: "Staff", issueNumber: "Issue # error", volumeNumber: "Volume # error") {
pictureElement.title = node.1["title"] as! String
pictureElement.nodeID = Int(nodeIDValue)!
let timeStampString = node.1["revision_timestamp"] as! String
pictureElement.timeStamp = Int(timeStampString)!
if let imageURL = node.1["image_url"] as? String {
pictureElement.imageURL = imageURL
}
if let author = node.1["author"] as? String {
pictureElement.author = author
}
if let issueNumber = node.1["issue_int"] as? String {
pictureElement.issueNumber = issueNumber
}
if let volumeNumber = node.1["volume_int"] as? String {
pictureElement.volumeNumber = volumeNumber
}
lastItem = self.temporaryPictureObjects.count // Using a temporary set to not handle the dataSource set directly (safer).
self.temporaryPictureObjects.addObject(pictureElement)
let indexPaths = (lastItem..<self.temporaryPictureObjects.count).map { NSIndexPath(forItem: $0, inSection: 0) }
}
}
/* Sorting the elements in order of newest to oldest (as the array index increases] */
let timeStampSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
self.pictureObjects.sortUsingDescriptors([timeStampSortDescriptor])
}
dispatch_async(dispatch_get_main_queue()) {
self.pictureObjects = self.temporaryPictureObjects
self.collectionView!.reloadData()
self.cellLoadingIndicator.stopAnimating()
self.currentPage++
self.populatingPhotos = false
}
}
}
}
}
handleRefresh:
func handleRefresh() {
goldenWordsRefreshControl.beginRefreshing()
self.pictureObjects.removeAllObjects()
self.currentPage = 0
self.cellLoadingIndicator.startAnimating()
self.picturesCollectionView.bringSubviewToFront(cellLoadingIndicator)
self.populatingPhotos = false
populatePhotos()
self.cellLoadingIndicator.stopAnimating()
goldenWordsRefreshControl.endRefreshing()
}
cellForItemAtIndexPath:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoBrowserCellIdentifier, forIndexPath: indexPath) as! PhotoBrowserCollectionViewCell
if let pictureObject = pictureObjects.objectAtIndex(indexPath.row) as? PictureElement {
let title = pictureObject.title ?? "" // if pictureObject.title == nil, then we return an empty string
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(pictureObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = pictureObject.author ?? ""
let issueNumber = pictureObject.issueNumber ?? ""
let volumeNumber = pictureObject.volumeNumber ?? ""
let nodeID = pictureObject.nodeID ?? 0
let imageURL = pictureObject.imageURL ?? "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png"
cell.request?.cancel()
if let image = self.imageCache.objectForKey(imageURL) as? UIImage {
cell.imageView.image = image
} else {
cell.imageView.image = nil
cell.request = Alamofire.request(.GET, imageURL).responseImage() { response in
if let image = response.result.value {
self.imageCache.setObject(response.result.value!, forKey: imageURL)
if cell.imageView.image == nil {
cell.imageView.image = image
}
}
}
}
}
return cell
}