Playground vs. Simulator - Why Does Simple View Render Differently? - ios

Xcode 7.3, iOS 9.3
I am experimenting with playgrounds so as to expand my capacity to use them to do rapid prototyping. I have created a simple view controller which is adding/centering a button to/in its view. I have duplicated the view controller code in a project and in a playground. When I execute the project in the simulator the button is centered. When I execute the playground the button is not centered. Would someone please help me to understand why this is happening?
I have included 3 screenshots:
Xcode Project With View Controller Code
Simulator Showing the Result of Executing the Project
Playground With View Controller Code and Timeline Showing the Execution Result
Per #Paulw11's comment, here is the updated and working view controller code:
class ViewController : UIViewController {
let button = UIButton(type: .System)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .whiteColor()
view.layer.borderColor = UIColor.redColor().CGColor
view.layer.borderWidth = 2
button.bounds = CGRect(x: 0, y: 0, width: 50, height: 20)
button.backgroundColor = .blueColor()
button.setTitle("Rotate", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(rotate), forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(button)
print("View: size is \(view.bounds.width) x \(view.bounds.height), centered #\(view.center)")
print("Button: size is \(button.bounds.width) x \(button.bounds.height), centered #\(button.center)")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
button.center = view.convertPoint(view.center, fromView: view.superview)
}
func rotate() {
print("Rotate")
}
}

Related

Why the interface is not displayed?

There are 2 functions:
func configure() {
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height))
scrollView.contentSize = CGSize(width: view.frame.size.width, height: 1200)
scrollView.backgroundColor = .white
view.addSubview(scrollView)
}
func configure1() {
let listButton = UIButton(frame: CGRect(x: view.frame.size.width - 30, y: 57, width: 25, height: 25))
listButton.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
listButton.setImage(UIImage(systemName: "list.bullet"), for: .normal)
scrollView.addSubview(listButton)
}
When calling these functions, only the scrollView is displayed, but the listButton is not displayed
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
configure()
configure1()
}
If combine the code of these functions into one, then everything works. Why doesn't it work out of two functions?
I have one question about your code, you created the ScrollView directly on Storyboard or directly on the code? If you created directly on code, the steps below should work.
I just paste your code to my Xcode and found some problems.
You did not paste the buttonAction code, so this error appeared:
Cannot find 'buttonAction' in scope
To solve this, I did a simple function that prints in console "buttonPrint".
#objc func buttonAction() {
print("buttonPrint")
}
configure1 function did not find scrollView in scope
To solve this, I created a view controller instance property declaring scrollView at the top of my ViewController, outside other functions, using the code below:
var scrollView = UIScrollView()
Redeclaration of scrollView
You declared scrollView on the first line of configure(). To solve the redeclaration, I simply deleted let statement.
Then I builded the app and it worked with these two functions :)
I'm using Xcode version 13.2.1 and an iPhone 11 simulator.

tabbar middle tab out of tabbar corner

I want to make a tab bar with 5 tab items. I want the middle one ( third ) to be out of tab bar's corner it may be tough to understand therefore I decided to add screenshot
I want to make something like you can see above but I don't know how it's possible.
I would appreciate any way you recommend to do it.
select tabbar Item and set its image insets
Make sure to get proper image (if using an image) goto Assets-> select desired image -> set property to always original
create a class of UITabBarController and assign it to the TabBarController.
initialise Variable
let button = UIButton.init(type: .custom)
Then in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
button.setImage(UIImage(named: "IMAGE_NAME_FROM_ASSETS"), for: .normal)
button.backgroundColor = UIStyle.Color.CameraBG
button.layer.cornerRadius = 40
button.addShadow(offset: CGSize(width: 5, height: 5), color: UIStyle.Color.CameraShadow, radius: 5, opacity: 0.1)
button.addTarget(self, action: #selector(pressedAction(_:)), for: .touchUpInside)
self.view.insertSubview(button, aboveSubview: self.tabBar)
}
Add viewDidLayoutSubviews in your class
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// safe place to set the frame of button manually
button.frame = CGRect.init(x: self.tabBar.center.x - 40, y: self.view.bounds.height - 100, width: 80, height: 80)
}
Action You Want To Perform on button click
#objc func pressedAction(_ sender: UIButton) {
// do your stuff here
let nc = UINavigationController(rootViewController: YOURVC.storyboardInstance())
nc.modalPresentationStyle = .fullScreen
present(nc, animated: true, completion: nil)
}

Create UIButton on top layer UITableViewController like as AirBnB

How to create UIButton in UITableViewController like as AirBnB map.
Highlighted in red in screenshot.
It's quite easy actually, just create the table view as you always do (either storyboard or code) then create the button, position it correctly, set constraints and make sure it's not a subview of the table view but the view that contains the table view.
Since you didn't specify whether you use the storyboard or not, I did use it for the example below.
See this extremely simple demo I've just created:
This is the view hierarchy:
And these are the constraints for the button:
Create a button first and then then override the function scrollViewDidScroll():
import UIKit
class YourTableViewController: UITableViewController {
private let button = UIButton(type: UIButton.ButtonType.custom) as UIButton
override func viewDidLoad() {
let image = UIImage(named: "Image.png")
button.frame = CGRect(x: yourXpos, y: yourYPos, width: 60, height: 60)
button.setImage(image, for: .normal)
button.clipsToBounds = true
button.layer.cornerRadius = 30
button.addTarget(self, action: #selector(buttonClicked(_:)), for:.touchUpInside)
areaOfTableView.addSubview(button)
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = self.areaOfTableView.contentOffset.y
button.frame = CGRect(x: yourXpos, y: offset + yourYpos, width: btn.frame.size.width, height: btn.frame.size.height)
}
#objc private func buttonClicked(_ button: UIButton) {
// Action when you tapped the button
}
}

