How to change the default name of file to share in Swift? - ios

everyone!
I'm new in Swift and I've run into a problem.
I have an app that show images and I want to share some. When I click "share icon" there is default name "JPEG image". How can I change it to something like "defaultImageName".
Image I want to share
Share using default share in iOS
And here's default name that I want to change "JPEG image"
I've tried something like
imageView.image = UIImage(named: "defaultImageName")
But it's not correct, cause imageView.image it's not that I want to change.
Here's my code. I think it should be in #objc func shareTapped(), but don't really know how to do it.
import UIKit
class DetailViewController: UIViewController {
#IBOutlet var imageView: UIImageView!
var selectedImage: String?
var pictures = [String]()
override func viewDidLoad() {
super.viewDidLoad()
title = "Picture \(pictures.firstIndex(of: selectedImage!)!+1) of \(pictures.count)"
navigationItem.largeTitleDisplayMode = .never //
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
if let imageToLoad = selectedImage {
imageView.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnTap = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.hidesBarsOnTap = false
}
#objc func shareTapped() {
guard let image = imageView.image?.jpegData(compressionQuality: 0.8) else {
print("No image found")
return
}
let vc = UIActivityViewController(activityItems: [image], applicationActivities: [])
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true)
}
}

Related

UIImagePickerControllerDelegate not being called, selected image never displayed

I'm stumped. Everything is working except it's not. I can call up the camera interface and take or select a photo yet UIImagePickerControllerDelegate is never being called (I've put two print statements that well, never get printed). Everything is correctly connected in IB, or so I believe it is (I'm fully ready for it so be something totally minor that I missed). Anyone care to take a frtesh set of eyes and go over this to see if I just can't see the forest for the trees?
Thanks in advance.
import UIKit
import Foundation
class afterPhotoViewController: UIViewController {
//MARK: - IBOutlet Properties
#IBOutlet weak var afterImageView: UIImageView!
#IBOutlet weak var aftervwImage: UIView!
#IBOutlet weak var cameraBtnPressed: UIButton!
//MARK: - Useful Variables
let afterImagePicker = UIImagePickerController()
var hud = HKProgressHUD()
var localTextFilePath : URL!
var isImageSetted = false
//MARK: - App Delegates
var isMain = false
var originFrame = CGRect()
override func viewDidLoad() {
super.viewDidLoad()
// Init UI Components
self.initUI()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - UI Init
func initUI() {
// Set Navigation Bar
let backButton = UIBarButtonItem(title: "", style: .plain, target: navigationController, action: nil)
navigationItem.leftBarButtonItem = backButton
self.title = "\(h_proposalNumberStr)-\(h_itemIndex)"
// Set ImageView
self.afterImageView.image = #imageLiteral(resourceName: "ic_placeholder")
self.afterImageView.clipsToBounds = false
cameraBtnPressed.layer.cornerRadius = 15
cameraBtnPressed.layer.borderColor = UIColor.lightGray.cgColor
cameraBtnPressed.layer.borderWidth = 1
self.isImageSetted = false
// self.tableView.reloadData()
}
//MARK: - UI Actions
#IBAction func cameraBtnPressed(_ sender: Any) {
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel) { _ in
}
actionSheetController.addAction(cancelActionButton)
let chooseLibraryActionButton = UIAlertAction(title: "Choose from Library", style: .default)
{ _ in
self.isMain = true
self.afterImagePicker.allowsEditing = true
self.afterImagePicker.sourceType = .photoLibrary
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(self.afterImagePicker, animated: true, completion: nil)
}
actionSheetController.addAction(chooseLibraryActionButton)
let takePhotoActionButton = UIAlertAction(title: "Take a Photo", style: .default)
{ _ in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.isMain = true
self.afterImagePicker.allowsEditing = false
self.afterImagePicker.sourceType = .camera
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .camera)!
self.afterImagePicker.showsCameraControls = true
self.present(self.afterImagePicker, animated: true, completion: nil)
} else {
Helper.showMessage(vc: self, title: CONSTANTS.APPINFO.APP_NAME, bodyStr: "No camera available.")
}
}
actionSheetController.addAction(takePhotoActionButton)
self.present(actionSheetController, animated: true, completion: nil)
}
//MARK: - UIImagePickerControllerDelegate
extension afterPhotoViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("called")
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("called2")
//getting actual image
var image = info[UIImagePickerControllerEditedImage] as? UIImage
if image == nil {
image = info[UIImagePickerControllerOriginalImage] as? UIImage
}
afterImageView.image = image
// Set Imageview Corner Radius
afterImageView.layer.cornerRadius = 5
afterImageView.clipsToBounds = true
self.isImageSetted = true
picker.dismiss(animated: true, completion: nil)
}
}
#raja Kishan caught my stupid simple error of forgetting to set the delegate.
Now, where's the facepalm emoji.
You have to specify that the UIImagePickerController's delegate is self, so that the events are triggered.
In your case:
afterImagePicker.delegate = self

