Resign First Responder function in SKScene - xcode

I am trying to create a game that requires to create a textfield in SKScene. I have built the text field successfully, but bringing the keyboard down is the problem. This is my code so far.
import SpriteKit
import GameplayKit
import UIKit
class GameScene: SKScene {
var sceneFrame : CGRect = CGRect()
var textFieldFrame : CGRect = CGRect()
var textField : UITextField = UITextField()
var skView: SKView = SKView()
override func didMove(to view: SKView) {
sceneFrame = CGRect(origin: .zero, size: CGSize(width: 200, height: 200))
let scene = SKScene(size: sceneFrame.size)
scene.backgroundColor = UIColor.lightGray
textFieldFrame = CGRect(origin: .init(x: 100, y: 200), size: CGSize(width: 200, height: 30))
textField = UITextField(frame: textFieldFrame)
textField.backgroundColor = UIColor.white
textField.placeholder = "Phone Number"
textField.keyboardType = .numberPad
textField.resignFirstResponder()
self.view!.addSubview(textField)
self.view!.presentScene(scene)
// Where to put the textField.resignFirstResponder() ?
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
Any answers would be helpful.

The problem is you are not adding:
textfield.delegate = self
Then you could call the function:
func textFieldShouldReturn(textField: UITextField) -> Bool {
// Hides the keyboard
textField.resignFirstResponder()
return true
}
Declaring the delegate statement initiate the function textFieldShouldReturn.
Hope this helps :)

Related

Change Label.stringValue of Label while editing textfield

I am trying to make a live textfield and show the entered string in a label but I don't know how to realize it.
What I can do now is only showing the text by a button click, but I want to skip this button. How to do this?
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var namefiled: NSTextField!
#IBOutlet weak var Mylabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func SayHelloButtonClick(_ sender: Any) {
let name:String = namefiled.stringValue
let greeting:String = "Hello \(name)!"
Mylabel.stringValue = greeting
}
}
There's likely more than one way to do this, but subclassing NSTextField and using NSTextFieldDelegate to get text changes is one way. May be run in Terminal by copy/pasting the source code into a file named 'txtfld.swift' and then using the command line code given below.
/*
To run in Terminal: swiftc -framework Cocoa txtfld.swift -o txtfld && ./txtfld
*/
import Cocoa
var label: NSTextField!
class TextField: NSTextField, NSTextFieldDelegate {
func controlTextDidChange(_ obj: Notification){
label.stringValue = "Hello " + self.stringValue
}
}
var txtFld = TextField()
class ApplicationDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}
func buildWnd() {
let _wndW:CGFloat = 400
let _wndH:CGFloat = 150
window = NSWindow(contentRect: NSMakeRect( 0, 0, _wndW, _wndH ), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(nil)
// **** Text Field Subclass **** //
txtFld = TextField (frame:NSMakeRect( 30, _wndH - 40, 120, 24 ))
window.contentView!.addSubview(txtFld)
txtFld.delegate = txtFld
// ***** Text Field as Label **** //
label = NSTextField (frame:NSMakeRect( 160, _wndH - 40, 180, 24 ))
window.contentView!.addSubview (label)
label.backgroundColor = NSColor.clear
label.isSelectable = false
label.isBordered = false
label.font = NSFont( name:"Lucida Grande", size:14 )
// === Quit btn === //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 5, 40, 40 ))
quitBtn.bezelStyle = NSButton.BezelStyle.circular
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}
func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let appDelegate = ApplicationDelegate()
let application = NSApplication.shared
application.setActivationPolicy(.regular)
application.delegate = appDelegate
application.activate(ignoringOtherApps:true)
application.run()

displaying CollectionViewController in Playground

I am simply trying to display a CollectionView in playground to quickly try out ideas. Yet this has been a hour+ affair. I'm getting the error:
2017-03-17 17:28:37.862 uikitTest[88414:10270872] * Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.6.21/UICollectionView.m:4971
2017-03-17 17:28:37.866 uikitTest[88414:10270872] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier test1 - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
*** First throw call stack:
I tried setting a view to the PlaygroundPage, and also creating a UIWindow. It isn't clear to me how to work with ViewControllers in Playground, and even whether this is the root problem and if its connected to the could not dequeue exception.
My Playground is as follows:
import UIKit
import XCPlayground
import PlaygroundSupport
class CVCCell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: .zero)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
label.frame = bounds
}
}
class CVC: UICollectionViewController {
var datasource = ["1","2","3"]
override func viewDidLoad() {
view.backgroundColor = .red
print(collectionView)
collectionView?.register(CVCCell.self, forCellWithReuseIdentifier: "test1")
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datasource.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "test1", for: indexPath) as! CVCCell
cell.label.text = datasource[indexPath.row]
return cell
}
}
let containerView = UIView(frame: CGRect(x: 0.0,
y: 0.0,
width: 375.0,
height: 667.0))
containerView.backgroundColor = .green
let fl = UICollectionViewFlowLayout()
let cvc = CVC(collectionViewLayout: fl)
let w = UIWindow(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
w.rootViewController = cvc
print(cvc.view)
containerView.addSubview(cvc.view)
//PlaygroundPage.current.liveView = containerView

How to get a custom tab bar to display a tab bar item's selected image set in Xcode?

I've created a custom tab bar that is displaying tab bar items correctly. When I select a tab / icon the tab bar item's view controller is displayed but the icon does not change to the 'Selected image' icon i.e. the icons don't change when their view controller is being shown.
What am I doing wrong? How can I get the icons to update to the images that I've set on IB as the selected images?
Here is some of my code:
class CustomTabBarController: UITabBarController, CustomTabBarDataSource, CustomTabBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.isHidden = true
let customTabBar = CustomTabBar(frame: self.tabBar.frame)
customTabBar.datasource = self
customTabBar.delegate = self
customTabBar.setup()
self.view.addSubview(customTabBar)
}
// MARK: - CustomTabBarDataSource
func tabBarItemsInCustomTabBar(_ tabBarView: CustomTabBar) -> [UITabBarItem] {
return tabBar.items!
}
// MARK: - CustomTabBarDelegate
func didSelectViewController(_ tabBarView: CustomTabBar, atIndex index: Int) {
self.selectedIndex = index
}
}
class CustomTabBar: UIView {
var tabBarItems: [UITabBarItem]!
var customTabBarItems: [CustomTabBarItem]!
var tabBarButtons: [UIButton]!
func setup() {
tabBarItems = datasource.tabBarItemsInCustomTabBar(self)
customTabBarItems = []
tabBarButtons = []
let containers = createTabBarItemContainers()
createTabBarItems(containers)
}
func createTabBarItems(_ containers: [CGRect]) {
var index = 0
for item in tabBarItems {
let container = containers[index]
let customTabBarItem = CustomTabBarItem(frame: container)
customTabBarItem.setup(item)
self.addSubview(customTabBarItem)
customTabBarItems.append(customTabBarItem)
let button = UIButton(frame: CGRect(x: 0, y: 0, width: container.width, height: container.height))
button.addTarget(self, action: #selector(CustomTabBar.barItemTapped(_:)), for: UIControlEvents.touchUpInside)
customTabBarItem.addSubview(button)
tabBarButtons.append(button)
index += 1
}
}
func barItemTapped(_ sender : UIButton) {
let index = tabBarButtons.index(of: sender)!
delegate.didSelectViewController(self, atIndex: index)
}
Change
class CustomTabBar: UIView {
to:
class CustomTabBar: UITabBar {
Then your custom tab bar will act like a tab bar!
Well I had a same kind of functionality and implemented with UITabBarController like this.
enum TabType:Int{
case viewController1 = 0
case viewController2 = 1
case viewController3 = 2
}
class CustomTabbarVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
convenience init(userType : UserType){
self.init()
addViewControllers()
setupOnInit()
let tabBar = self.tabBar
tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(UIColor(red: 22/255, green: 52/255, blue: 89/255, alpha: 1.0), size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height: tabBar.frame.height), lineWidth: 3.0)
}
func setupOnInit(){
delegate = self
tabBar.barStyle = UIBarStyle.black
tabBar.isTranslucent = false
}
func addViewControllers(){
// We will add 3 controllers
let viewController1 = viewController1(nibName: “viewController1”, bundle: nil)
let viewController2 = viewController2(nibName: “viewController2”, bundle: nil)
let viewController3 = viewController3(nibName: “viewController3”, bundle: nil)
let viewController1Navigation = UINavigationController(rootViewController: viewController1)
viewController1Navigation.tabBarItem = getTabbarItem(.viewController1)
viewController1Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
let viewController2Navigation = UINavigationController(rootViewController: viewController2)
viewController2Navigation.tabBarItem = getTabbarItem(.viewController2)
viewController2Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
let viewController3Navigation = UINavigationController(rootViewController: viewController3)
viewController3Navigation.tabBarItem = getTabbarItem(.viewController3)
viewController3Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
viewControllers = [viewController1Navigation,viewController2Navigation,viewController3Navigation]
}
func getTabbarItem(_ tabType:TabType)->UITabBarItem{
// Fetch tab bar item and set image according to it.
var image = String()
var selectedImage = String()
if tabType == .viewController1{
image = “img_viewController1_tab_nonSelected”
selectedImage = “img_viewController1_tab_Selected”
}else if tabType == .viewController2{
image = “img_viewController2_tab_nonSelected”
selectedImage = “img_viewController2_tab_Selected”
}else if tabType == .viewController3{
image = “img_viewController3_tab_nonSelected”
selectedImage = “img_viewController3_tab_Selected”
}else{
print("Unknown tab type")
}
if let imageName:String = image,let selectedImageName:String = selectedImage{
return UITabBarItem(title: nil, image: UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage(named: selectedImageName)?.withRenderingMode(.alwaysOriginal))
}else{
return UITabBarItem()
}
}
}
extension UIImage {
func createSelectionIndicator(_ color: UIColor, size: CGSize, lineWidth: CGFloat) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: size.height - lineWidth, width: size.width, height: lineWidth))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
How to implement in App delegate
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
var customTabbarVC: CustomTabbarVC?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
customTabbarVC = customTabbarVC() // It will invoke init methods of customtabbarvc
window?.rootViewController = customTabbarVC // Here your tab bar controller will setup
return true
}
// Other APP DELEGATE METHODS
}
Let me know if you have any questions..
For Changing image in your custom tab bar button after you click the button you need to write the code to change image in below function
func barItemTapped(_ sender : UIButton) {
}
similarly
func barItemTapped(_ sender : UIButton)
{
if sender.tag == 1
{
tabBarButtons.setImage(UIImage(named:"FirstImage.png"), forState: .Normal)
}
else
{
tabBarButtons.setImage(UIImage(named:"SecImage.png"), forState: .Normal)
}
}

