Delegate events not called for custom view class in iOS - ios

I'm trying to play a youtube video using
Swift-Youtube-Player
and I'm currently having trouble with the delegate methods not being called.
I have created an outlet from IB to this player, but I couldn't drag the delegate to the view controller from IB for some reason so I tried to do it in code.
This is what I tried:
#IBOutlet weak var youtubePlayer: YouTubePlayerView!
var _currentYoutubeId: String = "";
override func viewDidLoad() {
super.viewDidLoad()
print(_currentYoutubeId)
youtubePlayer.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func playerReady(videoPlayer: YouTubePlayerView) {
print(videoPlayer)
if youtubePlayer.ready {
youtubePlayer.playerVars = [
"playsinline": "1",
"controls": "0",
"showinfo": "0"
]
youtubePlayer.loadVideoID(_currentYoutubeId)
if youtubePlayer.playerState != YouTubePlayerState.Playing {
youtubePlayer.play()
} else {
youtubePlayer.pause()
}
}
}
func playerStateChanged(videoPlayer: YouTubePlayerView, playerState: YouTubePlayerState) {
print("promjena")
}
func playerQualityChanged(videoPlayer: YouTubePlayerView, playbackQuality: YouTubePlaybackQuality) {
print("promjena")
}
I'm doing this in the newest XCode versions and I'm very new to iOS, Swift and everything Apple related.
Concretely, my question is how to connect this delegate to the player so that its lifecycle methods are called?
EDIT: I have previously managed to this with UICollectionViewDelegate, but I haven't succeded with this custom view.

this is the way I use Swift-Youtube-Player.
class videoController: UIViewController, YouTubePlayerDelegate {
#IBOutlet var videoPlayer: YouTubePlayerView!
var videoID: String?
override func viewDidLoad() {
super.viewDidLoad()
videoPlayer.delegate = self
if let videoID = self.videoID {
videoPlayer.loadVideoID(videoID)
}
}
func playerReady(videoPlayer: YouTubePlayerView) {
videoPlayer.play()
}
func playerStateChanged(videoPlayer: YouTubePlayerView, playerState: YouTubePlayerState) {
if videoPlayer.playerState == YouTubePlayerState.Ended || videoPlayer.playerState == YouTubePlayerState.Paused {
//Your code here
}
}
func playerQualityChanged(videoPlayer: YouTubePlayerView, playbackQuality: YouTubePlaybackQuality) {
//Your code here
}
}

Related

How to handle a connected bluetooth keyboard's operations in Swift 3?

My IOS app need to handle a connected bluetooth keyboard to do some function in the app, I tried this method, but the xcode cannot found the Cocoa
Then I tried this method, this time xcode cannot find the canBecomeFirstResponder in super class.
How can I capture keyboard event in my app?
import UIKit
class ViewController: UIViewController {
var keys = [UIKeyCommand]()
override func viewDidLoad() {
super.viewDidLoad()
for digit in "1234567890abcdefghijklmnopqrstuvwxyz"
{
keys.append(UIKeyCommand(input: String(digit), modifierFlags: [], action: Selector(("keyPressed:"))))
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override var keyCommands: [AnyObject]? {
get {
return keys
}
}
func keyPressed(command: UIKeyCommand) {
print("user pressed \(command.input)")
}
}

How can swift closure reference properties of class its running from?

I have the following 2 controllers listed below. I'm using delegation to try and create a progressWindow which will run code and print it nicely but where the code is arbitrary.
The closures are defined by the class conforming to the protocol (in my case SyncViewController), but I want to change the UI of the progressWindowViewController from SyncViewControllers codeToRun {} closure. How do I do this?
SyncViewController.swift
import UIKit
class SyncViewController: UIViewController, progressWindowDelegate {
var codeToRun = {
//(self as! ProgressWindowViewController).theTextView.text = "changed the text"
print("code to run")
}
var codeToCancel = {print("code to cancel")}
var titleToGive = "Starting Sync..."
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func yesSyncButtonAction(sender: UIButton) {
//Segue to the ProgressWindowViewController...
}
#IBAction func noSyncActionButton(sender: UIButton) {
tabBarController?.selectedIndex = 1 //assume back to inventory section
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "SyncToProgressSegue"){
let progressWindow = segue.destinationViewController as! ProgressWindowViewController
progressWindow.controllerDelegate = self //sets the delegate so we have reference to this window still.
}
}
}
ProgressWindowViewController.swift
import UIKit
protocol progressWindowDelegate{
var titleToGive : String {get}
var codeToRun : ()->() {get}
var codeToCancel : ()->() {get}
}
class ProgressWindowViewController: UIViewController {
#IBOutlet weak var theTextView: UITextView!
#IBOutlet weak var theProgressBar: UIProgressView!
#IBOutlet weak var navItemLabel: UINavigationItem!
//Sets delegate
var controllerDelegate:progressWindowDelegate!
override func viewDidLoad() {
super.viewDidLoad()
navItemLabel.title! = controllerDelegate.titleToGive
dispatch_async(dispatch_get_main_queue(),{
self.controllerDelegate.codeToRun() //Will run code accordingly.
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func cancelNavItemButtonAction(sender: UIBarButtonItem) {
dispatch_async(dispatch_get_main_queue(),{
self.controllerDelegate.codeToCancel()
})
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
An example of how his might be used is downloading thousands of inventory records with images, which would print the inventory details as it grabs them into the progressWindow.
But this progressWindow could also be used for other large/small tasks that need to print particular stuff into the progressWindow textarea (like logging in and therefore coming from a different view controller than sync in my example). The idea is to make it a dynamic class.
Instead of creating a variable, just use a function/method?
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_main_queue(),{
self.controllerDelegate?.codeToRun(self)
})
}
.
protocol progressWindowDelegate : class {
var titleToGive : String {get}
func codeToRun(progressWindowViewController:ProgressWindowViewController)
var codeToCancel : ()->() {get}
}
class SyncViewController: UIViewController, progressWindowDelegate {
func codeToRun(progressWindowViewController:ProgressWindowViewController) {
print("code to run")
}
Also make delegate weak and optional:
delegate weak var controllerDelegate:progressWindowDelegate? = nil

ViewControllerApple.Apple.Type does not have a member named appleQuantity

I have a UITextField named 'appleQuantity', when I try to convert it to an int to do math with it, it gives me an error named 'ViewControllerApple.Apple.Type does not have a member named appleQuantity'
Here's the code, the error is in 'var b:Int=appleQuantity.text.toInt()'
import UIKit
class ViewControllerApple: UIViewController {
//80, 0, 0, 0, 22, 0, 2, 20, 2, 2
class Apple {
#IBOutlet weak var appleQuantity: UITextField!
#IBAction func addApple(sender: UIButton) {
}
var b:Int=appleQuantity.text.toInt()
// var appleCal = 80 * b
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
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 prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
I'm Really new to swift, so the more details provided, the more helpful it is!
Thanks so much in advance!
UPDATED Answer:
I feel that you're thinking of things the wrong way slightly. Here is how I propose you try and achieve what you're doing.
import UIKit
class ViewControllerApple: UIViewController {
class Apple {
var b: Int?
init() {
}
func getAppleCalculation() -> Int {
if let unwrappedB = b {
return unwrappedB * 80
}
else {
return 0
}
}
}
#IBOutlet weak var appleQuantity: UITextField!
#IBAction func addApple(sender: UIButton) {
}
override func viewDidLoad() {
super.viewDidLoad()
// This is where the view has loaded. Your buttons and textviews will
// have loaded and you can perform any actions on them.
var apple = Apple()
if let unwrappedAppleQuantityInt = appleQuantity.text.toInt() {
apple.b = unwrappedAppleQuantityInt
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
OLD ANSWER: Your variable b will actually never contain anything except the default value.
You should assign your Int b in your class' viewDidLoad, or following your structure, in your object's init function:
class Apple {
#IBOutlet weak var appleQuantity: UITextField!
#IBAction func addApple(sender: UIButton) {
}
var b: Int
init() {
if let unwrappedAppleQuantityInt = appleQuantity.text.toInt() {
b = unwrappedAppleQuantityInt
}
else {
// assign b a default value
b = 0
}
}
}
or you could do return a computed value, provided you only care about the output rather than storing the value, like so:
var b:Int {
get {
if let unwrappedAppleQuantityInt = appleQuantity.text.toInt() {
return unwrappedAppleQuantityInt
}
else {
return 0
}
}
}

Swift: How to use property observers with delegation

I'm trying to use delegation and property observers together to know when a property changes. I setup the protocol but I'm not sure how to use property observers.
I have a class called GridView that is being added to DetailViewController. GridView has an array of ints called rowValues. I would like to observe rowValues from DetailViewController.
GridView.swift
protocol gridViewDelegate {
func rowValueChanged(value: [Int])
}
class GridView: UIView {
var rowValues = [0,0,0,0,0]
var delegate: gridViewDelegate?
func updateRowValue() {
rowValues[0] = 1
}
}
DetailViewController.swift
class DetailViewController: UIViewController, gridViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
var grid = GridView(frame: view.frame)
grid.delegate = self
view.addSubview(grid)
}
func rowValueChanged(value: [Int]) {
println(value)
}
}
Probably this is the syntax you are looking for:
class GridView: UIView {
var rowValues: [Int] = [0,0,0,0,0] {
didSet {
if let theDelegate = self.delegate {
theDelegate.rowValueChanged(rowValues)
}
}
}
var delegate: gridViewDelegate?
}

Delegate Not Called In SWIFT iOS

I am Created 2 Views, One is and Used Protocol and Delegate. For first view the Delegate function is not called.
My FirstView Controller : Here I am Accessing the Delegate Function.
import UIKit
class NextViewController: UIViewController,DurationSelectDelegate {
//var secondController: DurationDel?
var secondController: DurationDel = DurationDel()
#IBAction func Next(sender : AnyObject)
{
let nextViewController = DurationDel(nibName: "DurationDel", bundle: nil)
self.navigationController.pushViewController(nextViewController, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
secondController.delegate=self
}
func DurationSelected() {
println("SUCCESS")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My SecondView Controller : Here I Am creating Delegate.
import UIKit
protocol DurationSelectDelegate {
func DurationSelected()
}
class DurationDel: UIViewController {
var delegate: DurationSelectDelegate?
#IBAction func Previous(sender : AnyObject) {
//let game = DurationSelectDelegate()
delegate?.DurationSelected()
self.navigationController.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
To me, it looks like you're pushing a view controller that you haven't actually set the delegate for. If you change your "Next" function, to include the line
nextViewController.delegate = self
You should see that the delegation works. In doing this, you can also probably remove the creation of "secondController", as it looks like that's redundant.
The naming convention you have followed would confuse fellow developers in your team. The instance should have been
let durationDel = DurationDel(nibName: "DurationDel", bundle: nil)
And then as #Eagerod mentioned, the delegate you would set is
durationDel.delegate = self

Resources