Make two different buttons create two different email subjects - ios

I'm trying to get the two different buttons I have shown with if indexPath.section == 1 && indexPath.row == 0 and if indexPath.section == 1 && indexPath.row == 1 to have different subjects when i pull up the email. Both buttons pull up the same subject (Suggestion: ). How would I allow the program to differentiate them?
import UIKit
import Foundation
import MessageUI
class AccountViewController: UITableViewController, MFMailComposeViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.view.backgroundColor = .clear
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1 && indexPath.row == 1{
print("pressed")
let mailComposeViewController2 = configureMailController()
if MFMailComposeViewController.canSendMail() {
self.present(mailComposeViewController2, animated: true, completion: nil)
} else {
showMailError()
}
}
if indexPath.section == 1 && indexPath.row == 0 {
print("pressed")
let mailComposeViewController = configureMailController()
if MFMailComposeViewController.canSendMail() {
self.present(mailComposeViewController, animated: true, completion: nil)
} else {
showMailError()
}
}
}
//if indexPath.section == 1 && indexPath.row == 1 {
//}
func configureMailController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["SolsticeOfficialLLC#gmail.com"])
mailComposerVC.setSubject("Suggestion: ")
return mailComposerVC
}
func configureMailController2() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["SolsticeOfficialLLC#gmail.com"])
mailComposerVC.setSubject("Report: ")
return mailComposerVC
}
func showMailError() {
let sendMailErrorAlert = UIAlertController(title: "Could not send email", message: "Your device could not send email", preferredStyle: .alert)
let dismiss = UIAlertAction(title: "OK", style: .default, handler: nil)
sendMailErrorAlert.addAction(dismiss)
self.present(sendMailErrorAlert, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith: MFMailComposeResult, error: Error?){
controller.dismiss(animated: true, completion: nil)
}
}

You need to add a parameter to help you:
func configureMailController(subject = "Unspecified Subject") -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["SolsticeOfficialLLC#gmail.com"])
mailComposerVC.setSubject(subject)
return mailComposerVC
}
Then, do as you please when configuring:
let mailComposeViewController1 = configureMailController("Specific Subject 1")
....
let mailComposeViewController2 = configureMailController("Specific Subject 2")

Related

How do I display contacts when UITextField is clicked?

I have tried multiple times to create a UITextField that when clicked should show the contacts available on the device and retrieve the phone number and display it in the textfield. However I have been unable to do that. The best that I could do is to use a button to receive and display the number on a textfield. This works! How do I do the same for when the UITextField is clicked?
I'm running it on Xcode 10
private let contactPicker = CNContactPickerViewController()
override func viewDidLoad() {
super.viewDidLoad()
configureTextFields()
configureTapGesture()
phonenumber.textContentType = .telephoneNumber
}
private func configureTextFields() {
phonenumber.delegate = self
}
private func configureTapGesture(){
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SelfTestTimer.handleTap))
viewcontact.addGestureRecognizer(tapGesture)
}
#objc private func handleTap(){
viewcontact.endEditing(true)
}
#IBAction func pbbbbb(_ sender: Any) {
contactPicker.delegate = self
self.present(contactPicker, animated: true, completion: nil)
}
}
extension SelfTestTimer: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
let phoneNumberCount = contact.phoneNumbers.count
guard phoneNumberCount > 0 else {
dismiss(animated: true)
return
}
if phoneNumberCount == 1 {
setNumberFromContact(contactNumber: contact.phoneNumbers[0].value.stringValue)
}else{
let alertController = UIAlertController(title: "Select one of the numbers", message: nil, preferredStyle: .alert)
for i in 0...phoneNumberCount-1 {
let phoneAction = UIAlertAction(title: contact.phoneNumbers[i].value.stringValue, style: .default, handler: {
alert -> Void in
self.setNumberFromContact(contactNumber: contact.phoneNumbers[i].value.stringValue)
})
alertController.addAction(phoneAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: {
alert -> Void in
})
alertController.addAction(cancelAction)
dismiss(animated: true)
self.present(alertController, animated: true, completion: nil)
}
}
func setNumberFromContact(contactNumber: String) {
var contactNumber = contactNumber.replacingOccurrences(of: "-", with: "")
contactNumber = contactNumber.replacingOccurrences(of: "(", with: "")
contactNumber = contactNumber.replacingOccurrences(of: ")", with: "")
guard contactNumber.count >= 10 else {
dismiss(animated: true) {
self.presentAlert(alertTitle: "", alertMessage: "A maximum of 10 contacts allowed per session", lastAction: nil)
}
return
}
phonenumber.text = String(contactNumber.suffix(10))
}
func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
}
}
extension SelfTestTimer: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
I want it so that when the UITextField is clicked, the contacts will appear and when one contact is selected, the number should appear in the textfield
You should use textFieldShouldBeginEditing method. Open the contacts controller in this method and return false, no need to add a gesture recogniser.

