I have an ImageView inside of a ScrollView.
Each time the user clicks on a point on the image a pin is set and the coordinates are printed out.
However, I'm trying to store multiple coordinates inside of an array.
The first 3 times the user clicks on the image, I need the coordinates to store inside refs1. The next 14-20 times inside spots1.
// MARK: - Outlets
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var sharkImage: UIImageView!
// MARK: - Properties
var refs1 :[Double] = []
var spots1 :[Double] = []
// MARK: - View Did Load
override func viewDidLoad() {
super.viewDidLoad()
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 6.0
scrollView.delegate = self
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapAction))
self.sharkImage.isUserInteractionEnabled = true
self.sharkImage.addGestureRecognizer(tapGestureRecognizer)
}
// MARK: - Scroll View
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return sharkImage
}
// MARK: - Functions
func tapAction(sender: UITapGestureRecognizer) {
// Get points for the UIImageView
let touchPoint = sender.location(in: self.sharkImage)
print(touchPoint)
// Add pin to tap
let pin = UIImageView(frame: CGRect(x: touchPoint.x - 5, y: touchPoint.y - 5, width:10, height:10))
pin.image = UIImage(named: "photo-pin-red")
sharkImage.addSubview(pin)
}
Well first of all you could store the coordinates in a 2D array if you want to:
var refs1 :[[Double]] = []
var spots1 :[[Double]] = []
Then store a global variable called counter to keep track of the click count:
var counter = 0
And then in your tapAction do the following (see comments for descriptions):
func tapAction(sender: UITapGestureRecognizer) {
// increase counter with +1 for each click
counter += 1
if counter <= 3 { // first 3
refs1.append([Double(touchPoint.x), Double(touchPoint.y)])
} else if counter <= 23 { // next 14 - 20 clicks
counter = 0 // reset counter to start over again
spots1.append([Double(touchPoint.x), Double(touchPoint.y)])
}
}
Use a counter variable:
var count = 0
func tapAction(sender: UITapGestureRecognizer) {
count = conut + 1
// Check for count
if (count >= 14) {
// Do stuff
}
// Get points for the UIImageView
let touchPoint = sender.location(in: self.sharkImage)
print(touchPoint)
// Add pin to tap
let pin = UIImageView(frame: CGRect(x: touchPoint.x - 5, y: touchPoint.y - 5, width:10, height:10))
pin.image = UIImage(named: "photo-pin-red")
sharkImage.addSubview(pin)
}
Related
I'm trying to update text of a label after a scroll event. I have a print command that prints the correct value but the label is not updating.
Here's my code
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)") // this prints correct value
self.signalLabel.text = signalText[Int(x/w)] // this does not update
}
what's the deal?
Here's the complete view controller code. This view is called from a button click on the initial view controller. This view contains a UIScrollView and UIPageControl. The UIScrollView contains two images that can be scrolled back and forth. I want to update the label text based on image that is shown.
import UIKit
class SignalOneViewController: UIViewController, UIScrollViewDelegate {
// MARK: Properties
#IBOutlet weak var signalScrollView: UIScrollView!
#IBOutlet weak var signalPageControl: UIPageControl!
#IBOutlet weak var signalLabel: UILabel!
// MARK: - Button Actions
#IBAction func signalOneButton(_ sender: Any) {
print("signal one button clicked")
performSegue(withIdentifier: "SignalOneSegue", sender: self)
}
#IBAction func onCancelButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
let signalImages = ["signal1a.png", "signal1b.png"]
let signalText = ["Ready for play", "Untimed down"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidLayoutSubviews() {
self.loadScrollView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadScrollView() {
let pageCount : CGFloat = CGFloat(signalImages.count)
signalLabel.text = signalText[0]
signalScrollView.backgroundColor = UIColor.clear
signalScrollView.delegate = self
signalScrollView.isPagingEnabled = true
signalScrollView.contentSize = CGSize(width: signalScrollView.frame.size.width * pageCount, height: signalScrollView.frame.size.height)
signalScrollView.showsHorizontalScrollIndicator = false
signalScrollView.showsVerticalScrollIndicator = false
signalPageControl.numberOfPages = Int(pageCount)
signalPageControl.pageIndicatorTintColor = UIColor.lightGray
signalPageControl.currentPageIndicatorTintColor = UIColor.blue
signalPageControl.addTarget(self, action: #selector(self.pageChanged), for: .valueChanged)
for i in 0..<Int(pageCount) {
print(self.signalScrollView.frame.size.width)
let image = UIImageView(frame: CGRect(x: self.signalScrollView.frame.size.width * CGFloat(i), y: 0, width: self.signalScrollView.frame.size.width, height: self.signalScrollView.frame.size.height))
image.image = UIImage(named: signalImages[i])!
image.contentMode = UIViewContentMode.scaleAspectFit
self.signalScrollView.addSubview(image)
}
}
//MARK: UIScrollView Delegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let viewWidth: CGFloat = scrollView.frame.size.width
// content offset - tells by how much the scroll view has scrolled.
let pageNumber = floor((scrollView.contentOffset.x - viewWidth / 50) / viewWidth) + 1
signalPageControl.currentPage = Int(pageNumber)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)")
self.signalLabel.text = signalText[p]
print(">>> \(signalText[Int(x/w)])")
}
//MARK: page tag action
#objc func pageChanged() {
let pageNumber = signalPageControl.currentPage
var frame = signalScrollView.frame
frame.origin.x = frame.size.width * CGFloat(pageNumber)
frame.origin.y = 0
signalScrollView.scrollRectToVisible(frame, animated: true)
}
}
Make sure signalLabe IBOutlet is attached to your label in storyboard or xib
I have an array of images if I pressed the button the image will randomly appear. and there is an image down also called from the array but it appears randomly just once I opened the game. I want to do a conditions statement for button pressed. like I have 5 conditions once the button clicked: 1- if pressed and the image appeared is not same as the UIIMage view down score will be added
2- if button did not press for 2 seconds will appear down.
3- if button pressed and it is same as the UIimage so game over.
4- If he calculated 4 images down because he didn't hit the image in 2 seconds he will lose.
var array:[UIImage] = [UIImage(named: "1.png")!,
UIImage(named: "2.png")!,
UIImage(named: "3.png")!,
UIImage(named: "4.png")!,
UIImage(named: "5.png")!,
UIImage(named: "6.png")!,
UIImage(named: "7.png")!,
UIImage(named: "8.png")!,
UIImage(named: "9.png")!,
UIImage(named: "10.png")!]
var random = arc4random_uniform(10)
#IBAction func myButtonPressed(button: UIButton) {
var randomNum: UInt32 = 10
randomNum = arc4random_uniform(UInt32(array.count))
myButton.setImage(UIImage(named: "bird\(randomNum).png"), for: UIControlState.normal)
// myButton.setImage(UIImage(named: "\(randomNum).png"), for: UI)
self.myImage.animationImages = array
let buttonWidth = myButton.frame.width
let buttonHeight = myButton.frame.height
// Find the width and height of the enclosing view
let viewWidth = myButton.superview!.bounds.width
let viewHeight = myButton.superview!.bounds.height
// Compute width and height of the area to contain the button's center
let xwidth = viewWidth - buttonWidth
let yheight = viewHeight - buttonHeight
// Generate a random x and y offset
let xoffset = CGFloat(arc4random_uniform(UInt32(xwidth)))
let yoffset = CGFloat(arc4random_uniform(UInt32(yheight)))
// Offset the button's center by the random offsets.
myButton.center.x = xoffset + buttonWidth / 2
myButton.center.y = yoffset + buttonHeight / 2
/* for i in array{
if myButton != myImage{
randomNum = arc4random_uniform(UInt32(array.count))
}
if else
} */
}
Perhaps you could try something like this. As for your first condition, what is your UIImage View Variable. Is it another UIImage View that is being displayed on the storyboard?
import UIKit
class ViewController: UIViewController {
var array: [UIImage] = [UIImage(named: "1.png")!,
UIImage(named: "2.png")!,
UIImage(named: "3.png")!,
UIImage(named: "4.png")!,
UIImage(named: "5.png")!]
#IBOutlet weak var myButton: UIButton!
var pressed: Bool = false;
var score: Int = 0;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//2nd Condition: if button did not press for 2 seconds will appear down
if(pressed == false){
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(ViewController.doSomething), userInfo: nil, repeats: true)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func isPressed(_ sender: UIButton) {
pressed = true;
var randomNum: UInt32 = 10
randomNum = arc4random_uniform(UInt32(array.count));
myButton.setImage(UIImage(named: "\(randomNum).png"), for: .normal)
// 1st Condition: if pressed and the image appeared is not same as the UIIMage view down score will be added
if( UIImage(named: "\(randomNum).png") != myButton.currentImage){
//Add View Down Score
score += 1;
}
// 3rd Condition: if button pressed and it is same as the UIimage so game over
else{
// Game Over
}
}
func doSomething() {
// Not sure what you mean by will appear down
print("Action")
}
}
I am not quite sure what your 4th condition does. Please clarify
Intro:
Functionality of adding multiple stickers/emoji to a view.
Setup:
There are 2 view controllers - one to which we're adding stickers, and another with a collectionview of stickers.
Stickers themselves are passed in arrays in 'prepareForSegue' func.
There are 2 arrays, one with just sticker images, another - with UIImageViews - stickers that were already panned, pinched and rotated.
Bug:
After adding 2nd sticker, the AddingStickersVC reappears but previous sticker isn't where we left if. It is pinched and zoomed, but not panned. Also new stickers are sticked to the first one (same frame?).
We can pinch and zoom previous stickers separately from new ones - (nope, they have their own frames), but we can't separate them.
End up having a stack of UIImageViews that takes rotating and pinching separately but pans all together.
Also, speed of panning is increasing after each additional sticker (the panning gesture is added multiple time?).
Hierarchy of views
Stickers are added to 'viewForEmoji' view (viewForImgAndEmoji).
AddingStickersVC:
#IBOutlet weak var viewForImgAndEmoji: UIView!
#IBOutlet weak var mainImg: UIImageView!
#IBOutlet weak var viewForSnapshot: UIView!
var imageData: Data!
var imageItself: UIImage!
var currentUserPostRef: FIRDatabaseReference!
var emojiImage: UIImage!
var geoFire: GeoFire!
var arrayOfEmojis = [UIImage]()
var arrayOfEmojiViews = [UIImageView]()
var n:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
if imageData != nil {
let img = UIImage(data: imageData)
let fixedImg = img!.fixOrientation(img: img!)
mainImg.image = fixedImg
} else if imageItself != nil {
mainImg.image = imageItself
}
if arrayOfEmojiViews.count != 0 {
for emojiView1 in arrayOfEmojiViews {
viewForImgAndEmoji.addSubview(emojiView1)
}
}
// get image out of array.
if arrayOfEmojis.count != 0 {
for emoji in arrayOfEmojis {
let emojiView = UIImageView(image: emoji)
emojiView.tag = n
emojiView.frame = CGRect(x: 153, y: 299, width: 70, height: 70)
emojiView.isUserInteractionEnabled = true
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:)))
pan.delegate = self
viewForImgAndEmoji.addGestureRecognizer(pan)
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.handlePinch(recognizer:)))
pinch.delegate = self
viewForImgAndEmoji.addGestureRecognizer(pinch)
let rotate = UIRotationGestureRecognizer(target: self, action: #selector(self.handleRotate(recognizer:)))
rotate.delegate = self
viewForImgAndEmoji.addGestureRecognizer(rotate)
// check so we won't add previous emoji. only new.
if viewForImgAndEmoji.viewWithTag(n) == nil {
viewForImgAndEmoji.addSubview(emojiView)
}
n += 1
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if arrayOfEmojis.count != 0 {
for j in 1...n {
if var view1 = self.viewForImgAndEmoji.viewWithTag(j) as? UIImageView {
arrayOfEmojiViews.append(view1)
print("Zhenya: views frame is \(view1.frame)")
}
}
}
if segue.identifier == "EmojiCollectionVC" {
if let emojiCollection = segue.destination as? EmojiCollectionVC{
if let image = sender as? UIImage {
emojiCollection.userImage = image
if arrayOfEmojis.count != 0 {
//arrayToStoreEmojis
emojiCollection.arrayToStoreEmojis = arrayOfEmojis
emojiCollection.arrayToStoreEmojiViews = arrayOfEmojiViews
}
}
}
}
}
#IBAction func handlePan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.viewForImgAndEmoji)
if let view = recognizer.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
recognizer.setTranslation(CGPoint.zero, in: self.viewForImgAndEmoji)
}
#IBAction func handlePinch(recognizer: UIPinchGestureRecognizer) {
let pinchPoint = recognizer.location(in: viewForImgAndEmoji)
let ourEmojiView = viewForImgAndEmoji.hitTest(pinchPoint, with: nil)
ourEmojiView!.transform = ourEmojiView!.transform.scaledBy(x: recognizer.scale, y: recognizer.scale)
recognizer.scale = 1
}
#IBAction func handleRotate(recognizer: UIRotationGestureRecognizer){
let rotatePoint = recognizer.location(in: viewForImgAndEmoji)
let ourEmojiView = viewForImgAndEmoji.hitTest(rotatePoint, with: nil)
ourEmojiView!.transform = ourEmojiView!.transform.rotated(by: recognizer.rotation)
recognizer.rotation = 0
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
And EmojiCollectionVC:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! EmojiCollectionCell
let chosenEmoji = cell.emojiView.image as UIImage!
arrayToStoreEmojis.append(chosenEmoji!)
performSegue(withIdentifier: "backToEmojiVC", sender: arrayToStoreEmojis)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "backToEmojiVC"{
if let destinationVC = segue.destination as? EmojiVC {
if let array = sender as? [UIImage] {
destinationVC.arrayOfEmojis = arrayToStoreEmojis
destinationVC.arrayOfEmojiViews = arrayToStoreEmojiViews
let data = UIImagePNGRepresentation(userImage)
destinationVC.imageData = data
}
}
}
}
Found solution.
There reason why all new imageViews were stacked - because after panning imageViews didn't change their location in view. The whole f view was moving.
(to find this, spent 8hours tracking changes of frame origins with 'prints' at every step of the program).
And the reason the whole view was moving - because panning gesture was added to the whole view.
So instead of
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:)))
pan.delegate = self
viewForImgAndEmoji.addGestureRecognizer(pan)
i needed:
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:)))
pan.delegate = self
emojiView.addGestureRecognizer(pan)
What is interesting, for pinching and rotating - we still add them to the whole view that contains emojiView:
viewForImgAndEmoji.addGestureRecognizer(pinch)
...
viewForImgAndEmoji.addGestureRecognizer(rotate)
I have a UIScrollView setup but when I change view the music doesn't stop. How do I make it so the music stops when you change view?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated)
meditationState = .on
setTrackForPlayerWith(trackName: "Bigsur")
player.play()
player.numberOfLoops = -1
}
Here is the whole class from viewcontroller.swift. I've added the func scrollViewDidScroll and the self part that you mentioned but it's still not working.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let vc0 = ViewController0(nibName: "ViewController0", bundle: nil)
var frame0 = vc0.view.frame
frame0.origin.x = self.view.frame.size.width
vc0.view.frame = frame0
self.addChildViewController(vc0)
self.scrollView.addSubview(vc0.view)
vc0.didMove(toParentViewController: self)
let vc1 = ViewController1(nibName: "ViewController1", bundle: nil)
var frame1 = vc1.view.frame
frame1.origin.x = self.view.frame.size.width
vc1.view.frame = frame1
self.addChildViewController(vc1)
self.scrollView.addSubview(vc1.view)
vc1.didMove(toParentViewController: self)
let vc2 = ViewController2(nibName: "ViewController2", bundle: nil)
var frame2 = vc2.view.frame
frame2.origin.x = self.view.frame.size.width * 2
vc2.view.frame = frame2
self.addChildViewController(vc2)
self.scrollView.addSubview(vc2.view)
vc2.didMove(toParentViewController: self)
let vc3 = ViewController3(nibName: "ViewController3", bundle: nil)
var frame3 = vc3.view.frame
frame3.origin.x = self.view.frame.size.width * 3
vc1.view.frame = frame3
self.addChildViewController(vc3)
self.scrollView.addSubview(vc3.view)
vc3.didMove(toParentViewController: self)
self.scrollView.contentSize = CGSize(width: Double(self.view.frame.size.width * 4), height: Double(self.view.frame.size.height - 66))
self.scrollView.delegate = self
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.x > self.view.frame.size.x {
player.stop()
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ViewController3 where 'player' is declared:
import UIKit
import AVFoundation
enum MeditationState {
case on
case off
}
class ViewController3: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
var player1:AVAudioPlayer = AVAudioPlayer()
var meditationState: MeditationState?
var replicatorLayer = CAReplicatorLayer()
var dot = CALayer()
func updateTimer(){
seconds += 1
timerclock.text = "\(seconds)"
}
// Animation starts running
func animation2() {
// A layer that creates a specified number of copies of its sublayers (the source layer), each copy potentially having geometric, temporal, and color transformations applied to it.
replicatorLayer = CAReplicatorLayer()
// The layer’s bounds rectangle. Animatable.
replicatorLayer.bounds = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0)
// The radius to use when drawing rounded corners for the layer’s background. Animatable.
replicatorLayer.cornerRadius = 10.0
// The background color of the receiver. Animatable.
replicatorLayer.backgroundColor = UIColor(white: 0.0, alpha: 0.0).cgColor
// The layer’s position in its superlayer’s coordinate space. Animatable.
replicatorLayer.position = view.center
// calling this method creates an array for that property and adds the specified layer to it.
view.layer.addSublayer(replicatorLayer)
// connectng the animation to the content
// An object that manages image-based content and allows you to perform animations on that content
dot = CALayer()
// The layer’s bounds rectangle. Animatable.
dot.bounds = CGRect(x: 0.0, y: 0.0, width: 12.0, height: 12.0)
//The layer’s position in its superlayer’s coordinate space. Animatable.
dot.position = CGPoint(x: 150.0, y: 40.0)
//The background color of the receiver. Animatable.
dot.backgroundColor = UIColor(white: 0.2, alpha: 1.0).cgColor
// The color of the layer’s border. Animatable.
dot.borderColor = UIColor(white: 1.0, alpha: 1.0).cgColor
// The width of the layer’s border. Animatable.
dot.borderWidth = 1.0
//The radius to use when drawing rounded corners for the layer’s background. Animatable.
dot.cornerRadius = 5.0
//Appends the layer to the layer’s list of sublayers.
replicatorLayer.addSublayer(dot)
// number of copies of layer is instanceCount
let nrDots: Int = 1000
//The number of copies to create, including the source layers.
replicatorLayer.instanceCount = nrDots
// The basic type for floating-point scalar values in Core Graphics and related frameworks.
let angle = CGFloat(2*M_PI) / CGFloat(nrDots)
// The transform matrix applied to the previous instance to produce the current instance. Animatable.
replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0.0, 0.0, 1.0)
// Type used to represent elapsed time in seconds.
let duration: CFTimeInterval = 10.0
// animation capabilities for a layer property.
// An object that provides basic, single-keyframe animation capabilities for a layer property.
let shrink = CABasicAnimation(keyPath: "transform.scale")
// Defines the value the receiver uses to start interpolation.
shrink.fromValue = 1.0
// Defines the value the receiver uses to end interpolation.
shrink.toValue = 0.1
// Specifies the basic duration of the animation, in seconds.
shrink.duration = duration
// Determines the number of times the animation will repeat.
shrink.repeatCount = Float.infinity
// Add the specified animation object to the layer’s render tree.
dot.add(shrink, forKey: "shrink")
// Specifies the delay, in seconds, between replicated copies. Animatable.
replicatorLayer.instanceDelay = duration/Double(nrDots)
// The transform applied to the layer’s contents. Animatable.
dot.transform = CATransform3DMakeScale(0.01, 0.01, 0.01)
}
// connecting the breathe in label
#IBOutlet weak var label: UILabel!
// instant delay
#IBOutlet weak var instantDelay: UIButton!
#IBAction func delayBtn(_ sender: Any) {
dot.removeAnimation(forKey: "shrink")
timer1.invalidate()
seconds = 0
timer2.invalidate()
timerclock.text = "\(seconds)"
time = 0
timerLabel.text = "Breathe in"
timerisOn = false
pauseBtn.isHidden = true
playBtn.isHidden = false
label.isHidden = true
replicatorLayer.isHidden = true
instantDelay.isHidden = true
instantDelay1.isHidden = false
slider.isHidden = false
}
// Delay 1
#IBOutlet weak var instantDelay1: UIButton!
#IBAction func delayBtn1(_ sender: Any) {
instantDelay1.isHidden = true
instantDelay.isHidden = false
label.isHidden = false
slider.isHidden = true
}
//Slider for changing animation speed
#IBOutlet weak var slider: UISlider!
#IBAction func slider(_ sender: Any) {
}
#IBAction func speed(_ sender: UISlider) {
view.layer.speed = sender.value
}
//Sound On button
#IBOutlet weak var soundOn: UIButton!
#IBAction func SoundOn(_ sender: Any) {
meditationState = .on
setTrackForPlayerWith(trackName: "Mute")
player.play()
soundoff.isHidden = false
soundOn.isHidden = true
}
//Sound Off button
#IBOutlet weak var soundoff: UIButton!
#IBAction func SoundOff(_ sender: Any) {
meditationState = .off
setTrackForPlayerWith(trackName: "Bigsur")
player.play()
soundoff.isHidden = true
soundOn.isHidden = false
}
//Timerclock at top of screen label
#IBOutlet weak var timerclock: UILabel!
// creating vars to set things
var animation = CFTimeInterval()
var timer1 = Timer()
var timer2 = Timer()
var time = 0
var seconds = 0
var timerisOn = false
// connecting breathe in label
#IBOutlet var question: UILabel!
var arrayOfStrings: [String] = [""]
// connecting timerclick and starting it
#IBOutlet var timerLabel: UILabel!
// changes the amount of time on the label of different labels
func increaseTimer() {
time += 1
switch time {
case 0 ... 7:
timerLabel.text = "Hold"
case 8 ... 10:
timerLabel.text = "Breathe Out"
case 11 ... 12:
timerLabel.text = "Breathe in"
default:
time = 0
}
}
// connecting the play button and vars
#IBOutlet weak var playBtn: UIButton!
#IBAction func play(sender: AnyObject) {
bell(trackName: "Bell")
player1.play()
timer1 = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController3.increaseTimer), userInfo: nil, repeats: true)
pauseBtn.isHidden = false
playBtn.isHidden = true
if timerisOn == false {
timer2 = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
timerisOn = true
}
animation2()
}
// pausing the timer with the vars
#IBOutlet weak var pauseBtn: UIButton!
#IBAction func pause(sender: AnyObject) {
dot.removeAnimation(forKey: "shrink")
timer1.invalidate()
seconds = 0
timer2.invalidate()
timerclock.text = "\(seconds)"
time = 0
timerLabel.text = "Breathe in"
timerisOn = false
pauseBtn.isHidden = true
playBtn.isHidden = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear( animated)
meditationState = .on
setTrackForPlayerWith(trackName: "Bigsur")
player.play()
player.numberOfLoops = -1
}
override func viewDidLoad() {
super.viewDidLoad()
time += 1
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
print("AVAudioSession Category Playback OK")
do {
try AVAudioSession.sharedInstance().setActive(true)
print("AVAudioSession is Active")
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
func setTrackForPlayerWith(trackName: String) {
do
{
let audioPath = Bundle.main.path(forResource: trackName, ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//ERROR
}
}
func bell(trackName: String) {
do
{
let audioPath = Bundle.main.path(forResource: trackName, ofType: "mp3")
try player1 = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//ERROR
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Are you looking for viewWillDisappear(_:)? In that method you can just add player.stop() to stop the music when you change views.
The smartass way to do this is just ....
let's say it's a vertical table.
1. Each table view cell has an audio track associated with it. Think of one particular cell - C - it has an audio track A.
2. As the view scrolls (ie, whenever it is moving), just get the frame of C
3. Just take the height. Then take the height of the screen SH. Then get the distance of C from the center of the screen .. so Abs(SH - H). Then just get that figure as a fraction (zero to one) of the SH. So, Abs(SH - H)/H
(Depending on your situation, it may be better if that is divided by the height of cells, rather than screen height.)
4. Now ... simply set the volume of all the audio track A, to that fraction. And in fact, simply do that for every cell.
As you scroll, the audio will mix between the various tracks.
"Magic" :)
You can observe the changes made in your UIScrollView subclass in various delegate methods.
First of all, lets make sure your scrollView's delegate is assigned to the viewController. To do so, one option is to add following to viewDidLoad()
// `scrollView` should be whatever is your scrollView called in your VC
self.scrollView.delegate = self
Once this is done, lets make your UIViewController subclass conform to UIScrollViewDelegate
class ViewController: UIViewController, UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.x > self.view.frame.size.x {
player.stop()
}
}
}
UIScrollViewDelegate has numerous methods to observe changes in your scrollView. scrollViewDidScroll(_:) will be called every time there is an interaction with the scrollView, so as soon as the contentOffset is greater than the width of the view, lets stop the music.
Why my current page in Page Control does not show correct output?
Page 1 and Page 2 display in one dot? Images here:
http://i.stack.imgur.com/498ap.png, http://i.stack.imgur.com/41kdg.png
Last page is page 6 display in dot 5th, doesn't last dot? Image: http://i.stack.imgur.com/NP9u1.png
My code here:
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
let totalPages = 6
let sampleBGColors: Array<UIColor> = [UIColor.redColor(), UIColor.yellowColor(), UIColor.greenColor(), UIColor.magentaColor(), UIColor.orangeColor(), UIColor.lightGrayColor()] #IBOutlet weak var scrollView: UIScrollView!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
configureScrollView()
configurePageControl()
}
func configureScrollView() {
// Enable paging.
scrollView.pagingEnabled = true
// Set the following flag values.
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.scrollsToTop = false
// Set the scrollview content size.
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(totalPages), scrollView.frame.size.height)
// Set self as the delegate of the scrollview.
scrollView.delegate = self
// Load the TestView view from the TestView.xib file and configure it properly.
for i in 0 ..< totalPages {
// Load the TestView view.
let testView = NSBundle.mainBundle().loadNibNamed("TestView", owner: self, options: nil)[0] as! UIView
// Set its frame and the background color.
testView.frame = CGRectMake(CGFloat(i) * scrollView.frame.size.width, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height)
testView.backgroundColor = sampleBGColors[i]
// Set the proper message to the test view's label.
let label = testView.viewWithTag(1) as! UILabel
label.text = "Page #\(i + 1)"
// Add the test view as a subview to the scrollview.
scrollView.addSubview(testView)
}
}
func configurePageControl() {
// Set the total pages to the page control.
pageControl.numberOfPages = totalPages
// Set the initial page.
pageControl.currentPage = 0
}
// MARK: UIScrollViewDelegate method implementation
func scrollViewDidScroll(scrollView: UIScrollView) {
// Calculate the new page index depending on the content offset.
let currentPage = floor(scrollView.contentOffset.x / UIScreen.mainScreen().bounds.size.width);
// Set the new page index to the page control.
pageControl.currentPage = Int(currentPage)
}
// MARK: IBAction method implementation
#IBAction func changePage(sender: AnyObject) {
// Calculate the frame that should scroll to based on the page control current page.
var newFrame = scrollView.frame
newFrame.origin.x = newFrame.size.width * CGFloat(pageControl.currentPage)
scrollView.scrollRectToVisible(newFrame, animated: true)
}
Please help me! Thank you.
Sorry for my English is bad.
Change the pageControl.currentPage in UIScrollViewDelegate's implemention scrollViewDidEndScrollingAnimation and scrollViewDidEndDecelerating, and I improved the calculation with scrollView's width, not screen's width:
// MARK: UIScrollViewDelegate method implementation
func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
// Calculate the new page index depending on the content offset.
let currentPage = floor(scrollView.contentOffset.x / scrollView.bounds.size.width)
// Set the new page index to the page control.
pageControl.currentPage = Int(currentPage)
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
scrollViewDidEndScrollingAnimation(scrollView)
}