Editor place holder in source file

I don't understand the problem here, my code has no bugs, but when I hit run nothing appears on the emulator. I need help, how can I see my images appear as a Scrollview on the emulator ?
import UIKit
class ViewController: UIViewController {
#IBOutlet var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
mainScrollView.frame = view.frame
super.viewDidLoad()
imageArray = [#imageLiteral(resourceName: "IMG_1750"), #imageLiteral(resourceName: "IMG_1754")]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat( i + 1)
mainScrollView.addSubview(imageView)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

How to format a scene in SKSpriteKit for Simulator AND Physical Device

I am having a problem formatting the scene for a simple game using SKSpriteKit.
In the simulator, my scene looks exactly how I want, but on a physical device it does not.
This is what is looks like in the Simulator
This is what it looks like on my Ipad
Once I run this on a physical device(my iPad), all i get is a zoomed in picture of the background.
Here is my GameViewController.swift
import UIKit
import SpriteKit
class GameViewController: UIViewController {
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
//Configure the view
let skView = view as! SKView
skView.multipleTouchEnabled = false
//Create and configure the scene
//create scene within size of skview
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
//present the scene
skView.presentScene(scene)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .Landscape
} else {
return .All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Additionally Here is my GameScene.swift
import SpriteKit
class GameScene: SKScene {
//////////////////////////////////////////////////////////////////////
//background
var background = SKSpriteNode(imageNamed: "Basketball")
//isStarted & GameOver
var isStarted = false
var isGameOver = false
//
var Ball: Basketball_Ball!
var Rim1: Rim!
var Rim2: Rim!
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
func addBackground(){
//background
background.zPosition = 0
background.size = self.frame.size
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
}
/////////////////////////////////////////////////////////////////////
func addBall() {
Ball = Basketball_Ball()
addChild(Ball)
Ball.loadAppearance()
}
/////////////////////////////////////////////////////////////////////
func addRims() {
Rim1 = Rim()
addChild(Rim1)
Rim1.loadAppearance()
Rim2 = Rim()
addChild(Rim2)
Rim2.loadAppearance_Rim2()
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
override func didMoveToView(view: SKView) {
addBackground()
addBall()
addRims()
}
/////////////////////////////////////////////////////////////////////
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Does the problem lie in my use of scene.scaleMode in my GameViewController file?
Do I need to upload different sizes for each image in my Assets Folder?

Resources