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

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)")
}
}

Related

Swift - Function in other view controller is not being called (protocol / delegate)

I'm trying to call the function updateProgress from a LoadingDataHelper object but my delegate is not being called. I think the problem is that this LoadingDataHelper is not connected to the LoadingDataViewController (I mean like when you're having a UIView and a viewController).
LoadingDataHelper
protocol LoadingNewDataDelegate: class {
func updateProgress(progress : Float)
}
class LoadingDataHelper: NSObject {
var delegate: LoadingNewDataDelegate?
static let shared = LoadingDataHelper() // shared instance
func loginUser() {
//more code
updateProgressInViewController()
//more code
}
func updateProgressInViewController() {
delegate?.updateProgress(0.3)
}
}
LoadingDataViewController
class LoadingDataViewController: UIViewController, LoadingNewDataDelegate {
let loadingDataHelper: LoadingDataHelper = LoadingDataHelper()
override func viewDidLoad() {
super.viewDidLoad()
loadingDataHelper.delegate = self
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (NSUserDefaults.standardUserDefaults().boolForKey("approvedTermsOfUse")) {
self.updateProgress(0.1)
LoadingDataHelper.shared.loginUser()
} else {
self.askForTerms()
}
}
func updateProgress(progress : Float) {
self.progressBar.setProgress(progress, animated: true)
self.progressBar.setNeedsDisplay()
}
}
Is there a way to solve this?
There is some wrong in above codeL:
In LoadingDataViewController, you are creating static property for LoadingDataHelper class and setting delegate to that class. But you are call "loginUser" using direct call.
You need to change like below:
class LoadingDataViewController: UIViewController, LoadingNewDataDelegate {
**//Change to shared initialisation of object//**
let loadingDataHelper: LoadingDataHelper = LoadingDataHelper.shared
override func viewDidLoad() {
super.viewDidLoad()
loadingDataHelper.delegate = self
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (NSUserDefaults.standardUserDefaults().boolForKey("approvedTermsOfUse")) {
self.updateProgress(0.1)
**//Call using static object instead of new instance or direct call//**
loadingDataHelper.loginUser()
} else {
self.askForTerms()
}
}
func updateProgress(progress : Float) {
self.progressBar.setProgress(progress, animated: true)
self.progressBar.setNeedsDisplay()
}
}
This will make your controller to get delegate call back.

Delegate events not called for custom view class in 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
}
}

Looking understand why delegate keep alive

I have the following structure
Main ViewController: it is responsible to call the (A) view controller.
(A) ViewController: create an CustomClass instance and has a delegate for this class.
CustomClass: in each period of 1 second, a message is sent to (A) view controller via delegate.
Until here all works fine. Once I returned to Main ViewController the delegate keep alive, in other words, the delegate updates A(ViewController) variable. I checked that viewDidDisappear of (A) ViewController is called.
When I return again from Main ViewController to (A) ViewController, a new variable instance is created. I don't understand this anyway.
Besides this doubt, I would like to understand why the delegate keep alive when I return to main view controller. I am using a UINavigationItem to navigation.
I am a beginner in IOS development.
Thanks advanced!!!
Edit 1:
The (A)ViewController is called from MainViewController by Segue. The segue was added via storyboard.
MainViewController.swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
AViewController.swift
class ScanDevices : UIViewController, CustomClassDelegate {
var myInts : [Int] = []
var customClass : CustomClass!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
if customClass == nil {
customClass = CustomClass()
customClass.customClassDelegate = self
}
}
override func viewWillAppear(animated: Bool) {
print("viewWillAppear")
}
override func viewDidAppear(animated: Bool) {
print("viewDidAppear")
}
override func viewWillDisappear(animated: Bool) {
print("viewWillDisappear")
}
override func viewDidDisappear(animated: Bool) {
print("viewDidDisappear")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func didDiscoverPeripheralInt(peripheral: Int) {
myInts.append(peripheral)
print("Number = \(myInts.count)")
}
}
CustomClass.swift
class CustomClass : NSObject {
var customClassDelegate : CustomClassDelegate?
// MARK: init
override init() {
super.init()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "writeInt", userInfo: nil, repeats: true)
}
func writeInt () {
CustomClassDelegate?.didDiscoverPeripheralInt(3)
}
}
var customClassDelegate : CustomClassDelegate?
You are holding a string reference to your delegate.
It needs to be
weak var customClassDelegate : CustomClassDelegate?
Take a look at the following document :
http://krakendev.io/blog/weak-and-unowned-references-in-swift
Your CustomClass holds strong reference to the delegate. You have to mark the property with weak:
weak var customClassDelegate : CustomClassDelegate?

Swift - 1 screen to another screen

I have set you my UI for both screens and I don't want to do the connect the screens in main.storyboard. I want to click a button and it will take to that screen, I will do the fade animations and stuff like that later. I just need to know how to go to one screen to the next screen when I press a button. I can give an example of what I am talking about down below.
Example: In flappy bird before you start the game it tell you to tap on the screen, then when you tap the text fades out. That is what I want to do with my game. I am not sure if that is another screen or if that is 1 view that makes certain labels disappear once the screen is tapped.
My MainMenuViewController:
import UIKit
import SpriteKit
class MainMenuViewController: UIViewController {
var mainMenuScene: MainMenuScene!
#IBOutlet weak var playButton: UIButton!
#IBAction func playButtonPressed(sender: AnyObject) {
mainMenuScene.playButtonPressed(sender)
}
#IBAction func playerButtonPressed(sender: AnyObject) {
println("player")
}
#IBAction func LeaderboardButtonPressed(sender: AnyObject) {
println("leaderboard")
}
#IBAction func shopButtonPressed(sender: AnyObject) {
println("shop")
}
override func viewDidLoad() {
super.viewDidLoad()
//set up game screens
// Configure the view
// store a ref
// Create and configure the scene
mainMenuScene?.scaleMode = .AspectFill
// Present the scene
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
My MainMenuScene:
import Foundation
import UIKit
import SpriteKit
class MainMenuScene: SKScene {
var movingGround: PPMovingGround!
var square1: PPSquare1!
var wallGen: PPWallGen!
var isStarted = false
var playButton: UIButton!
func playButtonPressed(sender: AnyObject) {
start()
}
func start() {
isStarted = true
square1.stop()
movingGround.start()
wallGen.startGenWallsEvery(1)
}
override func didMoveToView(view: SKView) {
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
}
override func update(currentTime: CFTimeInterval) {
}
}
I want to connect this code to my GameScene File. How do I do it?
I think I know what you're aiming for, since you don't want to do work with the Main.storyboard directly, you could do this:
presentViewController(YourNextViewController, animated: true, completion: nil)
you would call that in the ViewController you are currently in to get to the next one.
Let's say you are on the main screen, as you said in Flappy Bird, when you tap the button, it could change to a different View Controller
My tip would be to nest this method in a function, so you can call it in a gameStart function, like so:
func changeViewControllers() {
presentViewController(GameViewController, animated: true, completion: nil)
}
then call this in your gameStart():
func gameStart() {
changeViewControllers()
//other code
}
//=====================================================================
Alright, I'm going to help you get to another view when you tap your play button, add the following code:
#IBAction func playButtonPressed(sender: AnyObject) {
mainMenuScene.playButtonPressed(sender)
}

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