provideAPIKey: should be called at most once (Swift)

I'm using Google maps and places API and i'm trying to load nearby places in a tableView but everytime i come in this class
import UIKit
import MapKit
import CoreLocation
import GoogleMaps
import GooglePlaces
import Social
import AVFoundation
private let resueIdentifier = "MyTableViewCell"
extension UIViewController {
func present(viewController : UIViewController, completion : (() -> ())? = nil ){
if let presented = self.presentedViewController {
presented.dismiss(animated: true, completion: {
self.present(viewController, animated: true, completion: completion)
})
} else {
self.present(viewController, animated: true, completion: completion)
}
}
}
class CourseClass2: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
struct User {
var name: String
var images: UIImage
var type: String
}
var previuosViewTappedButtonsArray = [String]()
var locationManager:CLLocationManager?
let minimumSpacing : CGFloat = 15 //CGFloat(MAXFLOAT)
let cellWidth: CGFloat = 250
let radius = 5000 // 5km
var category : QCategoryy?
var currentLocation : CLLocationCoordinate2D?
var places: [QPlace] = []
var isLoading = false
var response : QNearbyPlacesResponse?
var rows = 0
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = category?.name
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
determineMyCurrentLocation()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
rows = 0
insertRowsMode3()
tableView.reloadData()
category?.markView()
}
#IBAction func refreshTapped(_ sender: Any) {
rows = 0
insertRowsMode3()
tableView.reloadData()
}
func canLoadMore() -> Bool {
if isLoading {
return false
}
if let response = self.response {
if (!response.canLoadMore()) {
return false
}
}
return true
}
func loadPlaces(_ force:Bool) {
if !force {
if !canLoadMore() {
return
}
}
print("load more")
isLoading = true
NearbyPlaces.getNearbyPlaces(by: category?.name ?? "food", coordinates: currentLocation!, radius: radius, token: self.response?.nextPageToken, completion: didReceiveResponse)
}
func didReceiveResponse(response:QNearbyPlacesResponse?, error : Error?) -> Void {
if let error = error {
let alertController = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let actionDismiss = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
let actionRetry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
})
alertController.addAction(actionRetry)
alertController.addAction(actionDismiss)
DispatchQueue.main.async {
self.present(viewController: alertController)
}
}
if let response = response {
self.response = response
if response.status == "OK" {
if let placesDownloaded = response.places {
places.append(contentsOf: placesDownloaded)
}
self.tableView?.reloadData()
} else {
let alert = UIAlertController.init(title: "Error", message: response.status, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction.init(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
}))
self.present(viewController: alert)
}
isLoading = false
}
else {
print("response is nil")
}
}
func insertRowsMode2() {
tableView.beginUpdates()
for i in 0..<places.count {
insertRowMode2(ind: i, usr: places[i])
}
tableView.endUpdates()
}
func insertRowMode2(ind:Int,usr:QPlace) {
tableView.beginUpdates()
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
tableView.endUpdates()
}
func insertRowsMode3() {
tableView.beginUpdates()
rows = 0
insertRowMode3(ind: 0)
tableView.endUpdates()
}
func insertRowMode3(ind:Int) {
tableView.beginUpdates()
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
guard ind < places.count-1 else { return }
DispatchQueue.main.asyncAfter(deadline: .now()+0.20) {
self.insertRowMode3(ind: ind+1)
}
tableView.endUpdates()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places.count /* rows */
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
let place = places[indexPath.row]
cell.update(place: place)
if indexPath.row == places.count - 1 {
loadPlaces(false)
}
/* let user = users[indexPath.row]
cell.selectionStyle = .none
cell.myImage.image = user.images
cell.myLabel.text = user.name
cell.myTypeLabel.text = user.type */
return (cell)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
UIView.animate(withDuration: 0.2, animations: {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
})
performSegue(withIdentifier: "goToLast" , sender: users[indexPath.row])
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
places.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
func didReceiveUserLocation(_ userLocation:CLLocation) {
currentLocation = userLocation.coordinate
loadPlaces(true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToLast" && sender is IndexPath {
let dvc = segue.destination as! FinalClass
dvc.index = (sender as! IndexPath).row
dvc.places = places
dvc.userLocation = currentLocation
/* guard let vc = segue.destination as? FinalClass else { return }
let guest = segue.destination as! FinalClass
if let user = sender as? User {
*/
}
}
#IBAction func IndTapped(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func socialShare(_ sender: Any) {
//Alert
let alert = UIAlertController(title: "Share", message: "First share!", preferredStyle: .actionSheet)
//First action
let actionOne = UIAlertAction(title: "Share on Facebook", style: .default) { (action) in
//Checking if user is connected to Facebook
if SLComposeViewController.isAvailable(forServiceType: SLServiceTypeFacebook)
{
let post = SLComposeViewController(forServiceType: SLServiceTypeFacebook)!
post.setInitialText("First")
post.add(UIImage(named: "uround logo.png"))
self.present(post, animated: true, completion: nil)
} else {self.showAlert(service: "Facebook")}
}
let actionThree = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
//Add action to action sheet
alert.addAction(actionOne)
alert.addAction(actionThree)
//Present alert
self.present(alert, animated: true, completion: nil)
}
func showAlert(service:String)
{
let alert = UIAlertController(title: "Error", message: "You are not connected to \(service)", preferredStyle: .alert)
let action = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
extension CourseClass2: CLLocationManagerDelegate {
func determineMyCurrentLocation() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
didReceiveUserLocation(userLocation)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
errorGettingCurrentLocation(error.localizedDescription)
}
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager?.startUpdatingLocation()
//locationManager.startUpdatingHeading()
} else if status == .denied || status == .restricted {
errorGettingCurrentLocation("Location access denied")
}
}
func errorGettingCurrentLocation(_ errorMessage:String) {
let alert = UIAlertController.init(title: "Error", message: errorMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
}
i get the message "error - response status" from this function
func didReceiveResponse(response:QNearbyPlacesResponse?, error : Error?) -> Void {
if let error = error {
let alertController = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let actionDismiss = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
let actionRetry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
})
alertController.addAction(actionRetry)
alertController.addAction(actionDismiss)
DispatchQueue.main.async {
self.present(viewController: alertController)
}
}
if let response = response {
self.response = response
if response.status == "OK" {
if let placesDownloaded = response.places {
places.append(contentsOf: placesDownloaded)
}
self.tableView?.reloadData()
} else {
let alert = UIAlertController.init(title: "Error", message: response.status, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction.init(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
}))
self.present(viewController: alert)
}
isLoading = false
}
else {
print("response is nil")
}
}
so looking in the console i saw this error "((null)) was false: provideAPIKey: should be called at most once" which is perhaps the cause of the problem (even if I'm not sure), i followed the google documentation guide to get the API key for the project, here is my appDelegate where there are my keys (i changed for now the numbers of the key with "My Api key")
import UIKit
import Firebase
import CoreLocation
import GoogleMaps
import GooglePlaces
import FBSDKCoreKit
import GoogleSignIn
import FBSDKShareKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
static let googleMapsApiKey = "MY API Key"
static let googlePlacesAPIKey = "MY API Key"
var window: UIWindow?
var locationManager: CLLocationManager?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
if GMSServices.provideAPIKey("MY API Key") {
print("good provided keys correctly")
}
else {
print("key didn't provided")
}
return true
}
someone can tell if the problem is a wrong use of the api key or if the keys are wrong or maybe the problem is another ?
Look at what you are doing here:
// once
GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
// twice!
if GMSServices.provideAPIKey("MY API Key") {
You are calling provideAPIKey twice!
I know you want to check whether the API key is provided correctly, but the correct way to do this is not to call the method twice. Instead, you should store the return value and check the return value:
// put the return value in "success"
let success = GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
// check "success"
if success {

camera app with collection view

I am very new to XCode and Swift. Hope you guys can give me a hand here. I am having a problem that when I click the camera button, and snap a photo and click "Use Photo", the camera will be dismissed and back to the main page again.
What I actually want :
When I click "Use Photo" the main page should show the image taken just now in thumbnail size in collection view.
Camera Example
The expected output
Here is my code :
import UIKit
import CoreLocation
import Photos
import PhotosUI
import MessageUI
let albumName = "CP"
class SpeakerViewController: UIViewController,
CLLocationManagerDelegate, UIImagePickerControllerDelegate,
UINavigationControllerDelegate, UICollectionViewDataSource,
UICollectionViewDelegate, UICollectionViewDelegateFlowLayout,
MFMailComposeViewControllerDelegate {
#IBOutlet var lblLocation: UILabel!
#IBOutlet var tvNews: UITextView!
#IBOutlet var tapView: UIView!
#IBOutlet var btnAlbum: UIButton!
#IBOutlet var btnCamera: UIButton!
#IBOutlet var btnSend: UIButton!
let locationManager = CLLocationManager()
let geoCoder = CLGeocoder()
var latitude = [String]()
var longitude = [String]()
var tap : UITapGestureRecognizer! = UITapGestureRecognizer()
var assetCollection: PHAssetCollection! = PHAssetCollection()
var photoAsset : PHFetchResult<PHAsset>!
var albumFound : Bool = false
var sendLocation : String = ""
var sendContent : String = ""
var imageArray = [UIImage]()
var isCamera : Bool = false
#IBAction func btnBack(_ sender: AnyObject) {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.deleteAssets(self.photoAsset)
}, completionHandler: {(success, error) in
NSLog("Delete image => %#", (success ? "Success" : "Error"))
self.navigationController?.dismiss(animated: true, completion: nil)
})
}
override func viewDidLoad() {
super.viewDidLoad()
LocalStore.setActiveView("speaker")
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 255/255, green: 237/255, blue: 0/255, alpha: 1.0)
if(locationManager.responds(to: #selector(CLLocationManager.requestAlwaysAuthorization))) {
locationManager.requestAlwaysAuthorization()
}
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
tap = UITapGestureRecognizer(target: self, action: #selector(SpeakerViewController.DismissKeyboard))
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let first_Obj:AnyObject = collection.firstObject{
//found the album
self.albumFound = true
self.assetCollection = first_Obj as! PHAssetCollection
} else {
var albumPlaceholder:PHObjectPlaceholder!
NSLog("\nFolder \"%#\" does not exist\nCreating now...", albumName)
PHPhotoLibrary.shared().performChanges({
let request = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
albumPlaceholder = request.placeholderForCreatedAssetCollection
},
completionHandler: {success, error in
if(success){
print("Successfully created folder")
self.albumFound = true
let collection = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [albumPlaceholder.localIdentifier], options: nil)
self.assetCollection = collection.firstObject as PHAssetCollection!
} else {
print("Error creating folder")
self.albumFound = false
}
})
}
NotificationCenter.default.addObserver(self,
selector: #selector(SpeakerViewController.keyboardShow(_:)),
name: NSNotification.Name.UIKeyboardDidShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(SpeakerViewController.keyboardHide(_:)),
name: NSNotification.Name.UIKeyboardDidHide,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(SpeakerViewController.applicationBecameActive(_:)),
name: NSNotification.Name.UIApplicationDidBecomeActive,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(SpeakerViewController.applicationBecameInactive(_:)),
name: NSNotification.Name.UIApplicationWillResignActive,
object: nil)
}
/* Start listening for iCloud user change notifications */
func applicationBecameActive(_ notification: Notification){
print("did become active notification")
if LocalStore.getPostIdMenu() != "0" {
self.navigationController?.dismiss(animated: true, completion: nil)
LocalStore.setPostIdMenu("0")
}
}
func applicationBecameInactive(_ notification: Notification){
print("did become inactive notification")
LocalStore.setPostIdMenu("0")
}
func keyboardShow(_ notification: Notification) {
print("Keyboard Show")
self.view.addGestureRecognizer(tap)
}
func keyboardHide(_ notification: Notification){
print("Keyboard Hide")
self.view.removeGestureRecognizer(tap)
}
override func viewWillAppear(_ animated: Bool) {
//fetch the photo from the collection
self.navigationController?.hidesBarsOnTap = false
self.photoAsset = PHAsset.fetchAssets(in: self.assetCollection, options: nil)
self.collectionView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
let alertView = UIAlertController(title: "出现错误", message: "无法检索您的位置", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default){ _ in})
self.present(alertView, animated: true, completion: nil)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
latitude.removeAll()
longitude.removeAll()
let currentLocation = locations.last!
print("didUpdateToLocation: \(currentLocation)")
latitude.append(String(format: "%.8f", currentLocation.coordinate.latitude))
longitude.append(String(format: "%.8f", currentLocation.coordinate.longitude))
print("Latitude \(latitude.count), Longtitude \(longitude.count)")
geoCoder.reverseGeocodeLocation(currentLocation, completionHandler: {(placemarks, error) -> Void in
if(error == nil && placemarks!.count > 0 ) {
let placeMark = placemarks![0] as CLPlacemark
if (placeMark.addressDictionary?["Thoroughfare"] as? String) != nil {
self.lblLocation.text = "\(placeMark.thoroughfare!), \(placeMark.postalCode!), \(placeMark.administrativeArea!)"
print("Location \(placeMark.locality!)\(placeMark.country!)")
self.locationManager.stopUpdatingLocation()
self.sendLocation = self.lblLocation.text!
} else {
print("thoroughfare not found, reupdate coordinate")
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.startUpdatingLocation()
}
} else {
NSLog("%#", error.debugDescription)
}
})
}
func DismissKeyboard() {
view.endEditing(true)
}
#IBOutlet var collectionView: UICollectionView!
#IBAction func btnAlbum(_ sender: AnyObject) {
isCamera = false
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.savedPhotosAlbum)) {
let imagePicker : UIImagePickerController = UIImagePickerController()
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
imagePicker.delegate = self
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
#IBAction func btnCamera(_ sender: AnyObject) {
isCamera = true
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)) {
let imagePicker : UIImagePickerController = UIImagePickerController()
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.delegate = self
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
} else {
let alert = UIAlertController(title: "出现错误", message: "您的手机没有相机", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
}
#IBAction func btnSend(_ sender: AnyObject) {
var count : Int = 0
if(self.photoAsset != nil) {
count = self.photoAsset.count
}
if (tvNews.text != "" && count > 0) {
sendContent = tvNews.text
if (MFMailComposeViewController.canSendMail()) {
let emailTitle = "App"
let messageBody = "位置: \(sendLocation) \n\n \(sendContent) \n\n "
let toReceipients = ["test#com"]
let mc : MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(emailTitle)
mc.setMessageBody(messageBody, isHTML: false)
mc.setToRecipients(toReceipients)
}
for image in self.imageArray {
let photoData : Data = UIImagePNGRepresentation(image)!
mc.addAttachmentData(photoData, mimeType: "image/png", fileName: "CP.png")
}
self.present(mc, animated: true, completion: nil)
} else {
print("No email account found")
}
} else {
let alertView = UIAlertController(title: "出现错误", message: "没有内容或照片", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alertView.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
var count : Int = 0
if(self.photoAsset != nil) {
count = self.photoAsset.count
}
return count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: PhotoCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCollectionViewCell
let asset : PHAsset = self.photoAsset[(indexPath as NSIndexPath).item] as PHAsset
PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFill, options: nil, resultHandler: {(result, info) in
if let image = result {
cell.setThumbnailImage(image)
self.imageArray.append(image)
}
})
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "viewLargePhoto") {
if let controller:ViewPhotoViewController = segue.destination as? ViewPhotoViewController {
if let cell = sender as? UICollectionViewCell {
if let indexPath: IndexPath = self.collectionView.indexPath(for: cell) {
controller.index = (indexPath as NSIndexPath).item
controller.photoAsset = self.photoAsset
controller.assetCollection = self.assetCollection
}
}
}
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 4
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if(isCamera) {
let image = info["UIImagePickerControllerOriginalImage"] as! UIImage
PHPhotoLibrary.shared().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceholder = createAssetRequest.placeholderForCreatedAsset
if let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection,
assets: self.photoAsset as PHFetchResult<PHAsset>) {
let enumeration: NSArray = [assetPlaceholder!]
albumChangeRequest.addAssets(enumeration)
}
//CORRECTION Error : App crashes
}, completionHandler: {(success, error) in
NSLog("Adding Image to Library => %#",(success ? "Success" : "Error!"))
//Relocated1
})
//CORRECTION Relocated1
picker.dismiss(animated: true, completion: nil)
} else {
let image = info["UIImagePickerControllerOriginalImage"] as! UIImage
PHPhotoLibrary.shared().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceholder = createAssetRequest.placeholderForCreatedAsset
if let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection,
assets: self.photoAsset as PHFetchResult<PHAsset>) {
let enumeration: NSArray = [assetPlaceholder!]
albumChangeRequest.addAssets(enumeration)
}
}, completionHandler: {(success, error) in
NSLog("Adding Image to Library => %#",(success ? "Success" : "Error!"))
picker.dismiss(animated: true, completion: nil)
//self.navigationController?.dismiss(animated: true, completion: nil)
})
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result {
case .cancelled:
let alertView = UIAlertController(title: "取消电邮", message: "您已经取消电邮", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alertView.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
case .saved:
let alertView = UIAlertController(title: "保存电邮", message: "您已经保存电邮", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alertView.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
case .sent:
let alertView = UIAlertController(title: "发送电邮", message: "您已经发送您的电邮", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alertView.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
case .failed:
let alertView = UIAlertController(title: "发送失败", message: "请检查您的电邮设定", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "好的", style: .default, handler: {(alertAction) in
alertView.dismiss(animated: true, completion: nil)
}))
self.present(alertView, animated: true, completion: nil)
//CORRECTION default:
// break
default :
break
}
self.dismiss(animated: false, completion: nil)
}
}
Thanks in advance!