"Use of unresolved indentifier 'self'" with button.addTarget

I am a beginner to Swift. I have created a very simple button component, but when I try to add a function that is tied to the button click, I get the error: "Use of unresolved identifier 'self.'" Here is my code:
import UIKit
import PlaygroundSupport
let containerView = UIView (frame: CGRect(x: 0, y: 0, width: 600, height: 600))
containerView.backgroundColor = UIColor.blue
let button = UIButton (frame: CGRect(x: 100, y: 100, width: 200, height: 200))
button.backgroundColor = UIColor.yellow
button.setTitle("Test Button", for: .normal)
button.setTitleColor(.red, for: .normal)
button.layer.cornerRadius = 10
func ButtonClicked(_ sender: UIButton) {
print()
}
button.addTarget(self, action: #selector(ButtonClicked), for: .touchUpInside)
containerView.addSubview(button)
PlaygroundPage.current.liveView = containerView
Any help would be appreciated greatly, thanks!
As mentioned in the comments, there is no self to reference in your code as you're not working within a class or struct. The first thing you'll want to do is to wrap this stuff up into a class, and reorganize it a bit. I'd suggest going back to Xcode and doing the following:
File > New > Playground…
Select iOS > Single View
Save this new Playground somewhere.
Now, you should have a simple Playground created from a template. Here, you'll be able to see how a new class called MyViewController that inherits from UIViewController is created. Within that, you'll find a function called loadView(). Then, outside the class, you'll see where this new view controller is created and placed into the PlaygroundPage's current liveView.
Ideally, you should be able to click the Play button at the bottom of the code view, and if the Assistant editor is open, you'll see a simple view with a "Hello World!" label in the center of the view. (The assistant button is the one with the two interlocking circles.)
Assuming that runs and works for you, then I'd suggest you start adding your code back in and try to follow the patterns setup in the template. Place your code that sets up the view in the loadView() function, and move the ButtonClicked() function outside of that, but still within the class.
With a few modifications, you should be able to get up and running, and start playing around with Swift. As an example, here's a working version of your Playground code:
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let containerView = UIView (frame: CGRect(x: 0, y: 0, width: 600, height: 600))
containerView.backgroundColor = UIColor.blue
let button = UIButton (frame: CGRect(x: 100, y: 100, width: 200, height: 200))
button.backgroundColor = UIColor.yellow
button.setTitle("Test Button", for: .normal)
button.setTitleColor(.red, for: .normal)
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(ButtonClicked), for: .touchUpInside)
containerView.addSubview(button)
self.view = containerView
}
#objc func ButtonClicked(_ sender: UIButton) {
print("ButtonClicked")
}
}
PlaygroundPage.current.liveView = MyViewController()
Have fun, spend some quality time with the Swift Programming Guide, and things'll start to make sense soon enough.

Detecting clicks on a button in Swift

How can I detect clicks on the following UIKit element in Swift, in an Xcode 6 playground?
let testLabel = UILabel(frame: CGRectMake(0, 0, 120, 40))
testLabel.text = "My Button"
The UILabel class is used just to display text on the screen. Sure you can detect taps (not clicks) on it, but theres a UIKit class specifically crafted to handle actions on the screen, and that's UIButton.
Note: A playground is intended for you to test logic, not events, in your code. If you want to play around with iOS specific stuff, try creating a Single View Application Project under the iOS section from Xcode 6.
Implementing a UIButton, assuming you're inside an iOS Project on Xcode:
var button = UIButton(frame: CGRect(x: 0, y: 0, width: 150, height: 60))
button.backgroundColor = UIColor.blackColor()
button.layer.cornerRadius = 3.0
button.setTitle("Tap Me", forState: .Normal)
button.addTarget(self, action: "buttonTapped", forControlEvents: .TouchUpInside)
Then, on the same ViewController class, create the buttonTapped method:
func buttonTapped() {
println("Button tapped!")
}
With Swift 3, UIButton - as a subclass of UIControl - has a method called addTarget(_:action:for:). addTarget(_:action:for:) has the following declaration:
func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControlEvents)
Associates a target object and action method with the control.
The Playground code below shows how to detect a click on a button:
import PlaygroundSupport
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
// Create button
let button = UIButton(type: UIButtonType.system)
button.setTitle("Click here", for: UIControlState.normal)
// Add action to button
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
// Add button to controller's view
view.addSubview(button)
// Set Auto layout constraints for button
button.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
// trigger action when button is touched up
func buttonTapped(sender: UIButton) {
print("Button was tapped")
}
}
// Display controller in Playground's timeline
let vc = ViewController()
PlaygroundPage.current.liveView = vc

Resources