Reputation: 6820
So I have
let verticalViewOne = UIView()
I want to add the following button to this view
/* Station */
DRN1Button.tintColor = .systemPink
DRN1Button.frame.size = CGSize(width: 200.0, height: 200.0)
DRN1Button.setImage(UIImage(named: "DRN1.jpg"), for: UIControl.State(rawValue: UIControl.State.RawValue(play)))
//playButton.imageView?.contentMode = .scaleAspectFit
DRN1Button.contentVerticalAlignment = .fill
DRN1Button.contentHorizontalAlignment = .fill
DRN1Button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
DRN1Button.addTarget(self, action: #selector(playdrn1), for: .touchUpInside)
DRN1Button.translatesAutoresizingMaskIntoConstraints = false
// self.view.addSubview(playButton)
verticalStackView.addSubview(DRN1Button)
My question is how do I go about this?
as this code
verticalStackView.addSubview(DRN1Button)
brings an error that crashes the app.
NOTE: the button is override func viewDidLoad() {
while the verticalStackView is set in
func setupHierachy(){
view.addSubview(containerStackView)
view.addSubview(verticalStackView)
verticalStackView.addArrangedSubview(verticalViewOne)
//verticalStackView.addArrangedSubview(DRN1Button)
containerStackView.addArrangedSubview(verticalStackView)
}
Error am getting is
Thread 1: Exception: "Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x281f52640 \"UIButton:0x10540ba90.centerY\"> and <NSLayoutYAxisAnchor:0x281f52680 \"UIView:0x10530ea40.centerY\"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal."
full code.
//
// ViewController.swift
// 1life.radio
//
// Created by Russell Harrower on 19/3/20.
// Copyright © 2020 Russell Harrower. All rights reserved.
//
import UIKit
import AVKit
import Network
import Kingfisher
struct Nowplayng: Decodable{
let data: [Data]
}
struct Data: Decodable{
let track: [Trackinfo]
}
struct Trackinfo: Decodable {
let title: String
let artist: String
let imageurl: String
}
class ViewController: UIViewController {
let uuid = UIDevice.current.identifierForVendor?.uuidString
let playButton = UIButton(frame: CGRect(x: 0, y:0, width: 100, height: 100))
let DRN1Button = UIButton(frame: CGRect(x: 0, y:0, width: 100, height: 48))
var play = 0;
var npinfo = "https://api.drn1.com.au/station/1lifeRadio/playing"
var currentstation = "";
var timer = Timer()
/* V VIEWS */
let containerStackView = UIStackView()
let verticalStackView = UIStackView()
let verticalViewOne = UIView()
let verticalViewTwo = UIView()
let verticalViewThree = UIView()
/* END V VIEWS */
var isPlaying = false {
didSet {
self.playButton.setImage(UIImage(systemName: self.isPlaying ? "play.circle" : "pause.circle"), for: UIControl.State(rawValue: UIControl.State.RawValue(play)))
//self.isPlaying ? MusicPlayer.shared.startBackgroundMusic() : MusicPlayer.shared.stopBackgroundMusic()
self.isPlaying ? MusicPlayer.shared.stopBackgroundMusic() : MusicPlayer.shared.startBackgroundMusic(url: currentstation)
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupHierachy()
setlayout()
currentstation = "http://stream.radiomedia.com.au:8015/stream?uuid=\(self.uuid ?? "")"
// Do any additional setup after loading the view.
MusicPlayer.shared.startBackgroundMusic(url: "http://stream.radiomedia.com.au:8015/stream?uuid=\(self.uuid ?? "")")
playButton.tintColor = .systemPink
playButton.frame.size = CGSize(width: 200.0, height: 200.0)
playButton.setImage(UIImage(systemName: "pause.circle"), for: UIControl.State(rawValue: UIControl.State.RawValue(play)))
//playButton.imageView?.contentMode = .scaleAspectFit
playButton.contentVerticalAlignment = .fill
playButton.contentHorizontalAlignment = .fill
playButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
playButton.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
playButton.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(playButton)
//verticalViewOne.addSubview(DRN1Button)
NSLayoutConstraint.activate([
playButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
playButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
playButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -208),
//playButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 12),
//playButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -12),
playButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2),
playButton.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2),
/* DRN1Button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
DRN1Button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
DRN1Button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0),
//playButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 12),
//playButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -12),
DRN1Button.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2),
DRN1Button.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.2)*/
])
self.artist.textAlignment = .center
self.song.textAlignment = .center
nowplaying()
scheduledTimerWithTimeInterval()
}
func setupViews(){
verticalStackView.axis = .vertical
verticalStackView.translatesAutoresizingMaskIntoConstraints = true
verticalStackView.distribution = .fillEqually
verticalViewOne.backgroundColor = .red
containerStackView.backgroundColor = .green
containerStackView.axis = .vertical
containerStackView.spacing = 15
containerStackView.distribution = .fillEqually
}
func setupHierachy(){
view.addSubview(containerStackView)
view.addSubview(verticalStackView)
verticalStackView.addArrangedSubview(verticalViewOne)
//verticalStackView.addArrangedSubview(DRN1Button)
containerStackView.addArrangedSubview(verticalStackView)
}
func setlayout(){
containerStackView.translatesAutoresizingMaskIntoConstraints = false
containerStackView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
containerStackView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2).isActive = true
containerStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
containerStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
}
@objc func appDidLaunch() {
#if targetEnvironment(simulator)
/*
if you don’t set up remote controls, the AVPlayer from
AVPlayerController will immediately create default remote controls
otherwise your simulator will not show the controls.
*/
self.isPlaying = false
self.playButton.setImage(UIImage(systemName: "pause.circle"), for: UIControl.State(rawValue: UIControl.State.RawValue(play)))
MusicPlayer.shared.startBackgroundMusic(url: "http://stream.radiomedia.com.au:8015/stream?uuid=\(uuid ?? "")")
#else
// MusicPlayer.shared.setupRemoteTransportControls()
// more custom controls set up
#endif
}
@objc func playdrn1(sender:UIButton!){
currentstation = "http://stream.radiomedia.com.au:8003/stream?uuid=\(uuid ?? "")"
MusicPlayer.shared.startBackgroundMusic(url: "http://stream.radiomedia.com.au:8003/stream?uuid=\(uuid ?? "")")
npinfo = "https://api.drn1.com.au/station/DRN1/playing"
}
@objc func buttonAction(sender: UIButton!) {
print(self.isPlaying)
self.isPlaying = !self.isPlaying
}
@IBOutlet var imageurl: UIImageView!
@IBOutlet var artist: UILabel!
@IBOutlet var song: UILabel!
func scheduledTimerWithTimeInterval(){
// Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds
timer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.nowplaying), userInfo: nil, repeats: true)
}
@objc func nowplaying(){
let jsonURLString = npinfo
guard let feedurl = URL(string: jsonURLString) else { return }
URLSession.shared.dataTask(with: feedurl) { (data,response,err)
in
guard let data = data else { return }
do{
let nowplaying = try JSONDecoder().decode(Nowplayng.self, from: data)
//print(nowplaying.data.first?.track.first?.artist as Any)
nowplaying.data.forEach {_ in
DispatchQueue.main.async {
self.artist.text = nowplaying.data.first?.track.first?.artist
self.song.text = nowplaying.data.first?.track.first?.title
}
if var strUrl = nowplaying.data.first?.track.first?.imageurl {
strUrl = strUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
DispatchQueue.main.sync {
let processor = DownsamplingImageProcessor(size: self.imageurl.bounds.size)
|> RoundCornerImageProcessor(cornerRadius: 20)
self.imageurl.kf.indicatorType = .activity
self.imageurl.kf.setImage(
with: URL(string: strUrl),
placeholder: UIImage(named: "placeholderImage"),
options: [
.processor(processor),
.scaleFactor(UIScreen.main.scale),
.transition(.fade(1)),
.cacheSerializer(FormatIndicatedCacheSerializer.png),
.cacheOriginalImage
])
{
result in
switch result {
case .success(let value):
print("Task done for: \(value.source.url?.absoluteString ?? "")")
case .failure(let error):
print("Job failed: \(error.localizedDescription)")
}
}
}
// self.imageurl.kf.setImage(with: URL(string: strUrl), placeholder: nil)
//MusicPlayer.shared.nowplaying(artist: $0.track.artist, song: $0.track.title, cover:strUrl)
// MusicPlayer.shared.getArtBoard(artist: $0.track.artist, song: $0.track.title, cover:strUrl)
}
}
}catch let jsonErr{
print("error json ", jsonErr)
}
}.resume()
}
}
Upvotes: 1
Views: 574
Reputation: 13300
First off, the line:
verticalStackView.addSubview(DRN1Button)
crashes because you are attempting to add a subview to stackView, you're supposed to do addArrangedSubview
.
For the crash:
Thread 1: Exception: "Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x281f52640 "UIButton:0x10540ba90.centerY"> and <NSLayoutYAxisAnchor:0x281f52680 "UIView:0x10530ea40.centerY"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal."
You have it already.
DRN1Button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
Your DRN1Button
has no common ancestor with your self.view
. This can mean that you haven't added your DRN1Button
to a view, or most probably the line above, can't be done. While your button is in a stackview but you are setting its centerYAnchor
equal to your self.view
.
Upvotes: 2