Getting to grip with the high level ways of Xcode + Swift - ios

Recently, I have started to study Swift with story board, Xcode, etc.
I am struggling to understand the principals of ViewController code, as it seems to miss a lot of essentials - presumably to try and make things more simple - but it just isn't for programmers who have come from else where.
import UIKit
class ViewController: UIViewController {
//Properties
#IBOutlet weak var textFieldName: UITextField!
#IBOutlet weak var submit: UIButton!
#IBOutlet weak var submit1: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
//Actions
#IBAction func onSubmit(sender: UIButton) {
switch(sender){
case submit:
print("only 1");
case submit1:
print("222");
default:
print("nothing");
}
}
}
After following a basic tutorial, I have tried playing around on my own to test out my understanding. The IBOutlets, which define elements of the storyboard requires me to actually drag and drop it into the code in order for it to correctly correspond to the element. When I just type
#IBOutlet weak var submit1: UIButton!
Without having dragged it from storyboard - it does not work / correspond. So essentially there is more backend that I do not have control over?
Also, Actions. How come it prints without the method being called?! I must be missing something obvious - something to do with the attributes?
I want to be able to code things myself, and identify elements/buttons/etc myself without dragging and dropping, and not seeing the associations - submit1 and submit, at the moment, are set to the exact same thing: UIButton!
I am aware and accept my confusion and interpretation is clearly flawed and wrong. But could someone shed some light on the lower level activities of ViewController?
Thanks.

If you don't want to drag and drop you can write, i don't see where is the problem
let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
button.backgroundColor = .greenColor()
button.setTitle("Test Button", forState: .Normal)
button.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
self.view.addSubview(button)

Related

Is there a way to programmatically associate a variable and a target object with the control in swift?

I'm creating a slider programmatically due to and Xcode bug, (don't let me center the thumb when I change the slider values, so I decided to do it using code) and I want to have a variable which saves the slider value. Is there a way to associate the variable and the target object with the control, similar to "addTarget", but instead of an action, its a variable?
I don't know if I explained myself but tell me if I need to be more specific. Thanks in advance :) for helping me.
This is my code:
import UIKit
class ViewController: UIViewController {
var slider: UISlider!
#IBOutlet weak var sliderVar: UISlider!
var currentSliderValue = 0
override func viewDidLoad() {
super.viewDidLoad()
slider = UISlider(frame: CGRect(x: 98, y: 173, width: 699, height: 30))
slider.center = self.view.center
slider.minimumValue = 1
slider.maximumValue = 100
slider.value = 50
slider.isContinuous = true
slider.addTarget(self, action: #selector(sliderMoved(_:)), for: UIControl.Event.valueChanged)
self.view.addSubview(slider)
}
#IBAction func sliderMoved(_ sender: UISlider) {
currentSliderValue = lroundf(sender.value)
}
}
My function “sliderMoved” changes the sliderCurrentValue variable, but this var won’t change until I use the slider and move it. I also have a button there, that when you touch it up it shows the slider value, but the “sliderCurrentValue” only changes its value when the slider is moved. I was thinking of creating an IBOutlet but I don’t know how to connect this one with the slider.
As far as I understand you need to bind variable to slider's value. There are several ways to achieve it. There is one way. Declare variable with custom setters and getters
class ViewController: UIViewController {
var slider: UISlider!
var sliderValue: Float {
set {
// use optional chaining here helps avoid crashes
slider?.setValue(newValue, animated: true)
}
get {
// if slider control hasn't created yet you need to return some dummy value
slider?.value ?? -1
}
}
func viewDidLoad() {
// your current implementation here
}
}

Customise tool bar item with label and image?

