I want my swift code to copy the object which is a brown view. So the user hits the copy button then the user hits the object they want to copy and then they point to the area where they want to place the object. Basically the gif below is exactly what I am look at I don't know if you would do something like a clone of something like this.
import UIKit;import CoreData
class ViewController: UIViewController {
var addBoxes = [UIImageView]()
let subview = UIImageView()
var currentView: UIView?
var box = UIButton()
var copyButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[box,copyButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
box.backgroundColor = .red
box.setTitle("Add", for: .normal)
copyButton.setTitle("Copy", for: .normal)
NSLayoutConstraint.activate([
box.leadingAnchor.constraint(equalTo: copyButton.trailingAnchor),
box.bottomAnchor.constraint(equalTo: view.bottomAnchor),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
box.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
copyButton.leadingAnchor.constraint(equalTo: view.leadingAnchor),
copyButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
copyButton.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
copyButton.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
])
copy.addTarget(self, action: #selector(copyBox), for: .touchDown)
box.addTarget(self, action: #selector(addQuarter), for: .touchDown)
copyButton.backgroundColor = .blue
}
override var prefersStatusBarHidden: Bool {
return true
}
#objc func copyBox() {
}
#objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
#objc func addQuarter(){
let subview = UIImageView()
subview.isUserInteractionEnabled = true
addBoxes.append(subview)
view.addSubview(subview)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
subview.addGestureRecognizer(pan)
subview.frame = CGRect(x: view.bounds.midX , y: view.bounds.midY + CGFloat(100), width: CGFloat(100), height: 100)
subview.backgroundColor = .brown
addBoxes.append(subview)
}
}
Achieve your requirement with code
class ViewController: UIViewController {
var addBoxes = [UIImageView]()
let subview = UIImageView()
var currentView: UIView?
var location: CGPoint = CGPoint.zero
var box = UIButton()
var copyButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[box,copyButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
box.backgroundColor = .red
box.setTitle("Add", for: .normal)
copyButton.setTitle("Copy", for: .normal)
NSLayoutConstraint.activate([
box.leadingAnchor.constraint(equalTo: copyButton.trailingAnchor),
box.bottomAnchor.constraint(equalTo: view.bottomAnchor),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
box.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
copyButton.leadingAnchor.constraint(equalTo: view.leadingAnchor),
copyButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
copyButton.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
copyButton.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
])
copyButton.addTarget(self, action: #selector(copyBox), for: .touchDown)
box.addTarget(self, action: #selector(addQuarter), for: .touchDown)
copyButton.backgroundColor = .blue
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:))))
}
override var prefersStatusBarHidden: Bool {
return true
}
#objc func copyBox() {
if let copyObject = currentView?.copyView as? UIImageView{
copyObject.center = location
copyObject.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:))))
view.addSubview(copyObject)
}
}
#objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
#objc func handleTapGestured(_ gesture: UITapGestureRecognizer) {
if self.view == gesture.view{
let loc = gesture.location(in: self.view)
location = loc
}
}
#objc func addQuarter(){
let subview = UIImageView()
subview.isUserInteractionEnabled = true
addBoxes.append(subview)
view.addSubview(subview)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
subview.addGestureRecognizer(pan)
subview.frame = CGRect(x: view.bounds.midX , y: view.bounds.midY + CGFloat(100), width: CGFloat(100), height: 100)
subview.backgroundColor = .brown
addBoxes.append(subview)
}
}
extension UIView{
var copyView : UIView?{
if let archiv = try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false){
if let view = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archiv) as? UIView{
return view
}
}
return nil
}
}
a way to achieve copy.
You can do it in the Model level.
In your case, to copy View, is to get the View property ( Frame Size, Color ),
then create a new one.
here is the code instruction
model part
// you can add info , in your needs
struct ViewModel{
let color: UIColor
let size: CGSize
}
Logic Part:
add an UITapGestureRecognizer to the base view (add part view)
in copy mode, the view isUserInteractionEnabled false,
in add mode, the view isUserInteractionEnabled true,
var selectModel: ViewModel?
#objc func copyBox() {
// now in the copy mode
}
func selectView(){
// get current model
selectModel = ViewModel(color: yourView.backgroundColor, size: yourView.frame.size)
}
#objc func AddBox() {
// now in the add mode / paste mode
}
func touchToAdd(_ gesture: UITapGestureRecognizer){
// get the tap location,
// the location point is the new view's center
// use the model from `func selectView(){`
// now you got center . frame size 、color, enough to create a new one ( a copy)
}
Related
var images : [UIImage?] = [nil, nil, nil, nil, nil]
I have image array. I want to replace nil to image by button sender.tag
#IBAction func addImage(_ sender: UIButton) {
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 1
configuration.filter = .any(of: [.images])
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
If array[index] is nil, show + image.
But array[index] is a photo, show photo
extension EditViewController: PHPickerViewControllerDelegate {
#available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
let itemProvider = results.first?.itemProvider
if let itemProvider = itemProvider,
itemProvider.canLoadObject(ofClass: UIImage.self) {
itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
if let image = object as? UIImage {
DispatchQueue.main.async {
print("image: \(image)")
print("IMAGES ARRAY : \(self.images)")
}
}
}
} else {
//
}
}
}
This code is PHPicerViewControllerDelegate (https://ikyle.me/blog/2020/phpickerviewcontroller)
you can do this with following method
assign tags to your UIButtons and on UIButton action add your image on specific index of array by managing an object
e.g
var selectedIndex or selectedTag // of your UIButton
on Button click update your selectedIndex value with
self.selectedIndex = sender.tag
then in your didFinishPicking method update your images array with selected image on selectedIndex and update your buttons images with following way
images.insert(yourSelectedImage, at: selectedIndex)
self.setImagesForButtons()
now assign your selected image to UIButton using UIButton Outlet
e.g you have five outlets for your five buttons
#IBOutlet weak var yourButtonOutlet1: UIButton!
#IBOutlet weak var yourButtonOutlet2: UIButton!
#IBOutlet weak var yourButtonOutlet3: UIButton!
#IBOutlet weak var yourButtonOutlet4: UIButton!
#IBOutlet weak var yourButtonOutlet5: UIButton!
func setImagesForButtons()
{
if (self.selectedIndex == 0)
{
if (images[selectedIndex] != nil)
{
self.yourButtonOutlet1.setImage(images[selectedIndex], for: .normal)
}
else
{
// set plus icon image to your button
}
}
else if (self.selectedIndex == 1)
{
if (images[selectedIndex] != nil)
{
self.yourButtonOutlet2.setImage(images[selectedIndex], for: .normal)
}
else
{
// set plus icon image to your button
}
}
else if (self.selectedIndex == 2)
{
if (images[selectedIndex] != nil)
{
self.yourButtonOutlet3.setImage(images[selectedIndex], for: .normal)
}
else
{
// set plus icon image to your button
}
}
else if (self.selectedIndex == 3)
{
if (images[selectedIndex] != nil)
{
self.yourButtonOutlet4.setImage(images[selectedIndex], for: .normal)
}
else
{
// set plus icon image to your button
}
}
else if (self.selectedIndex == 4)
{
if (images[selectedIndex] != nil)
{
self.yourButtonOutlet5.setImage(images[selectedIndex], for: .normal)
}
else
{
// set plus icon image to your button
}
}
}
You can use in build Image Picker
extension EditProfileViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// localUserData.ProfileImage = info[.originalImage] as? UIImage
self.imgProfile.image = info[.originalImage] as? UIImage
self.dismiss(animated: true, completion: {
let yes = UIAlertAction(title: "Yes", style: .default, handler: { _ in
self.imgProfile.image = self.localUserData.ProfileImage
})
let no = UIAlertAction(title: "No", style: .default, handler: nil)
self.showCustomAlert(alertMsg: ValidationMsg.imageUpload.rawValue, actions: [yes,no])
})
}
}
The correct answer was given, just want to make it shorter.
The every button should have a tag, from 0 to 4.
Then you can create a property in your controller. Let it be selectedIndex. In the addImage you should add the line:
#IBAction func addImage(_ sender: UIButton) {
self.selectedIndex = _sender.tag
....
}
Then in the delegate method after you got an image:
images[selectedIndex] = image
let buttons = [button1, button2, button3, button4, button5]
let selectedButton = buttons[selectedIndex]
if (images[selectedIndex] != nil) {
selectedButton.setImage(images[selectedIndex], for: .normal)
}
else {
selectedButton.setImage(imagePlus, for: .normal)
}
I have a chat feature within my app. The page loads the existing data as an array called hhmessages. The last message in the conversation was 'Welcome', when I enter new text 'Thank You' and hit enter the table automatically displays 'Welcome' again instead of 'Thank You.' If it exit out of the page and come back it now shows 'Thank You' as the last message. It's working on the backend just the instant update isn't showing the value in the UITableView when entered.
This is for an iPhone app.
UPDATED TO SHOW COMPLETE CODE - Now that reverse has been removed the new entry shows as blank.
import UIKit
import Foundation
extension String {
// Calculeta the hight string Function
func calculateTextFrameRect(
objectsInPlaceHeight: CGFloat,
objectsInPlaceWidth: CGFloat,
fontSize: CGFloat,
fontWeight: CGFloat) -> CGSize
{
let bounding = CGSize(width: UIScreen.main.bounds.width - objectsInPlaceWidth, height: .infinity)
let rect = NSString(string: self).boundingRect(
with: bounding,
options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin),
attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize, weight: UIFont.Weight(rawValue: fontWeight))],
context: nil)
return CGSize(width: UIScreen.main.bounds.width, height: rect.height + objectsInPlaceHeight )
}
}
// Messages for test
let frame = CGRect(origin: .zero, size: CGSize.init(width: 375, height: 559))
class Message {
let message: String
var incoming: [Int]
let image: UIImage
var avas = UIImage()
init(message: String, image: UIImage, incoming: Int, avas: UIImage) {
self.message = message
self.image = image
self.incoming = [incoming]
self.avas = avas
}
}
class ConversationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
//var user = NSDictionary()
var messages = NSDictionary()
//var guest = NSDictionary()
#IBOutlet var senderLbl: UILabel!
#IBOutlet var senderageLbl: UILabel!
#IBOutlet var senderraceLbl: UILabel!
#IBOutlet var sendergenderLbl: UILabel!
#IBOutlet var sendercityLbl: UILabel!
#IBOutlet var senderstateLbl: UILabel!
// #IBOutlet var tableView: UITableView!
var hhmessages = [AnyObject]()
//var messages: [Message] = []
var pictures = [UIImage]()
var avas = [UIImage]()
var avaURL = [String]()
var isLoading = false
var skip = 0
var limit = 50
var images = [UIImage]()
var incoming: [Int] = []
var comments = [String]()
var ids = [String]()
//var isSent: String = ""
var isPictureSelected = false
//var currentUser_ava = [Any]()
#IBOutlet var pictureImg: UIImageView!
#IBOutlet var avaImg: UIImageView!
#IBOutlet var viewprofile_btn: UIButton!
#IBOutlet var imgprofile_btn: UIButton!
#IBOutlet var replyTxt: UITextView!
//var replyTxt:UITextView!
#IBOutlet var replyTxt_height: NSLayoutConstraint!
#IBOutlet var replyTxt_bottom: NSLayoutConstraint!
#IBOutlet var picSelect: UIButton!
#IBOutlet var replyBtn: UIButton!
var puuid = String()
var imageSelected = false
var coolIndicator: UIActivityIndicatorView!
var commentsTextView_bottom_identity = CGFloat()
#IBOutlet var tableView: UITableView!
// Table View here + basic configuration
override func viewDidLoad() {
//self.tabBarController?.tabBar.isHidden = true
super.viewDidLoad()
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
// dynamic cell height
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 200
loadPosts()
replyTxt.layer.cornerRadius = replyTxt.bounds.width / 50
replyTxt.backgroundColor = UIColor.clear
replyTxt.layer.borderColor = UIColor.gray.cgColor
replyTxt.layer.borderWidth = 1.0
let username = messages["sender"] as? String
self.navigationItem.title = username
}
// pre last func
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// remove observers of notification when the viewController is left
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
// exec-d once notification is caught -> KeyboardWillShow
#objc func keyboardWillShow(_ notification: Notification) {
// getting the size of the keyboard
if let keyboard_size = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
// increasing the bottom constraint by the keyboard's height
replyTxt_bottom.constant += keyboard_size.height
}
// updating the layout with animation
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
// exec-d once notification is caught -> KeyboardWillHide
#objc func keyboardWillHide() {
// updating the layout with animation
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//replyTxt().resignFirstResponder()
self.view.endEditing(false)
}
// TABLEVIEW
// Number os cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hhmessages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let colorSmoothGray = UIColor(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
let colorBrandBlue = UIColor(red: 148 / 255, green: 33 / 255, blue: 147 / 255, alpha: 1)
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
print("test 1", pictureURL)
// no picture in the post
if pictureURL == nil || pictureURL == "" {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// shortcuts
let hhpost = hhmessages[indexPath.row]
let text = hhpost["messagetext"] as? String
cell.messageLbl.text = text
cell.messageLbl.textAlignment = .right
cell.messageLbl.backgroundColor = colorSmoothGray
cell.messageLbl.textColor = .black
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
cell.messageLbl.sizeToFit()
pictures.append(UIImage())
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "PicCell", for: indexPath) as! PicConversationCell
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
let smimages = hhmessages[indexPath.row]["path"] as? UIImage
cell.smavaImg.image = smimages
for i in 0 ..< self.incoming.count {
// Confiture the constraints for cell
if self.incoming[indexPath.row] == 1 {
// Text
cell.messageLbl.textAlignment = .left
cell.messageLbl.backgroundColor = colorBrandBlue
cell.messageLbl.textColor = .white
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
// Constraints
cell.lefBubbleConstraint.isActive = true
cell.rightBubbleConstraint.isActive = false
if cell.postpictureImg.image == nil {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
else {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
}
else if self.incoming[indexPath.row] == 0 {
// Text
cell.messageLbl.textAlignment = .right
cell.messageLbl.backgroundColor = colorSmoothGray
cell.messageLbl.textColor = .black
cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
cell.messageLbl.font?.withSize(25)
cell.messageLbl.clipsToBounds = true
// Constraints
cell.lefBubbleConstraint.isActive = false
cell.rightBubbleConstraint.isActive = true
if cell.postpictureImg.image == nil {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
else {
cell.postpictureImg.backgroundColor = .black
cell.postpictureImg.clipsToBounds = true
}
}
if cell.lefBubbleConstraint.isActive == true {
cell.lefImageConstraint.isActive = true
cell.rightImageConstraint.isActive = false
} else {
cell.lefImageConstraint.isActive = false
cell.rightImageConstraint.isActive = true
}
let pictureString = hhmessages[indexPath.row]["uploadpath"] as! String
let pictureURL = URL(string: pictureString)!
// if there are still pictures to be loaded
if hhmessages.count != pictures.count {
URLSession(configuration: .default).dataTask(with: pictureURL) { (data, response, error) in
// downloaded
if let image = UIImage(data: data!) {
self.pictures.append(image)
DispatchQueue.main.async {
cell.postpictureImg.image = image
}
}
}.resume()
// cached picture
} else {
DispatchQueue.main.async {
cell.postpictureImg.image = self.pictures[indexPath.row]
}
}
}
return cell
}
}
// pre load func
override func viewDidAppear(_ animated: Bool) {
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
// func of loading posts from server
#objc func loadPosts() {
//isLoading = true
let me = user!["username"] as! String
let meid = user!["id"] as! String
print(meid)
print(me)
//print(username)
let uuid = messages["uuid"] as! String
print(uuid)
// accessing php file via url path
let url = URL(string: "http://localhost/message.php")!
// pass information to php file
let body = "username=\(me)&uuid=\(uuid)&recipient_id=\(meid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: String.Encoding.utf8)
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
// launch session
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// no error of accessing php file
// error occured
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
do {
// access data - safe mode
guard let data = data else {
Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
// getting content of $returnArray variable of php file
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
// accessing json data - safe mode
guard let posts = json?["messages"] as? [NSDictionary] else {
//self.isLoading = false
return
}
// assigning all successfully loaded posts to our Class Var - posts (after it got loaded successfully)
self.hhmessages = posts
self.tableView.reloadData()
// scroll to the latest index (latest cell -> bottom)
let indexPath = IndexPath(row: self.hhmessages.count - 1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
// self.isLoading = false
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
//self.isLoading = false
return
}
}
}.resume()
}
#IBAction func viewprofile_clicked(_ sender: Any) {
// performSegue(withIdentifier: "guest2", sender: self.guest)
}
#IBAction func imgprofile_clicked(_ sender: Any) {
// performSegue(withIdentifier: "guest2", sender: self.guest)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "guest" {
if let destination = segue.destination as? GuestViewController {
destination.guest = messages
}
}
}
// function sending requset to PHP to uplaod a file
func uploadPost() {
// validating vars before sending to the server
guard let user_id = user?["id"] as? String, let username = user?["username"] as? String, let avaPath = user?["ava"] else {
// converting url string to the valid URL
if let url = URL(string: user?["ava"] as! String) {
// downloading all data from the URL
guard let data = try? Data(contentsOf: url) else {
return
}
// converting donwloaded data to the image
guard let image = UIImage(data: data) else {
return
}
// assigning image to the global var
let currentUser_ava = image
}
return
}
let user_id_int = Int(user_id)!
let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
replyTxt.text = ""
textViewDidChange(replyTxt)
let recipient = messages["username"] as! String
let rid = String(describing: messages["recipient_id"]!)
let uuid = messages["uuid"] as! String
puuid = UUID().uuidString
// prepare request
let url = URL(string: "http://localhost/messagepost.php")!
let body = "sender_id=\(user_id)&sender=\(username)&text=\(messagetext)&recipient_id=\(rid)&recipient=\(recipient)&uuid=\(uuid)&puuid=\(puuid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: .utf8)
// send request
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// error happened
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
return
}
do {
// converting received data from the server into json format
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
// safe mode of casting json
guard let parsedJSON = json else {
return
}
// if the status of JSON is 200 - success
if parsedJSON["status"] as! String == "200" {
} else {
Helper().showAlert(title: "400", message: parsedJSON["status"] as! String, in: self)
return
}
// json error
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
return
}
}
}.resume()
}
// exec-d whenever delegated textView has been changed by chars
func textViewDidChange(_ textView: UITextView) {
// declaring new size of the textView. we increase the height
let new_size = textView.sizeThatFits(CGSize.init(width: textView.frame.width, height: CGFloat(MAXFLOAT)))
// assign new size to the textView
textView.frame.size = CGSize.init(width: CGFloat(fmaxf(Float(new_size.width), Float(textView.frame.width))), height: new_size.height)
//UIView.animate(withDuration: 0.2) {
self.view.layoutIfNeeded()
//}
}
#IBAction func picSelect_clicked(_ sender: AnyObject) {
// calling picker for selecting iamge
showActionSheet()
}
// this function launches Action Sheet for the photos
func showActionSheet() {
// declaring action sheet
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// declaring camera button
let camera = UIAlertAction(title: "Camera", style: .default) { (action) in
// if camera available on device, than show
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.showPicker(with: .camera)
}
}
// declaring library button
let library = UIAlertAction(title: "Photo Library", style: .default) { (action) in
// checking availability of photo library
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
self.showPicker(with: .photoLibrary)
}
}
// declaring cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
// adding buttons to the sheet
sheet.addAction(camera)
sheet.addAction(library)
sheet.addAction(cancel)
// present action sheet to the user finally
self.present(sheet, animated: true, completion: nil)
}
// takes us to the PickerController (Controller that allows us to select picture)
func showPicker(with source: UIImagePickerControllerSourceType) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = source
present(picker, animated: true, completion: nil)
}
// executed whenever the image has been picked via pickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// accessing selected image
let image = info[UIImagePickerControllerEditedImage] as? UIImage
// assigning selected image to pictureImageView
pictureImg.image = image
// cast boolean as TRUE -> Picture Is Selected
isPictureSelected = true
// remove pickerController
pictureImg.image = info[UIImagePickerControllerEditedImage] as? UIImage
self.dismiss(animated: true, completion: nil)
// cast as a true to save image file in server
if pictureImg.image == info[UIImagePickerControllerEditedImage] as? UIImage {
imageSelected = true
}
dismiss(animated: true, completion: nil)
}
// exec when pictureImageView has been tapped
#IBAction func pictureImageView_tapped(_ sender: Any) {
// declaring action sheet
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// declaring delete button
let delete = UIAlertAction(title: "Delete", style: .destructive) { (action) in
self.pictureImg.image = UIImage()
}
// declaring cancel button
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
// adding buttons to the sheet
sheet.addAction(delete)
sheet.addAction(cancel)
// present action sheet to the user finally
self.present(sheet, animated: true, completion: nil)
}
// custom body of HTTP request to upload image file
func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
// if file is not selected, it will not upload a file to server, because we did not declare a name file
var filename = ""
if imageSelected == true {
filename = "notes-\(puuid).jpg"
}
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body as Data
}
#IBAction func replyBtn_clicked(_ sender: Any) {
if replyTxt.text.isEmpty == false && replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false {
uploadPost()
//tableView.reloadData()
}
}
#objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
//print("deltaY",deltaY)
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.replyTxt.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.tableView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.replyBtn.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
self.picSelect.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
},completion: nil)
}
func textFieldShouldReturn(_ replyTxt: UITextField) -> Bool {
replyTxt.resignFirstResponder()
return true
}
}
the problem is you are inserting the new text at
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
which is the last field of the array.
but in your cellForRow: you have
let text = hhmessages.reversed()[indexPath.row]["messagetext"] as! String
which shows the first field of your array in the last cell of tableView.
I think thats your problem.
Like others have told, you are messing up your order in hhmessages.
Imagine you have messages Welcome, Hello, and you are trying to add Thank Your, your code with more comments:
self.hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex) // Thank You is inserted to the end of the array at 3rd position (2)
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0) // ok, let's get index of 3rd row (2)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic) // add new row to the end
tableView.endUpdates()
Then later UIKit asks you to load this new 3rd row at position 2, and you call:
let text = hhmessages.reversed()[indexPath.row]["messagetext"] as! String
The problem is hhmessages.reversed() which reverses your array, and makes Thank you in fact first at position 0, and Welcome the last one at position 2, which will get the text Welcome.
The second problem I see is this line:
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
Here you are getting unreveresed picture url, which at least is very strange.
I've been looking around on stackoverflow for a solution but I haven't yet successfully implemented it. If someone can give me some tips on where the problem lies, thank you so much. Here is what I have so far
Here is location class
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
Method to display all annotations.
func displayAllEventsPins() {
for event in events {
let address = event.location
geocoder.geocodeAddressString(address!, completionHandler: { (placemarks: [CLPlacemark]?, error: Error?) -> Void in
if let placemark = placemarks?.first {
let eventlat = placemark.location?.coordinate.latitude
let eventlong = placemark.location?.coordinate.longitude
let annotation = MKPointAnnotation()
annotation.title = event.name
annotation.coordinate = CLLocationCoordinate2D(latitude: eventlat!, longitude: eventlong!)
self.locations.append(Location(title: annotation.title!, coordinate: annotation.coordinate))
for location in self.locations {
let pin = MKPointAnnotation()
pin.title = location.title
pin.coordinate = location.coordinate
self.mapView.addAnnotation(pin)
}
}
})
}
}
Edited: The problem here is that annotations doesnt show up on mapview. I can only see the currentlocation pin and nothing else.
Edited: This is the call i used to drop user current location pin.
extension Search : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//MARK: remove previous current pin for user location
mapView.removeAnnotation(newPin)
let location = locations.last! as CLLocation
let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
self.currentLocation = location
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.03, 0.03))
mapView.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
mapView.addAnnotation(newPin)
}
}
Here is the code in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Request Current Location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.requestLocation()
displayAllEventsPins()
}
This should work for you.
By the way, looping through your locations whilst in the events loop is just going to add duplicates of the same pin, which will be very bad on memory and it's not a good thing to do.
import UIKit
import MapKit
import Firebase
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
var events = Array<Event>()
var locations = Array<Location>()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// This closure gets called once for every event in your database
getEvents { (event, pin) in
self.tableView.reloadData()
if event != nil && pin != nil {
print(event!)
self.locations.append(pin!)
self.events.append(event!)
} else {
print("Failed to get event.")
}
}
}
func getEvents(results: #escaping (_ event: Event?, _ pin:Location?)->()) {
let ref = FIRDatabase.database().reference().child("Events")
ref.observe(.childAdded, with: { (snapshot) in
guard let value = snapshot.value as? Dictionary<String,String> else { return }
guard let name = value["eventName"],
let location = value["location"],
let attending = value["attendance"],
let dateTime = value["dateTime"],
let addedByUser = value["addedByUser"] else { return }
self.getEventPlacemark(address: location, results: { (placemark) in
if let placemark = placemark {
let pin = Location(title: name, coordinate: placemark.coordinate)
var distance: Double = -1 // If user location is not avalible, this will stay at -1
if let currentLocation = self.locationManager.location?.coordinate {
distance = pin.coordinate.distance(to: currentLocation)
}
let event = Event(id: snapshot.key, name: name, location: location, dateTime: dateTime, addedByUser: addedByUser, attending: attending, distance: distance)
results(event, pin)
return
}
})
})
}
func getEventPlacemark(address:String, results: #escaping (_ placemark: MKPlacemark?)->()){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let error = error {
print(error.localizedDescription)
results(nil)
}
if let placemark = placemarks?.first {
results(MKPlacemark(placemark: placemark))
}
}
}
func displayAllEvents(){
self.map.addAnnotations(self.locations)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let userLocation = annotation as? MKUserLocation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "userLocationPin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: userLocation, reuseIdentifier: "userLocationPin")
view.pinTintColor = .purple
view.canShowCallout = true
return view
}
if let pin = annotation as? MKPointAnnotation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "pin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: pin, reuseIdentifier: "pin")
view.pinTintColor = .red
view.canShowCallout = true
return view
}
return nil
}
}
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
}
struct Event {
var name: String
var location: String
}
extension CLLocationCoordinate2D {
func distance(to: CLLocationCoordinate2D) -> CLLocationDistance {
return MKMetersBetweenMapPoints(MKMapPointForCoordinate(self), MKMapPointForCoordinate(to))
}
}
If you are going to implement my code above, you'll need to remove your code from
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
because you don't need to add the pin manually anymore.
Can you try putting this in your view did load function and not have anything else run. This should put a pin to the west of Africa.
Something to notice, if the coordinate is
CLLocationCoordinate2D(latitude: 0, longitude: 0), the pin appears
right down at Antartica on the date line, which is the bottom right of
the map. So if for some reason your coordinate is the default 0,0,
your pins might by sitting there.
let pin = MKPointAnnotation()
pin.title = "Null Island"
pin.coordinate = CLLocationCoordinate2DMake(0.000001, 0.000001)
self.map.addAnnotation(pin)
This could possibly be where your pins are.
I have 2 arrays
var messages = [Message]()
var screenMessages = [screenMessage]()
I have the messages array items in a NSTableView.. when I press an IBOutlet I would like to pass the items in that row to the screenMessages array to present in another NSTableView.
My NSTableView starts like so..
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
I've tried a number of ways of appending the screenMessages with the messages[row] but I can't put my finger on it. If anyone could demonstrate or point me in the right direction that would be brilliant.
Thank you.
Added more detail:
Screen one looks like so and when pressing the add button it should then pass that data from that row into screen twos tableview..
Screen two:
My View for screen one is as:
import Firebase
import Cocoa
var messages = [Message]()
var screenMessages = [screenMessage]()
class secondVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var screenRefreshBtn: NSButton!
#IBOutlet weak var refreshButton: NSButton!
var senderImageUrl: String!
var ref: Firebase!
var messagesRef: Firebase!
func setupFirebase() {
messagesRef = Firebase(url: "https://url.firebaseio.com/screenmessages")
messagesRef.queryLimitedToLast(25).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in
let text = snapshot.value["text"] as? String
let sender = snapshot.value["senderName"] as? String
let imageUrl = snapshot.value["profileImageURL"] as? String
let MediaType = snapshot.value["MediaType"] as! String
let fileUrl = snapshot.value["fileUrl"] as? String
let message = Message(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
messages.append(message)
let screenmessage = screenMessage(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
screenMessages.append(screenmessage)
switch MediaType{
case "TEXT":
print("text message")
case "PHOTO":
print("photo message")
default:
print("default")
}
self.tableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
setupFirebase()
}
// MARK: - Table View
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return messages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
if mess.text() == nil {
result?.textField?.alphaValue = 0
result!.sendertextView.stringValue = mess.sender()
let url = NSURL(string: mess.fileUrl()!)!
// Download task:
// - sharedSession = global NSURLCache, NSHTTPCookieStorage and NSURLCredentialStorage objects.
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
// if responseData is not null...
if let data = responseData{
// execute in UI thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
task.resume()
} else {
result!.textField!.stringValue = mess.text()!
result!.sendertextView.stringValue = mess.sender()
}
return result
}
#IBAction func addtablerow(object: NSButton) {
let row = tableView.rowForView( object as NSView )
if ( row > -1 ) {
}
}
And my second screen is:
import Cocoa
class screenVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
var addedObserver = false
#IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
refreshObs()
clearObs()
self.tableView.backgroundColor = NSColor.clearColor()
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
} else {
addedObserver = true
self.addObserver(self, forKeyPath: "view.window", options: [.New, .Initial], context: nil)
}
}
func refreshList(notification: NSNotification){
self.tableView.alphaValue = 0
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
animateViewRefresh()
tableView.scrollToEndOfDocument(self)
}
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return screenMessages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell2", owner: self) as? screenviewTableCell
let mess = screenMessages[row]
result?.senderLabel.stringValue = mess.sender()
if mess.text() != nil {
result?.messageTextView.stringValue = mess.text()!
let url = NSURL(string: mess.imageUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
} else {
result?.messageTextView.alphaValue = 0
let mess = screenMessages[row]
let url = NSURL(string: mess.fileUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
let url2 = NSURL(string: mess.imageUrl()!)!
let task2 = NSURLSession.sharedSession().dataTaskWithURL(url2) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
task2.resume()
}
return result
}
// MARK : Animate
func animateView(notification: NSNotification){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 2
self.tableView.animator().alphaValue = 0
screenMessages.removeAll()
}, completionHandler: { () -> Void in
})}
func animateViewRefresh(){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 4
self.tableView.animator().alphaValue = 1
}, completionHandler: { () -> Void in
})}
func refreshObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.refreshList(_:)), name:"refreshMyTableView", object: nil)
}
func clearObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.animateView(_:)), name:"clearMyTableView", object: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
window.titlebarAppearsTransparent = true
window.movableByWindowBackground = true
window.opaque = true
window.backgroundColor = NSColor.clearColor()
}
}
deinit {
if addedObserver {
self.removeObserver(self, forKeyPath: "view.window")
}
}
}
I have tried a number of things such as 'screenMessages += messages(row)' and appending to add that row to the screenMessages array but I've had no luck.
Am I going about this in the right way or is there a better way of doing so?
Thank you.
To append an element from one array to another array just write
let index = index of element you need
let message = messages[index]
screenMessages.append(message)
If message is not the same type as the contents of the screenMessages array you will need to convert it, I would need more details of the types to help with that.
If you are having trouble passing the data to another ViewController I would need more information on the current architecture to give good advice, but for example you might define a protocol MessageDelegate that one of the controllers implements and the other has as a property.
update
If you update your data array for a table and want the new information to appear remember to call reloadData on the UITableView
So I have an array made of strings, and when the user presses on my textfield, it shows a PickerView using the array.
I would like the PickerView to show the contents of the array in alphabetical order. But I have no idea how to do this, and cannot find anywhere online how to do it in Swift. Can someone please help?
Thanks in advance!
MY CODE:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet var questionLabel: UILabel!
#IBOutlet var buttonLabel: UIButton!
#IBOutlet var myBackgroundView: UIImageView!
#IBOutlet var questionTextField: UITextField!
let questions = ["Where are you going?", "Which city?", "When do you go?"]
var currentQuestionIndex = 0
let placeholder = ["Country", "City", "Date"]
var currentPlaceholderIndex = 0
#IBAction func nextButton(sender: AnyObject) {
// Initial setup on button press
questionTextField.hidden = false
barImage.hidden = false
// Reset text field to have no text
questionTextField.text = ""
// Displays the questions in array and displays the placeholder text in the textfield
if currentQuestionIndex <= questions.count && currentPlaceholderIndex <= placeholder.count {
questionLabel.text = questions[currentQuestionIndex]
questionTextField.placeholder = placeholder[currentPlaceholderIndex]
currentQuestionIndex++
currentPlaceholderIndex++
buttonLabel.setTitle("Next", forState: UIControlState.Normal)
// Animate text for questionLabel
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.5, options: nil, animations: {
self.questionLabel.center = CGPoint(x: -110 , y: 305 + 20)
}, completion: nil)
} else {
performSegueWithIdentifier("countdownSegue", sender: self)
//Add some logic here to run whenever the user has answered all the questions.
}
}
var countryPicker = ["France", "Germany", "Spain", "Northern Ireland", "Austria"]
var sortedArray = sorted(countryPicker)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Hides the text field
questionTextField.hidden = true
questionTextField.delegate = self
// Sets the button text
buttonLabel.setTitle("Get started", forState: UIControlState.Normal)
// Sets the question text to be blank
questionLabel.text = ""
// Sets placeholder text in the text field
questionTextField.placeholder = ""
var pickerView = UIPickerView()
pickerView.delegate = self
questionTextField.inputView = pickerView
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return countryPicker.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return countryPicker[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
questionTextField.text = countryPicker[row]
}
// resigns the keyboard when user presses the return/next key on keyboard
func textFieldShouldReturn(textField: UITextField) -> Bool {
questionTextField.resignFirstResponder()
return true
}
// Resigns the keyboard if the user presses anywhere on the screen
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Sort the array, or create a sorted version of the array, and then use that sorted array as the source for your picker view.
let array = ["orange", "grape", "apple", "pear", "mango"]
let sortedArray = sorted(array)
you would then use sortedArray in the data source for your picker view.
I managed to get was i was looking for with this:
countryPicker.sort(){$0 < $1}
It sorted the array from A-Z, and was the only way it worked for me.