Parsing JSON Tableview Information as Separate Strings

I am currently trying to use information in Tableview cells that I have populated with JSON to execute various operations but I am unable to call the specific information due to the fact that it isn't in individual strings. Is there any way to take the group of data I have pulled into each tableview cell and turn it into a series of individual strings? Here is what I currently have:
import UIKit
import GoogleMobileAds
class OngoingViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var userUsernameLabel: UILabel!
#IBOutlet weak var bannerView: GADBannerView!
#IBOutlet weak var ongoingTable: UITableView!
var list:[MyStruct] = [MyStruct]()
struct MyStruct
{
var user1 = ""
var user2 = ""
var wager = ""
var amount = ""
init(_ user1:String, _ user2:String, _ wager:String, _ amount:String)
{
self.user1 = user1
self.user2 = user2
self.wager = wager
self.amount = amount
}
}
override func viewDidLoad() {
super.viewDidLoad()
let username = UserDefaults.standard.string(forKey: "userUsername")!
userUsernameLabel.text = username
/// The banner view.
print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
ongoingTable.dataSource = self
ongoingTable.delegate = self
get_data("http://cgi.soic.indiana.edu/~team10/ongoingWagers.php")
}
func get_data(_ link:String)
{
let url:URL = URL(string: link)!
var request = URLRequest(url:url);
request.httpMethod = "POST";
let postString = "a=\(userUsernameLabel.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.extract_data(data)
}
task.resume()
}
func extract_data(_ data:Data?)
{
let json:Any?
if(data == nil)
{
return
}
do{
json = try JSONSerialization.jsonObject(with: data!, options: [])
}
catch
{
return
}
guard let data_array = json as? NSArray else
{
return
}
for i in 0 ..< data_array.count
{
if let data_object = data_array[i] as? NSDictionary
{
if let data_user1 = data_object["id"] as? String,
let data_user2 = data_object["id2"] as? String,
let data_wager = data_object["wager"] as? String,
let data_amount = data_object["amount"] as? String
{
list.append(MyStruct(data_user1, data_user2, data_wager, data_amount))
}
}
}
refresh_now()
}
func refresh_now()
{
DispatchQueue.main.async(
execute:
{
self.ongoingTable.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.ongoingTable.dequeueReusableCell(withIdentifier: "owcell", for: indexPath) as! OngoingTableViewCell
cell.infoLabel.text = list[indexPath.row].user1 + " " + list[indexPath.row].user2 + " " + list[indexPath.row].wager + " " + list[indexPath.row].amount
cell.user1Button.tag = indexPath.row
cell.user1Button.addTarget(self, action: #selector(OngoingViewController.user1Action), for: .touchUpInside)
cell.user2Button.tag = indexPath.row
cell.user2Button.addTarget(self, action: #selector(OngoingViewController.user2Action), for: .touchUpInside)
return cell
}
#IBAction func user1Action(sender: UIButton) {
let user1Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user1Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user1ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user1ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user1ConfirmationAlert, animated: true, completion: nil)
}))
user1Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user1Alert, animated: true, completion: nil)
}
#IBAction func user2Action(sender: UIButton) {
let user2Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user2Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user2ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user2ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user2ConfirmationAlert, animated: true, completion: nil)
}))
user2Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user2Alert, animated: true, completion: nil)
}
}
Here is the OngoingTableViewCell subclass:
import UIKit
class OngoingTableViewCell: UITableViewCell {
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var user1Button: UIButton!
#IBOutlet weak var user2Button: 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
}
}
You have an array of MyStruct structures, that contain entries for user1, user1, wager, and amount. That's good.
You're using tags on the buttons as a way of figuring out the selected cell, which is not ideal. Instead I would suggest using the sender parameter to figure out the indexPath of the cell that contains the button. See the bottom of my answer for the details of a better way to do it.
In any case, once you have a row number, you can easily get to the data for that wager by indexing into your array:
#IBAction func user1Action(sender: UIButton) {
selectedRow = sender.tag
//or, using my function:
selectedRow = tableView.indexPathForView(sender)
//Get the wager for the button the user tapped on.
let thisWager = list[selectedRow]
}
If you want to take action on the wager once the user taps a button in your UIAlertController, don't use a nil handler on the your second alert controller. Instead, pass in a closure that uses the selectedRow parameter from the code above to index into the list of wagers, or even use the thisWager local variable I show in my code.
Getting the indexPath of the button the user taps on:
I created a simple extension to UITableView that lets you pass in a UIView (like the sender from a button action) and get back the indexPath that contains that view.
That extension is dirt-simple. Here's how it looks:
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
And you can call that function from your button's actions:
#IBAction func buttonTapped(_ button: UIButton) {
if let indexPath = self.tableView.indexPathForView(button) {
print("Button tapped at indexPath \(indexPath)")
}
else {
print("Button indexPath not found")
}
}
The whole project can be found on Github at this link: TableViewExtension

