I have a simple media player and I'm trying to make it change the artwork image as the songs change. With the code I have now it will display the artwork when you hit play but when I hit the next button to skip to the next item it stays the same unless you hit another button.
How can I make the UIImageView image change as the song media item changes?
import UIKit
import MediaPlayer
class ViewController: UIViewController {
#IBOutlet weak var coverImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createQueue()
}
func showArt(){
coverImageView.image =
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
coverImageView.isUserInteractionEnabled = true
}
#IBAction func playButton(_ sender: UIButton) {
togglePlay(on: sender)
showArt()
}
#IBAction func backButton(_ sender: UIButton) {
back()
}
#IBAction func nextButton(_ sender: UIButton) {
skip()
}
}
My other functions are as followed:
import MediaPlayer
let myMediaPlayer = MPMusicPlayerApplicationController.systemMusicPlayer
let playDrake = MPMediaPropertyPredicate(value: "Drake", forProperty: MPMediaItemPropertyArtist, comparisonType: MPMediaPredicateComparison.equalTo)
let myFilterSet: Set<MPMediaPropertyPredicate> = [playDrake]
func createQueue() {
let drakeQuery = MPMediaQuery(filterPredicates: myFilterSet)
myMediaPlayer.setQueue(with: drakeQuery)
}
func skip() {
myMediaPlayer.skipToNextItem()
}
func back() {
if myMediaPlayer.currentPlaybackTime > 0.05 {
myMediaPlayer.skipToPreviousItem()
} else if myMediaPlayer.currentPlaybackTime < 0.05 {
myMediaPlayer.skipToBeginning()
} else {
//do nothing
}
}
func togglePlay(on: UIButton) {
if myMediaPlayer.playbackState.rawValue == 2 || myMediaPlayer.playbackState.rawValue == 0 {
on.setTitle("Pause", for: UIControlState.normal)
myMediaPlayer.play()
} else if myMediaPlayer.playbackState.rawValue == 1{
on.setTitle("Play", for: UIControlState.normal)
myMediaPlayer.pause()
} else {
// do nothing
}
}
Try loading the image asynchronously
DispatchQueue.global(qos: .background).async {
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
}
Related
Here's what my textView looks like right now. It is a textview inside a scrollview.
I am trying to replace the usual UIMenuController menu items with Save and Delete but not getting there. Can someone help me out?
Here's my code:
import UIKit
class DetailViewController: UIViewController, UIGestureRecognizerDelegate, {
var selectedStory : URL!
#IBOutlet weak var textView: UITextView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var textSlider: UISlider! {
didSet {
configureSlider()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let storyText = try? String(contentsOf: selectedStory)
textView.text = storyText
textView.isUserInteractionEnabled = true
let longPressGR = UILongPressGestureRecognizer(target: self, action: #selector(longPressHandler))
longPressGR.minimumPressDuration = 0.3 //
textView.addGestureRecognizer(longPressGR)
}
// MARK: - UIGestureRecognizer
#objc func longPressHandler(sender: UILongPressGestureRecognizer) {
guard sender.state == .began,
let senderView = sender.view,
let superView = sender.view?.superview
else { return }
senderView.becomeFirstResponder()
UIMenuController.shared.setTargetRect(senderView.frame, in: superView)
UIMenuController.shared.setMenuVisible(true, animated: true)
}
override var canBecomeFirstResponder: Bool {
return true
}
}
extension UITextView{
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == Selector(("_copy:")) || action == Selector(("_share:"))
{
return true
} else {
return false
}
}
}
extension UIScrollView{
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == Selector(("_copy:")) || action == Selector(("_share:"))
{
return true
} else {
return false
}
}
}
I'm getting 2 issues:
When I tap the screen, only the Share is showing up and the Copy is not.
The Share button shows up randomly near the center, not on the text that is selected, like so.
First of all, remove UITextView that is inside UIScrollView because UIScrollView itself is the parent class of UITextView. It will place the UIMenuController at appropriate frame.
Remove longPressGR and longPressHandler methods.
Replace this method,
extension UITextView{
override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action.description == "copy:" || action.description == "_share:" {
return true
} else {
return false
}
}
}
You will get following output.
I want to set a switch or button to mute on a video background in swift 3+
CODE:
import UIKit
import SwiftVideoBackground
class ViewController: UIViewController {
private let videoBackground = VideoBackground()
override func viewDidLoad() {
super.viewDidLoad()
videoBackground.play(view: view, videoName: "intro", videoType: "mp4", isMuted: false, alpha : 0.25, willLoopVideo : true)
}
}
//Add this method to VideoBackground class
public var isMuted = true {
didSet {
playerLayer.player?.isMuted = isMuted
}
}
//Button action method
#IBAction func mute(_ sender: Any) {
videoBackground.isMuted = true
}
// when app is in background
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
videoBackground.pause() // OR videoBackground.isMuted = true
}
SOLUTION:
SOLUTION:
import UIKit
import SwiftVideoBackground
import AVFoundation
class ViewController: UIViewController {
private let videoBackground = VideoBackground()
#IBAction func `switch`(_ sender: UISwitch) {
if (sender.isOn == true)
{
videoBackground.isMuted = true
}
else
{
videoBackground.isMuted = false
}
}
override func viewDidLoad() {
super.viewDidLoad()
videoBackground.play(view: view, videoName: "intro", videoType: "mp4", isMuted: false, alpha : 0.25, willLoopVideo : true)
}
}
I have two of the StoryBoards containing TextFields and two Buttons.
The second StoryBoard has an ImageView received from the first StoryBoard.
I want to make the text in the TextField on the ImageView in the second StoryBoard and then convert it to a PDF file.
I found this code on the site and tried to use it, but I really did not know how to use it and I could not do that. Can someone help me?
import UIKit
import PDFKit
class ViewController: UIViewController {
#IBOutlet weak var textview: UITextField!
#IBOutlet weak var imageview1: UIImageView!
let PdfView = pdfViewController()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Button To send Data To Another view
#IBAction func aa(_ sender: Any)
{
let label = UILabel(frame: CGRect(x: 20, y: 20, width: 80, height: 30))
label.text = "Hello ...!"
label.font = UIFont.systemFont(ofSize: 20)
label.textColor = .black
view.addSubview(label)
sample1(label: label)
//sample2(label: label)
//sample3(label: label)
//sample4(label: label)
PdfView.imageview.clipsToBounds = true
view.addSubview(PdfView.imageview)
}
func sample1(label: UILabel) {
PdfView.imageview.contentMode = .scaleAspectFit
PdfView.imageview.image = UIImage(named: "AR1-1")?.with(view: label) { (parentSize, viewToAdd) in
print("parentSize: \(parentSize)")
viewToAdd.font = UIFont.systemFont(ofSize: 40)
viewToAdd.textColor = .yellow
viewToAdd.bounds = CGRect(x: 40, y: 40, width: 200, height: 40)
}
}
// Button To Move To Another View
#IBAction func ww(_ sender: Any)
{
}
}
extension UIView {
func copyObject<T: UIView> () -> T? {
let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? T
}
}
extension UIImage {
typealias EditSubviewClosure<T: UIView> = (_ parentSize: CGSize, _ viewToAdd: T)->()
func with<T: UIView>(view: T, editSubviewClosure: EditSubviewClosure<T>) -> UIImage {
if let copiedView = view.copyObject() as? T {
UIGraphicsBeginImageContext(size)
let basicSize = CGRect(origin: .zero, size: size)
draw(in: basicSize)
editSubviewClosure(size, copiedView)
copiedView.draw(basicSize)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
return self
}
}
extension UIImageView {
enum ImageAddingMode {
case changeOriginalImage
case addSubview
case addCopiedSubview
}
func drawOnCurrentImage<T: UIView>(view: T, mode: ImageAddingMode, editSubviewClosure: #escaping UIImage.EditSubviewClosure<T>) {
guard let image = image else {
return
}
let addSubView: (T) -> () = { view in
editSubviewClosure(self.frame.size, view)
self.addSubview(view)
}
switch mode {
case .changeOriginalImage:
self.image = image.with(view: view, editSubviewClosure: editSubviewClosure)
case .addSubview:
addSubView(view)
case .addCopiedSubview:
if let copiedView = view.copyObject() as? T {
addSubView(copiedView)
}
}
}
}
/
import UIKit
import PDFKit
class pdfViewController: UIViewController {
#IBOutlet weak var imageview: UIImageView!
let me = ViewController()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func sendbutton(_ sender: Any)
{
}
}
I am trying to display a button on the MainViewController and a UITextField in an ExternalViewController for when the device is connected via HDMI. When a click occurs in the MainViewController, I need to update the UITextField in the ExternalViewController. I can see the prints occur in the output window, but the text field does not update.
MainViewController.swift
import UIKit
import WebKit
class MainViewController: UIViewController {
fileprivate var externalWindow: UIWindow?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if UIScreen.screens.count > 1 {
setupExternalScreen(UIScreen.screens[1])
}
let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
button.backgroundColor = UIColor.blue
button.setTitle("Click Me", for: UIControlState.normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
fileprivate func setupExternalScreen(_ screen: UIScreen) {
guard externalWindow == nil,
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ExternalScreen") as? ExternalViewController else {
return
}
externalWindow = UIWindow(frame: screen.bounds)
externalWindow!.rootViewController = vc
externalWindow!.screen = screen
externalWindow!.isHidden = false
}
func buttonAction(sender: UIButton) {
print("Button tapped")
ExternalViewController().updateLabel()
}
}
ExternalViewController.swift
import UIKit
class ExternalViewController: UIViewController {
let output = UITextField(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 300, height: 100)))
override func viewDidLoad() {
super.viewDidLoad()
self.addTextField()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func addTextField() {
output.textColor = UIColor.black
output.text = "This is the other text field"
view.addSubview(output)
}
func updateLabel() {
print("inside updateLabel")
output.text = "button was clicked"
}
}
This is how it looks like.
This is my first project with Swift, so I apologize if it is a bad question.
Try using NotificationCentre .
In ExternalVC
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(receivedDataFromNotification(notification:)), name: NSNotification.Name(rawValue: "passdata"), object: nil)
}
func receivedDataFromNotification(notification : NSNotification) -> Void {
print(notification.object);
output.text = "button was clicked"
}
In MainViewController
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "passdata"), object: "your string pass here")
While you can use a notification to transfer data between I prefer creating a delegate to transfer the data.
first create a protocol
protocol ExternalViewControllerDelegate: class{
func shouldUpdateLabel(withText text: String)
}
Then update the ExternalViewController appropriately to contain the delegate which a weak reference of course
class ExternalViewController: UIViewController {
weak var delegate: ExternalViewControllerDelegate?
let output = UITextField(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 300, height: 100)))
override func viewDidLoad() {
super.viewDidLoad()
self.addTextField()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func addTextField() {
output.textColor = UIColor.black
output.text = "This is the other text field"
view.addSubview(output)
}
func updateLabel() {
print("inside updateLabel")
output.text = "button was clicked"
delegate?.shouldUpdateLabel(withText: "Your text")
}
}
Remember to call the method in the delegate. I used the updateLabel method in the class to call the method. Which I assume you also want to use
Finally implement the protocol in the MainViewController and remember to set the delegate.
extension MainViewController: ExternalViewControllerDelegate{
func shouldUpdateLabel(withText text: String) {
//Do what you want with the text
}
}
Then update the setupExternalScreen method to set the delegate
func setupExternalScreen(_ screen: UIScreen) {
guard externalWindow == nil,
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ExternalScreen") as? ExternalViewController else {
return
}
vc.delegate = self
externalWindow = UIWindow(frame: screen.bounds)
externalWindow!.rootViewController = vc
externalWindow!.screen = screen
externalWindow!.isHidden = false
}
I have a iOS Swift Project for share and save image. I try to add a long press interaction to save the image. I created the function of interaction, but I do not know how to save the image in Swift.
My code
override func viewDidLoad() {
super.viewDidLoad()
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
self.view.addGestureRecognizer(longPressRecognizer)
}
func longPressed(sender: UILongPressGestureRecognizer) {
println("longpressed")
}
I would like to know how to add image in the library pictures. Thank you in advance for your response.
Use this code
import UIKit
class ViewController: UIViewController {
#IBOutlet var imageview: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageview.userInteractionEnabled = true
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
longPressRecognizer.minimumPressDuration = 0.5
imageview.addGestureRecognizer(longPressRecognizer)
// Do any additional setup after loading the view, typically from a nib.
}
func longPressed(sender: UILongPressGestureRecognizer) {
UIImageWriteToSavedPhotosAlbum(imageview.image, self, "image:didFinishSavingWithError:contextInfo:", nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func image(image: UIImage!, didFinishSavingWithError error: NSError!, contextInfo: AnyObject!) {
if (error != nil) {
// Something wrong happened.
} else {
// Everything is alright.
}
}
}
try this, you should edit your question for saving image displayed in UICollectionViewCell
class ViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
collectionView.addGestureRecognizer(longPressRecognizer)
}
func longPressed(sender: UILongPressGestureRecognizer) {
if (sender.state != .Ended) {
return
}
let point = sender.locationInView(self.collectionView)
let indexPath = self.collectionView.indexPathForItemAtPoint(point)
if (indexPath == nil) {
print("long press on collection view but not on a item")
} else {
let cell = self.collectionView.cellForItemAtIndexPath(indexPath!)
// save image to album
UIImageWriteToSavedPhotosAlbum(cell.imageView.image!, self, "image:didFinishSavingWithError:contextInfo:", nil)
}
}
func image(image: UIImage!, didFinishSavingWithError error: NSError!, contextInfo: AnyObject!) {
if (error != nil) {
// Something wrong happened.
print(error.localizedDescription)
} else {
// Everything is alright.
}
}
}