Accessing rightBarButton function from another ViewController in Swift

I'm trying to access the rightBarButton function for showing cart from an another ViewController, although I can call that function but it won't display any image i.e cart image
Below code show how am i calling this function.
override func viewDidLoad() {
super.viewDidLoad()
// Adding Right Bar Button Item
let rightBarButton = RightBarButton()
rightBarButton.addingRightButton()
}
Below code show about the rightBarButton function.
class RightBarButton {
var storyboard = UIStoryboard()
var navigationItem = UINavigationItem()
var navigationController = UINavigationController()
func addingRightButton() {
let image = UIImage(named: "cart")
let finalImage = resizeImage(image: image!, newWidth: 30)
navigationItem.rightBarButtonItem = FFBadgedBarButtonItem(image: finalImage, target: self, action: #selector(rightButtonTouched))
let button = navigationItem.rightBarButtonItem as? FFBadgedBarButtonItem
cartCount { (cartCount) in
print("Api calling done ...")
print(cartCount)
button?.badge = "\(cartCount)"
}
}
#objc func rightButtonTouched() {
// print("Event Called")
}
func cartCount(completion: #escaping (Int) -> Void) {
// print("Api calling ...")
}
}
If I add this code inside the viewDidLoad() the image will display and the click event work as well.
If you find any solution regarding this code please help!
It doesn't work because navigationItem in your RightBarButton class is not part to of any navigation contoller (as it is manually created and not explicitly attached).
Make the created FFBadgedBarButtonItem instance to be accessible to the view controller so you can add it correctly:
override func viewDidLoad() {
super.viewDidLoad()
// Adding Right Bar Button Item
let rightBarButton = RightBarButton()
rightBarButton.addingRightButton()
navigationItem.rightBarButtonItem = rightBarButton.badgeBarItem // badgeBarItem is the property exposed to the view controller
}
The edited RightBarButton class:
class RightBarButton {
var badgeBarItem: FFBadgedBarButtonItem?
func addingRightButton() {
let image = UIImage(named: "cart")
let finalImage = resizeImage(image: image!, newWidth: 30)
badgeBarItem = FFBadgedBarButtonItem(image: finalImage, target: self, action: #selector(rightButtonTouched))
cartCount { [weak self] cartCount in
print("Api calling done ...")
print(cartCount)
self?.badgeBarItem?.badge = "\(cartCount)"
}
}
#objc func rightButtonTouched() {
// print("Event Called")
}
func cartCount(completion: #escaping (Int) -> Void) {
// print("Api calling ...")
}
}
You need to retreive an instance of needed ViewController with rightBarButton, say neededViewController. And then you can call it like here:
neededViewController.viewDidLoad()
or make another method in neededViewController's class with next content:
func addRB () {
// let rightBarButton = RightBarButton(image: UIImage(named: "imageName"), landscapeImagePhone: UIImage(named: "imageName"), style: .done, target: self, action: nil)
let nc = navigationController
let navBar = nc?.navigationBar
let but = UIBarButtonItem(image: UIImage(named: "imageName"), landscapeImagePhone: UIImage(named: "imageName"), style: .done, target: self, action: nil)
// try to create RightBarButton with defined images and a text and pass it instead of `but`
navBar?.topItem?.setRightBarButton(but, animated: false)
}
and call neededViewController.addRB()

