I am making an app that takes inputs from textFields in an alertController, then stored into CoreData and eventually be displayed in a tableView.
The plan for now is to create a string to create a CSV by combining the textField.text together, something like
let string CSV = textField.text + " ," + textField2.text + " ," + ...
However, when I tried to do this, they say that I cannot force unwrap an optional value.
I tried to put a "!" in textField.text, etc but they are all still seen as optional values. The textFields, when employed in the app must always be filled, but I could not find a way to provide an error that forces the user of the app to fill in a value.
Here is my ViewController:
import UIKit
import CoreData
class ViewController: UITableViewController {
var alarmItems: [NSManagedObject] = []
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
navigationController?.navigationBar.barTintColor = UIColor(red: 21/255, green: 101/255, blue: 192/255, alpha: 1)
navigationController?.navigationBar.tintColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add Alarm", style: .plain, target: self, action: #selector(addAlarmItem))
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "AlarmItems")
do {
alarmItems = try managedContext.fetch(fetchRequest)
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
//now to figure out how to add multiple text fields
#objc func addAlarmItem(_ sender: AnyObject) {
print("this works")
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alertController.textFields!.first, let itemToAdd = textField.text else { return }
//guard let textField2 = alertController.textFields?.first, let itemToAdd2 = textField2.text else { return } //tried this to get the input of a second textField
/*
one thing I tried:
let textField1 = alertController.textFields[0]
let textField1String = textField1.text!
let textField2 = alertController.textFields![1]
let textField2String = textField2.text
let itemToAdd = textField1String + textField2String
*/
//var textField1String = textField1.text
//let textField2 = alertController.textFields![1]
//var textField2String = textField2.text
self.save(itemToAdd)
//self.save(itemToAdd2)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
//alertController.addTextField(configurationHandler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "First"
}
alertController.addTextField { (textField) in
textField.placeholder = "Second"
}
//let combinedString = UITextField[0] + " ," + UITextField[1]
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItems", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
alarmItems.append(item)
} catch let err as NSError {
print("Failed to save an item", err)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return alarmItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = alarmItems[indexPath.row]
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
}
You can use compactMap to easily convert an array of optionals into an array of non-optionals.
let myStrings: [String] = alert.textfields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ", ")
To learn more about compactMap, head over to https://developer.apple.com/documentation/swift/sequence/2950916-compactmap
One of the ways you can do the error validation is that when save is pressed, do empty checks on the textfields values in a separate function and show an error alert box.
I don't think you can show some kind of error inside your initial textfield alert controller. You have to validated the text separately and then show a separate alert error alert box.
You can use String extension to unwrap text this way:
extension Optional where Wrapped == String{
func safe() -> String{
if self == nil{
return ""
}else{
return self.unsafelyUnwrapped
}
}
Hope this helps.
I am getting some data from server using Alamofire like this :
func getNewestFeed(order:String , page:Int) {
Alamofire.request("https://blahblah.com/api/front/\(page)/\(order)", method: .post, parameters: ["foo":"bar"], encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: { respone in
if respone.response?.statusCode == 200 {
let result = respone.result.value as! [String:Any]
self.newestArray = result["records"] as! [Any]
self.tableView.reloadData()
} else {
//Show error
let alertController = UIAlertController(title: "Error", message: "", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
OperationQueue.main.addOperation { self.present(alertController, animated: true, completion: nil) }
}
})
}
by default server gives me page 1, now I need to add more data too self.newestArray to load more contents. So here is the code :
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let lastElement = newestArray.count - 1
if indexPath.row == lastElement {
//add more data
}
}
Now I am trying to add result to self.newestArray , like this :
let result = respone.result.value as! [String:Any]
self.newestArray.append(result["records"] as! [Any])
self.tableView.reloadData()
but crashes with this error :
Could not cast value of type 'Swift.Array' (0x109c3c828) to
'Swift.Dictionary' (0x109c3c798).
How should I addd more array to self.newestArray and show it again in table view ?
append(_:) is used to add a single element to the end of the array.
There is append(contentsOf:) if you want to add a collection of items:
self.newestArray.append(contentsOf: result["records"] as! [Any])
So I am really new to threading and I've been reading up on it all day. For some reason though the data isn't loading before other code executes
Basically I need all the values that have a key ["whatever"] to be filled into an array, which works in other places because I don't need to load it first. So i have checked and double checked the keys that I am updating do exist and the keys I am extracting do exist maybe not the values yet but the keys do.
The problem is the code goes to fast to through the method. How would I make the main thread wait untill my firebase has loaded the data I have tried it below but it does not seem to be working
here is my code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert)
let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in
print("Ok button tapped")
})
let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
// let them know to wait a second or the bet won't go through
var waitController = UIAlertController(title: "Please Wait", message: "You must wait for the bet to go through", preferredStyle: .alert)
self.present(waitController, animated: true, completion: nil)
//take away that bitches money
self.takeAwayMoney(self.amountBets[indexPath.row], completion: { (result: Bool?) in
guard let boolResult = result else {
return
}
if boolResult == true {
self.updateBet(indexPath.row, completion: {(result: String?) in
guard let resultRecieved = result else {
return
}
print(self.opposingUserNames)
//let delayInSeconds = 7.0 // 1
//DispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) { // 2
self.dismiss(animated: true, completion: nil)
let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames!, preferredStyle: .alert)
let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil)
successController.addAction(okButt)
self.present(successController, animated: true, completion: nil)
//lastly delete the opposing UserName
print(self.opposingUserNames)
self.amountBets.remove(at: indexPath.row)
self.tableView.reloadData()
print("Second")
print(self.opposingUserNames)
//}
})
} else {
return
}
})
//then delete that cell and do another pop up that says successful
// check if value is yes or no in the database
})
alertController.addAction(okButton)
alertController.addAction(yesButton)
present(alertController, animated: true, completion: nil)
}
The below function updates the values OpposingUsername and show
func updateBet(_ index: Int, completion: #escaping (_ something: String?) -> Void) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
let values = ["OpposingUsername": self.userName,"Show": "no"]
self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values)
// now get the opposing username which is just the Username registered to that specific bet
self.datRef.child("Bets").child(self.tieBetToUser[index]).observe(.childAdded, with: { snapshot in
guard let dict2 = snapshot.value as? [String: AnyHashable] else {
return
}
let userNameOfOtherPlayer = dict2["Username"] as? String
self.opposingUserNames = userNameOfOtherPlayer!
completion(self.opposingUserNames)
})
})
}) { (error) in
print(error.localizedDescription)
}
}
ok so with this updated code it cuts out the logic errors I had earlier, but now the app hangs on my waitAlertViewController. Not sure why. it does updated the bet in the firebase database so I know its working and running that code but its like never completing it all. sorry bibscy I see what you mean now
completion handlers are pretty powerful once you understand them better
//Notice that I made `result: String?` optional, it may or may not have a value.
func getOpoosingUserNames(_ username: String,_ index: Int, completion: #escaping (_ result: String?) -> Void ) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let username = value?["username"] as? String ?? ""
self.userName = username
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
let betId = snapshot.key as String
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
if let show = dict["Show"] as? String {
let opposingUser = dict["OpposingUsername"] as? String
self.opposingUserNames.append(opposingUser!)
}
completion(opposingUserNames)
})
}) { (error) in
print(error.localizedDescription)
}
}
//update the be
func updateBet(_ index: Int, completion: #escaping (_ something: [String]?) -> Void) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
let values = ["OpposingUsername": self.userName,"Show": "no"]
//store the values received from Firebase in let valueOfUpdate and pass this
// constant to your completion handler completion(valueOfUpdate) so that you can use this value in func
//tableView(_ tableView:_, didSelectRowAt indexPath:_)
let valueOfUpdate = self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values)
completion(valueOfUpdate)
}) { (error) in
print(error.localizedDescription)
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert)
let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in
print("Ok button tapped")
})
let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
//take away that bitches money
self.takeAwayMoney(self.amountBets[indexPath.row])
//then delete that cell and do another pop up that says successful
// check if value is yes or no in the database
self.updateBet(indexPath.row, completion: {(result: String) in
guard let resultReceivedInupdateBet = result, else {
print("result of updateBet() is \(result)")
}
print("If you see this print, database was updated")
//calling this method with the indexPath.row clicked by the user
self.getOpoosingUserNames(self.userName, indexPath.row, completion: { (result: [String]) in
guard let resultReceivedIngetOpoosingUserNames = result{
print("result of getOpoosingUserNames is \(result)")
}
print("If you see this print, you received a value from db after calling getOpoosingUserNames and that value is in \(result) ")
//result is not nil, resultReceivedIngetOpoosingUserNames has the same value as result.
}//end of self.getOpoosingUserNames
self.checkForNo(indexPath.row)
self.amountBets.remove(at: indexPath.row)
self.tableView.reloadData()
print(self.opposingUserNames)
let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames[indexPath.row], preferredStyle: .alert)
let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil)
successController.addAction(okButt)
self.present(successController, animated: true, completion: nil)
//lastly delete the opposing UserName
self.opposingUserNames.remove(at: indexPath.row)
})
alertController.addAction(okButton)
alertController.addAction(yesButton)
present(alertController, animated: true, completion: nil)
}
How can i upload a row in Parse.com?
This is my query code:
func queryFromParse(){
self.arrayOfDetails.removeAll()
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 deviceID = oneobject["identifierForVendor"] as! String
let reportedCount = oneobject["reportedCount"] as! String
let time = oneobject.createdAt!
if let userImage = oneobject["imageFile"] as? PFFile {
let userImage = oneobject["imageFile"] as! PFFile
let imageURL = userImage.url // <- Bruker nå userImage.URL, henter ikke bildefilen med en gang
let OneBigObject = Details(username: username, text: text, CreatedAt: time, image: imageURL!, deviceID: deviceID, reportedCount: reportedCount)
//let OneBigObject = Details(username: username, text: text, CreatedAt: time, image: imageURL!)
self.arrayOfDetails.append(OneBigObject)
dispatch_async(dispatch_get_main_queue()) { self.collectionView.reloadData() }
}
}
}
}
}
}
Image here
I want to update the "reportedCount" when the image is reported. I have a code that i have been using, but that created new rows in another class for each report, and I want only to update the "reportedCount":
#IBAction func reportContentAction(sender: AnyObject) {
let buttonPosition = sender.convertPoint(CGPointZero, toView: self.collectionView)
let indexPath = self.collectionView.indexPathForItemAtPoint(buttonPosition)
////
println(indexPath?.item)
////
let post = self.arrayOfDetails[indexPath!.item]
var alertMessage = NSString(format:"*User: %#\r *Text: %#\r *Created at %#", post.username, post.text, post.CreatedAt)
var reportAlert = UIAlertController(title: "Report Content", message:alertMessage as String, preferredStyle: UIAlertControllerStyle.Alert)
reportAlert.addAction(UIAlertAction(title: "Yes", style: .Default, handler: { (action: UIAlertAction!) in
println("Handle Report Logic here")
var currentUploads = PFObject(className: "banned")
currentUploads["username"] = post.username
currentUploads["imageText"] = post.text
currentUploads["imageFile"] = post.image
currentUploads["identifierForVendor"] = post.deviceID
currentUploads["flaggedBy"] = PFUser.currentUser()?.username
currentUploads["flaggedByUUID"] = UIDevice.currentDevice().identifierForVendor.UUIDString
currentUploads.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if error == nil{
//**Success saving, now save image.**//
currentUploads.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if error == nil{
// Take user home
print("Data uploaded")
// Show UIAlertView
let alert = UIAlertView()
alert.title = "Message"
alert.message = "You report has been sent. Thank you for your support."
alert.addButtonWithTitle("Close")
alert.show()
}
else{
print(error)
}
})
}
else{
print(error)
}
})
}))
reportAlert.addAction(UIAlertAction(title: "Cancel", style: .Default, handler: { (action: UIAlertAction!) in
println("Handle Cancel Logic here")
}))
presentViewController(reportAlert, animated: true, completion: nil)
}
You should be keeping a reference to oneobject, or more broadly, all of the objects returned from the query. Now when something changes you can get the appropriate instance from the objects array and then update and save it to modify the existing 'row'.
When the cells first appear,they will look like my picture shows.If scroll top then scroll down let them show again,they will be normal.The top three cells is always being normal while the bottom are narrowed.This is my code`
import UIKit
class AllCommentsViewController: UIViewController {
#IBAction func unwindToAllComments(sender: UIStoryboardSegue){
if sender.identifier == "unwindToAllComments"{
}
}
override func awakeFromNib() {
let photo = ZLLPhoto(withoutDataWithObjectId: "55cd717700b0875fb6cc125f")
photo.fetch()
self.photo = photo
}
var photo: ZLLPhoto!
var comments = [ZLLComment]()
#IBAction func commentButtonClicked(sender: UIButton){
performSegueWithIdentifier("comment", sender: nil)
}
private func initialCommentsQuery() -> AVQuery {
let query = ZLLComment.query()
query.whereKey("photo", equalTo: photo)
query.limit = 20
query.orderByDescending("likeCount")
query.addDescendingOrder("createdAt")
query.includeKey("score")
query.includeKey("author")
return query
}
func getFirst(){
initialCommentsQuery().findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0 {
let comments = objects as! [ZLLComment]
self.comments = comments
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
var indexPath = NSIndexPath(forRow: i, inSection: 2)
indexPaths.append(indexPath)
}
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .None)
self.tableView.endUpdates()
self.tableView.footer.endRefreshing()
self.tableView.footer = MJRefreshAutoNormalFooter(refreshingTarget: self, refreshingAction: "loadMore")
self.tableView.header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: "refresh")
}
}else{
print(error)
}
self.tableView.footer.endRefreshing()
}
}
func loadMore(){
let last = comments.last!
let query = initialCommentsQuery()
query.whereKey("likeCount", lessThanOrEqualTo: last.likeCount)
query.whereKey("createdAt", lessThan: last.createdAt)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0{
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
let indexPath = NSIndexPath(forRow: self.comments.count + i, inSection: 2)
indexPaths.append(indexPath)
}
let comments = objects as! [ZLLComment]
self.comments.extend(comments)
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .None)
self.tableView.endUpdates()
}
}else{
print(error)
}
self.tableView.footer.endRefreshing()
}
}
func refresh(){
let first = comments.first!
let query = initialCommentsQuery()
query.whereKey("likeCount", greaterThanOrEqualTo: first.likeCount)
query.whereKey("createdAt", greaterThan: first.createdAt)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0 {
var comments = objects as! [ZLLComment]
comments.extend(self.comments)
self.comments = comments
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
var indexPath = NSIndexPath(forRow: i, inSection: 2)
indexPaths.append(indexPath)
}
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths,
withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
}
}else{
print(error)
}
self.tableView.header.endRefreshing()
}
}
#IBOutlet weak var commentButton: UIButton!
#IBOutlet weak var photoTitle: UILabel!{
didSet{
photoTitle.text = photo.title
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "comment" {
let VC = segue.destinationViewController as! CommentPhotoViewController
VC.photo = photo
}else if segue.identifier == "showUser"{
let VC = segue.destinationViewController as! UserInfoTableViewController
VC.user = sender as! ZLLUser
}
}
#IBAction func likeButtonClicked(sender: UIButton) {
let indexPath = tableView.indexPathForCellContainingView(sender)!
let comment = comments[indexPath.row]
let I = ZLLUser.currentUser()
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CommentCell
if !cell.liked{
I.likeComment(comment, completion: { (error) -> Void in
if error == nil {
comment.incrementKey("likeCount")
cell.likeCount += 1
cell.liked = true
}else{
print(error)
}
})
}else{
I.unlikeComment(comment, completion: { (error) -> Void in
if error == nil{
comment.incrementKey("likeCount", byAmount: -1)
cell.likeCount -= 1
cell.liked = false
}else{
print(error)
}
})
}
}
//XIBload
#IBOutlet weak var tableView: UITableView!
#IBOutlet var titleScoreLabel: UILabel?
#IBOutlet var titleLabel: UILabel?
#IBOutlet var photoCell: UITableViewCell!
override func viewDidLoad() {
NSBundle.mainBundle().loadNibNamed("PhotoCell", owner: self, options: nil)
tableView.footer = MJRefreshAutoNormalFooter(refreshingTarget: self, refreshingAction: "getFirst")
let query = ZLLScore.query()
query.whereKey("photo", equalTo: photo)
query.whereKey("scorer", equalTo: ZLLUser.currentUser())
query.countObjectsInBackgroundWithBlock { (count, error) -> Void in
if error == nil {
if count > 0{
self.commentButton.setImage(UIImage(named: "comments_add_comment")!, forState: UIControlState.Normal)
}
}else{
print(error)
}
}
}
}
extension AllCommentsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("photoCell") as! PhotoCell
cell.loadPhoto2(photo)
return cell
case 1:
tableView
let cell = tableView.dequeueReusableCellWithIdentifier("commentCell", forIndexPath: indexPath) as! CommentCell
cell.loadPhotoInfo(photo)
return cell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("commentCell", forIndexPath: indexPath) as! CommentCell
if indexPath.row == 0{
cell.smallTagImage.image = UIImage(named: "jian")
return cell
}
cell.delegate = self
cell.loadComment(comments[indexPath.row])
return cell
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section{
case 2:
return comments.count
default:
return 1
}
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 1
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
switch section{
case 0:
return 1
default:
return 10
}
}
}
extension AllCommentsViewController: PhotoCellDelegate{
func photoCellDidTapUserField(photoCell: PhotoCell) {
}
func photoCellDidClickShareButton(photoCell: PhotoCell) {
//
let indexPath = tableView.indexPathForCell(photoCell)!
let share = UIAlertController(title: "分享图片", message: "\(photo.title)", preferredStyle: UIAlertControllerStyle.ActionSheet)
let weibo = UIAlertAction(title: "微博", style: UIAlertActionStyle.Default) { (action) -> Void in
if !WeiboSDK.isWeiboAppInstalled(){
ZLLViewModel.showHintWithTitle("未安装微博应用", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeSinaWeibo){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeSinaWeibo, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeSinaWeibo, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeSinaWeibo, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let qZone = UIAlertAction(title: "qq空间", style: UIAlertActionStyle.Default) { (action) -> Void in
//
if !QQApiInterface.isQQInstalled(){
ZLLViewModel.showHintWithTitle("未安装腾讯QQ", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeQQSpace){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeQQSpace, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQSpace, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = UIImage(data: self.photo.imageFile.getData())
let data = UIImageJPEGRepresentation(image, 0.1)
let attachment = ShareSDK.imageWithData(data, fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: attachment, title: "c", url: "www.baidu.com", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQSpace, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let weixin = UIAlertAction(title: "微信好友", style: UIAlertActionStyle.Default) { (action) -> Void in
if !QQApiInterface.isQQInstalled(){
ZLLViewModel.showHintWithTitle("未安装腾讯QQ", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeQQSpace){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeQQ, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQ, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQ, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let pengyouquan = UIAlertAction(title: "朋友圈", style: UIAlertActionStyle.Default) { (action) -> Void in
}
let cancl = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
share.addAction(weibo)
share.addAction(qZone)
share.addAction(weixin)
share.addAction(pengyouquan)
share.addAction(cancl)
self.presentViewController(share, animated: true, completion: nil)
}
func photoCellDidClickMoreButton(photoCell: PhotoCell) {
let indexPath = tableView.indexPathForCell(photoCell)!
let alertController = UIAlertController(title: "更多", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
let report = UIAlertAction(title: "举报", style: UIAlertActionStyle.Default) { (alertAction) -> Void in
let confirmReport = UIAlertController(title: "确认举报?", message: nil, preferredStyle: UIAlertControllerStyle.Alert)
let delete = UIAlertAction(title: "确认", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let report = ZLLReport.new()
report.reportedPhoto = self.photo
report.reporter = ZLLUser.currentUser()
let success = report.save()
if success{
ZLLViewModel.showHintWithTitle("举报成功", on: self.view)
}else{
ZLLViewModel.showHintWithTitle("举报失败", on: self.view)
}
}
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
confirmReport.addAction(delete)
confirmReport.addAction(cancel)
self.presentViewController(confirmReport, animated: true, completion: nil)
}
alertController.addAction(report)
if photo.owner.objectId == ZLLUser.currentUser().objectId{
let delete = UIAlertAction(title: "删除图片", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let confirmDelete = UIAlertController(title: "确认删除?", message: nil, preferredStyle: UIAlertControllerStyle.Alert)
let delete = UIAlertAction(title: "确认", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let success = self.photo.delete()
self.photo.deleteInBackgroundWithBlock({ (success, error) -> Void in
if success{
self.performSegueWithIdentifier("deleteComplete", sender: nil)
ZLLViewModel.showHintWithTitle("删除成功", on: self.view)
self.myPopBackButtonClicked(nil)
}else{
print(error)
}
})
}
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
confirmDelete.addAction(delete)
confirmDelete.addAction(cancel)
self.presentViewController(confirmDelete, animated: true, completion: nil)
}
alertController.addAction(delete)
}
let cancelAction = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
extension AllCommentsViewController: CommentCellProtocol{
func commentCellDidTapAuthorLabel(cell: CommentCell) {
let indexPath = tableView.indexPathForCell(cell)!
let comment = comments[indexPath.row]
let user = comment.author
performSegueWithIdentifier("showUser", sender: user)
}
}`
In Your PhotoCell class, add this snippet code.
override func didMoveToSuperview() {
layoutIfNeeded()
}
Your problem is in the section where you define your tableView.
In your tableView extension, you set the numberOfSectionsInTableView method to return 3 rows, so your code defining the cell dimensions only runs on the first 3 rows.
Try setting your numberOfSections method to the number of rows you want based on the dimensions of your view, it looks to be about 5.