RussellHarrower
RussellHarrower

Reputation: 6820

How to add a button a UIView()

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

Answers (1)

Glenn Posadas
Glenn Posadas

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

Related Questions