I want to create a hyperlink with selected text in UITextView in swift.eg. When I type "Please click here" in UITextView and select "here" from the sentence I will open a UIAlertController with textView where I can enter the url and while tapping "Save" button on UIAlertController I want the word "here" to add the hyperlink. How do I achieve this?
This is my code for UITextView:
var textView: TextView?
override public func viewDidLoad() {
super.viewDidLoad()
textView = TextView(
editorConfig: EditorConfig(
theme: getTheme()
)
)
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.backgroundColor = .white
layoutTextView()
}
private func layoutTextView() {
textView?.frame = CGRect(
x: view.safeAreaInsets.left,
y: view.safeAreaInsets.top,
width: view.bounds.width - view.safeAreaInsets.left - view.safeAreaInsets.right,
height: view.frame.size.height / 3
)
textView?.layer.borderWidth = 1
textView?.layer.borderColor = UIColor.gray.cgColor
textView?.isEditable = true
textView?.isUserInteractionEnabled = true
textView?.textColor = .black
if let textView = textView {
view.addSubview(textView)
}
}
I have a button insertLink which displays the UIAlertController. Here's the code for the Alert:
func showAlert(url: String?) {
guard let url = url else {
return
}
let attributedString = NSMutableAttributedString(string: url)
attributedString.SetAsLink(textToFind: url + alertTextView.text, linkURL: url + alertTextView.text)
let alertController = UIAlertController(title: "Link", message: nil, preferredStyle: .alert)
alertTextView.textContainerInset = UIEdgeInsets.init(top: 15, left: 5, bottom: 8, right: 35)
let saveAction = UIAlertAction(title: "Save", style: .default) { (action) in
alertController.view.removeObserver(self, forKeyPath: "bounds")
}
saveAction.isEnabled = false
let cancelAction = UIAlertAction.init(title: "Cancel", style: .default) { (action) in
alertController.view.removeObserver(self, forKeyPath: "bounds")
}
alertController.view.addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions.new, context: nil)
NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: alertTextView, queue: OperationQueue.main) { (notification) in
saveAction.isEnabled = self.alertTextView.text != ""
}
alertTextView.backgroundColor = UIColor.white
alertTextView.isEditable = true
alertTextView.attributedText = attributedString
alertTextView.dataDetectorTypes = UIDataDetectorTypes.link
alertTextView.layer.cornerRadius = 20
alertController.view.addSubview(self.alertTextView)
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "bounds"{
if let rect = (change?[NSKeyValueChangeKey.newKey] as? NSValue)?.cgRectValue {
let margin:CGFloat = 8.0
alertTextView.frame = CGRect.init(x: rect.origin.x + margin, y: rect.origin.y + margin, width: rect.width - 2*margin, height: rect.height / 2)
alertTextView.bounds = CGRect.init(x: rect.origin.x + margin, y: rect.origin.y + margin, width: rect.width - 2*margin, height: rect.height / 2 - 10)
}
}
}
So in the UIAlertController's textView(alertTextView) when I type "https://www.google.com" how do I send this link to the main UITextView and onClick of it it should open browser?
Related
When I added an extension to UIAlertController to modify actions fonts, it didn't seem to work. What should I do to modify the Action font。
Here is my code
extension UIAlertController {
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if self.preferredStyle == .actionSheet {
for i in self.actions {
let attributedText = NSAttributedString(string: i.title ?? "", attributes: [NSAttributedString.Key.font : UIFont(name: "SFProText-Semibold", size: 15.0)!])
guard let label = (i.value(forKey: "__representer") as AnyObject).value(forKey: "label") as? UILabel else { return }
label.attributedText = attributedText
}
}
}
}
Create an extension of UIAlertController
extension UIAlertController {
func setBackgroudColor(color: UIColor) {
if let bgView = self.view.subviews.first,
let groupView = bgView.subviews.first,
let contentView = groupView.subviews.first {
contentView.backgroundColor = color
}
}
func setTitle(font: UIFont?, color: UIColor?) {
guard let title = self.title else { return }
let attributeString = NSMutableAttributedString(string: title)
if let titleFont = font {
attributeString.addAttributes([NSAttributedString.Key.font : titleFont],
range: NSMakeRange(0, title.utf8.count))
}
if let titleColor = color {
attributeString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor],
range: NSMakeRange(0, title.utf8.count))
}
self.setValue(attributeString, forKey: "attributedTitle")
}
func setMessage(font: UIFont?, color: UIColor?) {
guard let title = self.message else {
return
}
let attributedString = NSMutableAttributedString(string: title)
if let titleFont = font {
attributedString.addAttributes([NSAttributedString.Key.font : titleFont], range: NSMakeRange(0, title.utf8.count))
}
if let titleColor = color {
attributedString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor], range: NSMakeRange(0, title.utf8.count))
}
self.setValue(attributedString, forKey: "attributedMessage")
}
func setTint(color: UIColor) {
self.view.tintColor = color
}
}
Call it from a UIViewController may be in a button action like below.
func tapShowAlert() {
let alertController = UIAlertController(title: "Alert!!", message: "This is custom alert message", preferredStyle: .alert)
alertController.setTitle(font: UIFont.boldSystemFont(ofSize: 24), color: UIColor.yellow)
alertController.setMessage(font: UIFont(name: "Verdana", size: 16), color: UIColor.red)
let actnOk = UIAlertAction(title: "Ok", style: .default, handler: nil)
let actnCancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alertController.addAction(actnOk)
alertController.addAction(actnCancel)
self.present(alertController, animated: true, completion: nil)
}
In a popover page, I'm trying to store some data in CoreData, and I need to show a loading view until the process is done.
I found a good and easy way, using a alert controller to show a loading label. In the function, I added a shouldPresent Boolean to make it false when the coreData process is done and hide the alert.
private func presentLoadingView(shouldPresent: Bool) {
let alert = UIAlertController(title: nil, message: "Retrieving Owner Data", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 3, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.medium
loadingIndicator.startAnimating()
alert.view.addSubview(loadingIndicator)
presentAnimated(alert)
if !shouldPresent {
alert.dismiss(animated: true)
}
}
The problem is, when I use
dismiss(animated: true)
the entire popover will be dismissed and when I use
alert.dismiss(animated: true)
Nothing happen, could anyone help me on this. Thanks in advance.
Try replaceing
presentAnimated(alert)
if !shouldPresent {
alert.dismiss(animated: true)
}
with
if shouldPresent {
presentAnimated(alert)
}
It seems it will do the work , accroding to your example code.
I think using alert view for loading is not good enough for your needs.
You can use this extension easily for showing a loading view.
extension UIViewController{
func showActivityIndicator(){
DispatchQueue.main.async {[weak self] in
guard let self = self else {return}
let indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
indicator.backgroundColor = UIColor.init(hexString: "#010101").withAlphaComponent(0.6)
indicator.layer.cornerRadius = 6
indicator.center = self.view.center
indicator.hidesWhenStopped = true
indicator.color = UIColor(hexString: "#FFEE00")
indicator.style = UIActivityIndicatorView.Style.large
indicator.startAnimating()
self.view.isUserInteractionEnabled = false
indicator.tag = 1000000
for subView in self.view.subviews{
if subView.tag == 1000000{
print("Already Added")
return
}
}
self.view.addSubview(indicator)
}
}
func hideActivityIndicator(){
DispatchQueue.main.async { [weak self] in
guard let self = self else {return}
let indicator = self.view.viewWithTag(1000000) as? UIActivityIndicatorView
indicator?.stopAnimating()
indicator?.removeFromSuperview()
self.view.isUserInteractionEnabled = true
indicator?.isHidden = true
}
}
}
In your view controller just call self.showActivityIndicator() when you want to show loader
and call self.hideActivityIndicator() for dismiss the loader.
You can use this technique
var alert:UIAlertController? = UIAlertController() //set variable outside in your popover
private func presentLoadingView(shouldPresent: Bool) {
if shouldPresent {
if self.alert == nil{
self.alert = UIAlertController(title: nil, message: "Retrieving Owner Data", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 3, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.medium
loadingIndicator.startAnimating()
alert.view.addSubview(loadingIndicator)
}
if !self.alert.isBeingPresented {
self.present(self.alert, animated: true, completion: nil)
}
}else{
self.alert.dismiss(animated: false, completion: nil)
}
}
I'm using CoreData and I have an issue.
So, I'm using scroll view and in the following code it adds a label and a textfield every time the user presses the "add" button. And I need to save this to CoreData(yes it needs to be CoreData). But how can I do this? I went through CoreData relationships but couldn't understand and hoping for help.
Thank you vary much :)
var count = 0
#IBAction func add(_ sender: Any) {
count += 1
let myPoint = count * 100
if count >= 1 {
let myAlartController = UIAlertController(title: "Add Item", message: "Please add title and context", preferredStyle: UIAlertControllerStyle.alert)
myAlartController.addTextField(configurationHandler: ({(firstText: UITextField!) -> Void in firstText.placeholder = "Please add title"}))
myAlartController.addTextField(configurationHandler: ({(secondText: UITextField!) -> Void in secondText.placeholder = "Please add context"}))
let okButton = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
(action: UIAlertAction) -> Void in
//When the bottum is pressed
let myCGRect = CGRect(x: 0, y: 0, width: 105, height: 30)
//Label
let myLabel = UILabel(frame: myCGRect)
myLabel.backgroundColor = UIColor.orange
let labelOfAlert = myAlartController.textFields?[0]
myLabel.text = labelOfAlert?.text
myLabel.textColor = UIColor.white
myLabel.layer.position = CGPoint(x: 60, y: (565 + myPoint))
//textFiled
let myTextField = UITextField(frame: myCGRect)
myTextField.backgroundColor = UIColor.gray
let textOfAlert = myAlartController.textFields?[1]
myTextField.text = textOfAlert?.text
myTextField.layer.position = CGPoint(x: 135, y: (565 + myPoint))
self.labelTopConstrain.constant = (CGFloat(900 + myPoint))
self.labelBottomConstrain.constant = 20
self.myScroll.layoutIfNeeded()
myLabel.tag = self.count
myTextField.tag = self.count
self.myScroll.addSubview(myLabel)
self.myScroll.addSubview(myTextField)
let testSave = Test(context: myContext)
testSave.label = myLabel.text
testSave.textField = myTextField.text
(UIApplication.shared.delegate as! AppDelegate).saveContext()
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
myAlartController.addAction(okButton)
myAlartController.addAction(cancelAction)
present(myAlartController, animated: true, completion: nil)
}/*if*/
}/**/
I have a videPlayerView which has ContainerView on top of it to show activityIndicatorView. The view gets loaded when i select an item from a collectionView inside a cell. My question is how to remove this view using the cancelButton, i tried removeFromSuperview() for both the container and the playerView but the app crashes with this error
AQDefaultDevice (1): skipping input stream 0 0 0x0
Here is the code:
class VideoPlayerView: UIView {
var videoUrl: String!
var uuidd: String!
let activityIndicatorView: UIActivityIndicatorView = {
let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
aiv.translatesAutoresizingMaskIntoConstraints = false
aiv.startAnimating()
return aiv
}()
lazy var controlsContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0, alpha: 1)
view.isUserInteractionEnabled = true
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handlezoomout)))
return view
}()
func handlezoomout(hh: UITapGestureRecognizer){
print("n3me")
}
lazy var cancelButton: UIButton = {
let cancelButton = UIButton()
cancelButton.setImage(#imageLiteral(resourceName: "cancel"), for: UIControlState())
cancelButton.addTarget(self, action: #selector(cancel), for: .touchUpInside)
return cancelButton
}()
func cancel() {
controlsContainerView.removeFromSuperview()
let video = VideoPlayerView()
video.removeFromSuperview()
}
lazy var pausePlayButton: UIButton = {
let button = UIButton(type: .system)
let image = UIImage(named: "pause")
button.setImage(image, for: UIControlState())
button.translatesAutoresizingMaskIntoConstraints = false
button.tintColor = .white
button.isHidden = true
button.addTarget(self, action: #selector(handlePause), for: .touchUpInside)
return button
}()
var isPlaying = false
func handlePause() {
if isPlaying {
player?.pause()
pausePlayButton.setImage(UIImage(named: "play"), for: UIControlState())
} else {
player?.play()
pausePlayButton.setImage(UIImage(named: "pause"), for: UIControlState())
}
isPlaying = !isPlaying
}
override init(frame: CGRect) {
super.init(frame: frame)
setUpPlayerView()
controlsContainerView.frame = frame
addSubview(controlsContainerView)
cancelButton.frame = CGRect(x: 16.0, y: 20.0, width: 30.0, height: 30.0)
controlsContainerView.addSubview(cancelButton)
controlsContainerView.addSubview(activityIndicatorView)
activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
controlsContainerView.addSubview(pausePlayButton)
pausePlayButton.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
pausePlayButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
pausePlayButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
pausePlayButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
backgroundColor = UIColor.black
}
var player: AVPlayer?
fileprivate func setUpPlayerView() {
let postQuery = PFQuery(className: "posts")
postQuery.whereKey("uuid", equalTo: PostUuidGlobalVariable.postuuid.last!)
postQuery.getFirstObjectInBackground { (object, error) in
if (error == nil && object != nil) {
let videoFile = object!["video"] as! PFFile
if let url = URL (string: videoFile.url!) {
self.player = AVPlayer(url: url)
let playerLayer = AVPlayerLayer(player: self.player)
self.layer.addSublayer(playerLayer)
playerLayer.frame = self.frame
self.player?.play()
self.player?.isMuted = false
self.player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(note:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem)
}
}
}
}
func playerDidFinishPlaying(note: NSNotification) {
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
//this is when the player is ready and rendering frames
if keyPath == "currentItem.loadedTimeRanges" {
activityIndicatorView.stopAnimating()
pausePlayButton.isHidden = false
isPlaying = true
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class VideoLauncher: NSObject {
func showVideoPlayer() {
if let keyWindow = UIApplication.shared.keyWindow {
let view = UIView(frame: keyWindow.frame)
view.isUserInteractionEnabled = true
view.backgroundColor = UIColor.white
view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)
let height = keyWindow.frame.height
let videoPlayerFrame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: height)
let videoPlayerView = VideoPlayerView(frame: videoPlayerFrame)
view.addSubview(videoPlayerView)
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
view.frame = keyWindow.frame
}, completion: { (completedAnimation) in
//maybe we'll do something here later...
UIApplication.shared.isStatusBarHidden = true
})
keyWindow.addSubview(view)
}
}
}
There is a chance this is related to you changing the user interface outside of the main thread.
From UIView documents
'Threading Considerations
Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the
UIView
class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself, but all other manipulations should occur on the main thread.'
Also your cancel function creates a new video player view and then tries to remove it from it parent which doesn't look correct.
Your cancel callback should probably be as follows
func cancel() {
DispatchQueue.main.async { [unowned self] in
// to remove controls
self.controlsContainerView.removeFromSuperview()
// to remove video player view
self.view.removeFromSuperview()
}
}
I am in the process of creating a game (Swift) in xcode using a number of SKScene and Sprite objects. I want to create a Scene (settings scene) that captures the player's name, email, gender etc. How can I go about this? How can I capture input from user. SKScenes do not allow input fields/values in the UI?
Thanks
You can build a custom login page that is conform with your game layout without try to rebuild in UIKit the same graphic assets.
Few days ago I've written an answer about SKSceneDelegate to communicate between the scene(SpriteKit) and the viewController (UIKit), take present this answer if you want to call other viewControllers because its the same concept of this answer..
Starting with this GameViewController we can develop some useful methods to handle the login form buttons and show some alerts:
import UIKit
import SpriteKit
class GameViewController: UIViewController, TransitionDelegate {
override func viewDidLoad() {
super.viewDidLoad()
guard let view = self.view as! SKView? else { return }
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
let scene = GameScene(size:view.bounds.size)
scene.scaleMode = .fill
scene.delegate = self as TransitionDelegate
scene.anchorPoint = CGPoint.zero
view.presentScene(scene)
}
func showAlert(title:String,message:String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default) { action in
print("handle Ok action...")
})
alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
self.present(alertController, animated: true)
}
func handleLoginBtn(username:String,password:String) {
print("handleLoginBtn")
print("username is: \(username) and password: \(password)")
}
func handleFacebookBtn() {
print("handleFacebookBtn")
}
func handleTwitterBtn() {
print("handleTwitterBtn")
}
}
Then we can make our scene trying to take the advantage of SpriteKit elements:
import SpriteKit
import UIKit
protocol TransitionDelegate: SKSceneDelegate {
func showAlert(title:String,message:String)
func handleLoginBtn(username:String,password:String)
func handleFacebookBtn()
func handleTwitterBtn()
}
class GameScene: SKScene,UITextFieldDelegate {
var usernameTextField:UITextField!
var passwordTextField:UITextField!
var loginBtn:SKShapeNode!
var facebookBtn:SKShapeNode!
var twitterBtn:SKShapeNode!
override func didMove(to view: SKView) {
//bg
let bg = SKSpriteNode(imageNamed: "appleWallpaper")
addChild(bg)
bg.position = CGPoint(x:self.size.width/2,y:self.size.height/2)
//title
let title = SKLabelNode.init(fontNamed: "AppleSDGothicNeo-Bold")
title.text = "xyzGame"; title.fontSize = 25
title.fontColor = .orange
addChild(title)
title.zPosition = 1
title.position = CGPoint(x:self.size.width/2,y:self.size.height-80)
//textfields
guard let view = self.view else { return }
let originX = (view.frame.size.width - view.frame.size.width/1.5)/2
usernameTextField = UITextField(frame: CGRect.init(x: originX, y: view.frame.size.height/4.5, width: view.frame.size.width/1.5, height: 30))
customize(textField: usernameTextField, placeholder: "Enter your username")
view.addSubview(usernameTextField)
usernameTextField.addTarget(self, action:#selector(GameScene.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
passwordTextField = UITextField(frame: CGRect.init(x: originX, y: view.frame.size.height/4.5+60, width: view.frame.size.width/1.5, height: 30))
customize(textField: passwordTextField, placeholder: "Enter your password", isSecureTextEntry:true)
view.addSubview(passwordTextField)
//buttons
let myBlue = SKColor(colorLiteralRed: 59/255, green: 89/255, blue: 153/255, alpha: 1)
loginBtn = getButton(frame: CGRect(x:self.size.width/4,y:self.size.height/2,width:self.size.width/2,height:30),fillColor:myBlue,title:"Login",logo:nil,name:"loginBtn")
addChild(loginBtn)
loginBtn.zPosition = 1
let label = SKLabelNode.init(fontNamed: "AppleSDGothicNeo-Regular")
label.text = "or connect with"; label.fontSize = 15
label.fontColor = .gray
addChild(label)
label.zPosition = 1
label.position = CGPoint(x:self.size.width/2,y:self.size.height/2-30)
let logoFb = SKSpriteNode.init(imageNamed: "facebook-icon")
logoFb.setScale(0.5)
facebookBtn = getButton(frame: CGRect(x:self.size.width/4,y:self.size.height/2-80,width:self.size.width/4.5,height:30),fillColor:myBlue,logo:logoFb,name:"facebookBtn")
addChild(facebookBtn)
facebookBtn.zPosition = 1
let myCyan = SKColor(colorLiteralRed: 85/255, green: 172/255, blue: 239/255, alpha: 1)
let logoTw = SKSpriteNode.init(imageNamed: "twitter-icon")
logoTw.setScale(0.5)
twitterBtn = getButton(frame: CGRect(x:self.size.width/2,y:self.size.height/2-80,width:self.size.width/4.5,height:30),fillColor:myCyan,logo:logoTw,name:"twitterBtn")
addChild(twitterBtn)
twitterBtn.zPosition = 1
}
func customize(textField:UITextField, placeholder:String , isSecureTextEntry:Bool = false) {
let paddingView = UIView(frame:CGRect(x:0,y: 0,width: 10,height: 30))
textField.leftView = paddingView
textField.keyboardType = UIKeyboardType.emailAddress
textField.leftViewMode = UITextFieldViewMode.always
textField.attributedPlaceholder = NSAttributedString(string: placeholder,attributes: [NSForegroundColorAttributeName: UIColor.gray])
textField.autocapitalizationType = .none
textField.autocorrectionType = .no
textField.layer.borderColor = UIColor.gray.cgColor
textField.layer.borderWidth = 0.5
textField.layer.cornerRadius = 4.0
textField.textColor = .white
textField.isSecureTextEntry = isSecureTextEntry
textField.delegate = self
}
func getButton(frame:CGRect,fillColor:SKColor,title:String = "",logo:SKSpriteNode!,name:String)->SKShapeNode {
let btn = SKShapeNode(rect: frame, cornerRadius: 10)
btn.fillColor = fillColor
btn.strokeColor = fillColor
if let l = logo {
btn.addChild(l)
l.zPosition = 2
l.position = CGPoint(x:frame.origin.x+(frame.size.width/2),y:frame.origin.y+(frame.size.height/2))
l.name = name
}
if !title.isEmpty {
let label = SKLabelNode.init(fontNamed: "AppleSDGothicNeo-Regular")
label.text = title; label.fontSize = 15
label.fontColor = .white
btn.addChild(label)
label.zPosition = 3
label.position = CGPoint(x:frame.origin.x+(frame.size.width/2),y:frame.origin.y+(frame.size.height/4))
label.name = name
}
btn.name = name
return btn
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let positionInScene = touch!.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
switch name {
case "loginBtn":
self.run(SKAction.wait(forDuration: 0.1),completion:{[unowned self] in
guard let delegate = self.delegate else { return }
(delegate as! TransitionDelegate).handleLoginBtn(username:self.usernameTextField.text!,password: self.passwordTextField.text!)
})
case "facebookBtn":
self.run(SKAction.wait(forDuration: 0.1),completion:{[unowned self] in
guard let delegate = self.delegate else { return }
(delegate as! TransitionDelegate).handleFacebookBtn()
})
case "twitterBtn":
self.run(SKAction.wait(forDuration: 0.1),completion:{[unowned self] in
guard let delegate = self.delegate else { return }
(delegate as! TransitionDelegate).handleTwitterBtn()
})
default:break
}
}
}
func textFieldDidChange(textField: UITextField) {
//print("everytime you type something this is fired..")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
if textField == usernameTextField { // validate email syntax
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
let result = emailTest.evaluate(with: textField.text)
let title = "Alert title"
let message = result ? "This is a correct email" : "Wrong email syntax"
if !result {
self.run(SKAction.wait(forDuration: 0.01),completion:{[unowned self] in
guard let delegate = self.delegate else { return }
(delegate as! TransitionDelegate).showAlert(title:title,message: message)
})
}
}
}
deinit {
print("\n THE SCENE \((type(of: self))) WAS REMOVED FROM MEMORY (DEINIT) \n")
}
}
Output:
Animated output:
As you can see we can handle both framework with their delegate methods, I've tested this page with iPhone 5 and iPhone 7 plus.