VC with UISlider to change textfield on VC2

I have a View controller that has a tableView embedded in a ContainerView and just below the ContainerView I have a UISlider. I have code on a view controller for the UISlider and code on another view controller that controls the table view.
Properties of the UISlider are set based on the selected text field - this section of code works. I am struggling to create a function/feature that will change the textField value when the UISlider is move. I think the UISlider Action needs to on the code that controls the UISlider, but I cannot determine how to cast the value of the UISlider.setvalue between the two viewController as the slider is moved to update the textField located in a tableCell. Hopefully makes some sense.
// UISlider ViewController
override func viewDidLoad() {
super.viewDidLoad()
sliderOutlet.isContinuous = true
sliderOutlet.tintColor = UIColor.green
self.refreshSlider()
}
#objc func refreshSlider() {
sliderOutlet.minimumValue = Float(GlobalSliderValues.minimumValue)
sliderOutlet.maximumValue = Float(GlobalSliderValues.maximumValue)
sliderOutlet.value = Float(GlobalSliderValues.sliderValue)
// if let chgIntValue = Int(GlobalSliderValues.changeValue)
// { sliderOutlet.setValue(Float(Double(chgIntValue)), animated: true)
// }
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshSlider), name: Notification.Name("refreshSlider"), object: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self, name: Notification.Name("refreshSlider"), object: nil)
}
TableView Controller
override func viewDidLoad() {
super.viewDidLoad()
mortgageAmount.addTarget(self, action: #selector(chgTextFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
}
#objc func chgTextFieldDidChange(textField: UITextField)
{
if let chgStringValue = mortgageAmount.text
{
if Double(chgStringValue) ?? 1 > 10000 {
let alert = UIAlertController(title: "Input Error", message: "Value cannot be greater than 10000", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
GlobalSliderValues.minimumValue = 10
GlobalSliderValues.maximumValue = 10000
GlobalSliderValues.sliderValue = Int(mortgageAmount.text!)!
GlobalSliderValues.mortageAmountValue = Float(Int(mortgageAmount.text!)!)
NotificationCenter.default.post(name:Notification.Name("refreshSlider"), object: nil)
if let chgIntValue = Int(chgStringValue)
{ GlobalSliderValues.changeValue.setValue(Float(Double(chgIntValue)), animated: true)
}
}
}
#IBAction func valueChanged(_ sender: UISlider) {
mortgageAmount.text = String(format: "%.2f",Double(sender.value))
}
struct GlobalSliderValues {
static var minimumValue = Int()
static var maximumValue = Int()
static var lowerValue = Int()
static var UpperValue = Int()
static var locationValue = Int()
static var sliderValue = Int()
static var sliderChgValue = ""
}
We don't need notification center to deal with refreshing the slider. Since we are using constants to store value your code can be changed as follows
class ViewController: UIViewController {
#IBOutlet weak var sliderOutlet: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
sliderOutlet.isContinuous = true
sliderOutlet.tintColor = UIColor.green
}
#objc func refreshSlider() {
DispatchQueue.main.async {
self.sliderOutlet.minimumValue = Float(GlobalSliderValues.minimumValue)
self.sliderOutlet.maximumValue = Float(GlobalSliderValues.maximumValue)
self.sliderOutlet.value = Float(GlobalSliderValues.sliderValue)
print(self.sliderOutlet.minimumValue)
print(self.sliderOutlet.maximumValue)
print(self.sliderOutlet.value)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.refreshSlider()
}
}
I entered mortgage amount as so 1098 so slider look like below

Selector in UIBarButtonItem not calling

I have a selector on my UIBarButton referencing a function to segue to another view controller but the function never gets called when clicked on. Through testing breakpoints I can see the function, segueToCartViewController, never gets called.
Thanks in advance!
UIBarButtonItem init
private let reuseIdentifier = "ItemCell"
private let SegueCartIdentifier = "CatalogToCart"
final class CatalogViewController: UICollectionViewController {
//MARK: -properties
var brand: Brand!
var cart: [Item]!
fileprivate let itemsPerRow:CGFloat = 3
fileprivate let sectionInsets = UIEdgeInsets(top: 30, left: 20, bottom: 30, right: 20)
private var cartItem: UIBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "Cart"), style: .plain, target: self, action: #selector(segueToCartViewController(_:)))
var selectedItemIndexPath: IndexPath?{
didSet{
var indexPaths = [IndexPath]()
if let selectedItemIndexPath = selectedItemIndexPath{
indexPaths.append(selectedItemIndexPath)
}
if let oldValue = oldValue{
indexPaths.append(oldValue)
}
collectionView?.performBatchUpdates({
self.collectionView?.reloadItems(at: indexPaths)
}) { completed in
if let selectedItemIndexPath = self.selectedItemIndexPath{
self.collectionView?.scrollToItem(at: selectedItemIndexPath, at: .centeredVertically, animated: true)
}
}
}
}
override func viewDidAppear(_ animated: Bool) {
self.navigationController?.setToolbarHidden(false, animated: false)
let flex = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
self.navigationController?.toolbar.items = [flex,cartItem,flex]
}
}
call for segue
//MARK: CartNavigation
extension CatalogViewController: CartDelegate{
func segueToCartViewController(_ sender: AnyObject){
super.performSegue(withIdentifier: SegueCartIdentifier, sender: sender)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? UINavigationController else{
return
}
cartVC.delegate = self
}
func closeModallyPresentedViewController() {
dismiss(animated: true, completion: nil)
}
}
The target of your UIBarButtonItem is nil because self is nil during it's initialization.
You can initialize it like this instead
final class CatalogViewController: UICollectionViewController {
lazy final private var cartItem: UIBarButtonItem = { [unowned self] in
return UIBarButtonItem(image: #imageLiteral(resourceName: <#T##String#>), style: .plain, target: self, action: #selector(segueToCartViewController(_:)))
}()
override function viewDidAppear(_ animated: Bool) {
//blah blah, the rest of your code
}
}
See here for a good explanation about the value of self during initialization of properties.

How to change the bar button icon in toolbar in swift?

I am trying to toggle between the play button and pause button in swift. I have a bar button item in the toolbar whose identifier is initially set to the play. I tried to search and found out the following piece of code but it does not work, looks like it works when the bar button is in the navigation bar
self.navigationItem.setLeftBarButtonItem(UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "TheMethodThatTheButtonShouldCall"), animated: true)
You need to set items on UIToolbar to update toolbar items: call func setItems(_items: [AnyObject]?,animated animated: Bool) with your new items to update the toolbar's items
Source: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIToolbar_Class/index.html#//apple_ref/occ/instm/UIToolbar/setItems:animated:
Implemented your question with the code as below. works in Swift 2. Please note I connected the IBAction outlet to playBtn
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet var sliderVal: UISlider!
#IBOutlet var theToolbar: UIToolbar!
var mySound = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let path = NSBundle.mainBundle().pathForResource("ColdPlay", ofType: "mp3")
do {
mySound = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: path!))
}
catch{
print("error caught")
}
}
#IBAction func playBtn(sender: UIBarButtonItem) {
let theBarbuttonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Pause, target: self, action: "pauseBtn:")
let arrayBarButtonItem = [theBarbuttonItem]
theToolbar.setItems(arrayBarButtonItem, animated: true)
mySound.play()
}
#IBAction func pauseBtn(sender: UIBarButtonItem) {
let theBarbuttonItemB = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Play, target: self, action: "playBtn:")
let arrayBarButtonItemB = [theBarbuttonItemB]
theToolbar.setItems(arrayBarButtonItemB, animated: true)
mySound.pause()
}
}

Resources