I am trying to do a custom toolbar that shows image and label but changes according to which view it is in. I have scoured the internet and read and tried everything I could find on the subject.
I figured that putting a tab bar was not a solution since it can't change for every view (or can it?).
Last time I asked I was marked duplicate and quoted Set image and title for bad button item?. I tried that but I could not get that to work at all. Ideally, I wanted a storyboard solution.
I'll show what I have done and tried with so far. What am I doing wrong? Have I missed something? I can't get the title to show on the toolbar item.
Xcode main.storyboard current toolbar version:
Sketch version (what I want it to look like):
What I hope it will change to in subsequent view:
Code:
class ViewController: UIViewController {
#IBOutlet weak var toolbar: UIToolbar!
#IBOutlet weak var leftBarButton: UIBarButtonItem!
var middleBarButton: UIBarButtonItem!
var rightBarButton: UIBarButtonItem!
var rightBarButton2: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView()
let button = UIButton(type: .system)
button.semanticContentAttribute = .forceRightToLeft
button.setImage(UIImage(named: "IconHelp"), for: .normal)
button.setTitle("Help", for: .normal)
button.addTarget(self, action: #selector(about), for: .touchUpInside)
button.sizeToFit()
view.addSubview(button)
view.frame = button.bounds
// var items = self.toolbar.items
// items![0] = UIBarButtonItem(customView: view)
leftBarButton = UIBarButtonItem(customView: button)
Any help would be much appreciated as I've tried to solve this all week. :P

Why does my UIButton affect my UIImageView in Swift?

I'm building a simple app in Swift, and the app contains a png image, a UISegmentedControl, and a UIButton. Selecting different controls on the UISegmentedControl resizes an image of a pizza. When I click on "Large" in the UISegmentedControl, and then I press a button on the interface called submitOrderDisplay, it shrinks the image from its large size to its small size. I know it has something to do with the setTitle method I am using at the very bottom of the code, but I don't understand why that causes the image to reset to its default small size. If I remove the setTitle method, the resizing does not occur after I click the UIButton. I don't want the image to change size after the button is pressed. How do I achieve that?
import UIKit
class SecondViewController: UIViewController{
#IBOutlet weak var sizeChoiceControl: UISegmentedControl!
#IBOutlet weak var submitOrderDisplay: UIButton!
#IBOutlet weak var myImageView: UIImageView!
#IBAction func sizeSelected() {
if(sizeChoiceControl.titleForSegmentAtIndex(sizeChoiceControl.selectedSegmentIndex)! == "Small"){
myImageView.setHeight(height: 85)
myImageView.setWidth(width: 85)
myImageView.setX(x: 146)
myImageView.setY(y: 63)
}
else if(sizeChoiceControl.titleForSegmentAtIndex(sizeChoiceControl.selectedSegmentIndex)! == "Medium"){
myImageView.setHeight(height: 100)
myImageView.setWidth(width: 100)
myImageView.setX(x: 139)
myImageView.setY(y: 55)
}
else if(sizeChoiceControl.titleForSegmentAtIndex(sizeChoiceControl.selectedSegmentIndex)! == "Large"){
myImageView.setHeight(height: 115)
myImageView.setWidth(width: 115)
myImageView.setX(x: 131)
myImageView.setY(y: 48)
}
}
#IBAction func SubmitOrderClicked(sender: UIButton) {
submitOrderDisplay.setTitle("Update Order", forState: UIControlState.Normal)
}
}
Write the configuration of the button inside the viewDidLoad function:
submitOrderDisplay.setTitle("Update Order", forState: UIControlState.Normal)
I understand that you want to put the title Update Order.
If you want to change the title when pressed, you must call it for another State of the button like:
submitOrderDisplay.setTitle("Update Order", forState: UIControlState.Highlihgted)
If you change the configuration of the button for different states when an event happens, that must be why the size is ressetting.

Xcode how to connect view to view using button ? (swift)