MFMailComposeViewController not called

I am trying to implement MFMailComposeViewController() in two cells (Subject "feedback"and "feedback2").
When I select each cell, "feedback" works well, but "feedback2" is not called.
It seems not difficult issue but I find it difficult to fix the problem.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if indexPath.row == 0 {
let message = "hey download this app"
let shareView = UIActivityViewController(activityItems: [message], applicationActivities: nil)
self.present(shareView, animated: true, completion: nil)
} else if indexPath.row == 1 {
let mailCompose = MFMailComposeViewController()
mailCompose.mailComposeDelegate = self
mailCompose.setToRecipients(["gmail.com"])
mailCompose.setSubject("feedback")
mailCompose.setMessageBody("text", isHTML: false)
if MFMailComposeViewController.canSendMail()
{
self.present(mailCompose, animated: true, completion: nil)
} else if indexPath.row == 2 {
let mailCompose = MFMailComposeViewController()
mailCompose.mailComposeDelegate = self
mailCompose.setToRecipients(["ba#mail.com"])
mailCompose.setSubject("feedback2")
mailCompose.setMessageBody("text", isHTML: false)
if MFMailComposeViewController.canSendMail()
{
self.present(mailCompose, animated: true, completion: nil)
}
else{
print("error...!")
}
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
Your else if indexPath.row == 2 is indented one level too deeply – its else refers to !MFMailComposeViewController.canSendMail(), not the previous indexPath check. You'll need to shift that branch outwards one level to get the effect you want.
For the future, it might be easier to debug if you refactor out a single method for all your mail-composing:
private func sendMail(to recipient: String, subject: String) {
if !MFMailComposeViewController.canSendMail() {
return
}
let mailCompose = MFMailComposeViewController()
mailCompose.mailComposeDelegate = self
mailCompose.setToRecipients([recipient])
mailCompose.setSubject(subject)
mailCompose.setMessageBody("text", isHTML: false)
self.present(mailCompose, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.row {
case 0: /* activity view controller stuff */ break;
case 1:
sendMail(to: "gmail.com", subject: "feedback")
break;
case 2:
sendMail(to: "ba#mail.com", subject: "feedback2")
break;
}
}

Resources