I'm making a custom keyboard using swift on Xcode.
I have created some views(xib files) which are of keyboards.
and I wanna connect these views each other like when I press [123]button, the view changes to the numeric one so I can type numbers :)
Actually I finished globe button(which is next keyboard button which is auto-created when I added custom keyboard target) but can't understand the codes ;-;
What I want to do is to connect button(as an IBOutlet or IBAction) with view(xib)
Take two views in xib or storyboard and IBOutlet them. One view has the buttons for alphabets and other view has buttons for numbers.
You have to do code something like below :
#IBOutlet var alphabelView: UIView!
#IBOutlet var numericView: UIView!
#IBOutlet var toggleBtn: UIButton!
btn.setTitle("ABC", forState: .Normal)
btn.setTitle("123", forState: .Selected)
toggleBtn.addTarget(self, action: #selector(self.toggleButtonsClicked(_:)), forControlEvents: .TouchUpInside)
Numeric view will be hidden initially. When user press on 123 do code like below lines of code:
func toggleButtonsClicked(button: UIButton) {
button.selected = !butto.selected
alphabelView.hidden = true
numericView.hidden = false
}

Re-write some basic swift code, with big if-statements

I am working on a project, with a UITabBarcontroller, in Xcode using swift code.
In this project the users can (among other stuff) choose their favorite images. These favorite images will be set on 30 buttons I have on my favorites UIViewController.
To accomplish what I want, I developed some very basic code: I assigned 30 IBOutlets for the 30 buttons and I made 30 (big) if-statements. It in fact works, but I know this code can be done in a simpler and more concise manner. And I am not yet able to do that.
I really want to learn, so can anybody help me with a way to rewrite this code? Help is much appreciated :). Just a push in the right direction would already be great
Should I for example assign tag values to the 30 buttons, and ‘find’ the appropriate buttons with .viewWithTag (instead of the 30 IBOutlets). And should I for example use some sort of loop for dealing with the different counts of the array? (see below)
Here is my code:
// I have created a subclass of UITabBarController
class TabBarData: UITabBarController {
/* In this class I have initialized an empty array to share between the various tabs.
The array will be populated with the favorites chosen by the user. */
var array = [Int]()
}
/* There are multiple ViewControllers in my project that have the same
code for adding a favorite. So for now I describe one example ViewController */
class exampleVC: UIViewController {
/* A variable that identifies the image by the number. There a a few
hundred images in the project, every images has its own identifying number */
var imageNumber = 0
// This function will execute if user adds a favorite:
func userAddedFavorite(imageNumber: Int) {
// The ViewController within the TabBarController getting acces to the properties
if let tbc = self.tabBarController as? TabBarData {
// The Array can not be bigger then a count of 30:
if tbc.array.count < 30 {
// When a user adds a new favorite image, the array gets filled with a new value:
tbc.array.append(imageNumber)
// Now I set the button images, in viewWillAppear, for my favorites VC:
class Favorites: UIViewController {
// IBOutlets for the 30 buttons
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
// etcetera…
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let tbc = self.tabBarController as? TabBarData {
if tbc.array.isEmpty {
print("The user has no Favorites at the moment. The array is empty")
} else if tbc.array.count == 1 {
// At the moment the images in my project have been named: test1/test2/test3 etc...
button1.setImage(UIImage(named: "test\(tbc.array[0])"), forState: .Normal)
} else if tbc.array.count == 2 {
button1.setImage(UIImage(named: "test\(tbc.array[0])"), forState: .Normal)
button2.setImage(UIImage(named: "test\(tbc.array[1])"), forState: .Normal)
} else if tbc.array.count == 3 {
button1.setImage(UIImage(named: "test\(tbc.array[0])"), forState: .Normal)
button2.setImage(UIImage(named: "test\(tbc.array[1])"), forState: .Normal)
button3.setImage(UIImage(named: "test\(tbc.array[2])"), forState: .Normal)
} else {
print("etcetera.....,the if-statements getting bigger each count up......")
}
Instead of making 30 IBOutlets (one for each button,) make a single IBOutletCollection that holds all thirty:
#IBOutlet var buttons: [UIButton]!
Then you can:
for (index, item) in tbc.array.enumerate() {
buttons[index].setImage(UIImage(named: "test\(item)"), forState: .Normal)
}

Resources