Generate a new image on a button press in Swift AppleWatch - image

Okay so I have 4 images, and they are named in sequence 'colour1.jpg', colour2.jpg, 'colour3.jpg', 'colour4.jpg'. Each of these images will act as a button background image.
The idea is there are 4 buttons on the screen, and each time one of the buttons is pressed, the images all change randomly on each of the buttons.
I am using the arc4random_uniform to randomise the images. But it doesn't work, at the moment, if the user presses one of the buttons, a random image is chosen, but it is identical across all 4 buttons. and then it won't ever change from that image. ie. if you press the same or another button, nothing happens. It just remains on the previous image.
I am new to swift so appreciate your patience with me, but would really like to learn where I'm going wrong.
class InterfaceController: WKInterfaceController {
#IBOutlet var blueColour: WKInterfaceButton!
#IBOutlet var pinkColour: WKInterfaceButton!
#IBOutlet var greenColour: WKInterfaceButton!
#IBOutlet var yellowColour: WKInterfaceButton!
var randomImageA1 = arc4random_uniform(4)
var randomImageA2 = arc4random_uniform(4)
var randomImageA3 = arc4random_uniform(4)
var randomImageA4 = arc4random_uniform(4)
var randomImageB1 = arc4random_uniform(4)
var randomImageB2 = arc4random_uniform(4)
var randomImageB3 = arc4random_uniform(4)
var randomImageB4 = arc4random_uniform(4)
var randomImageC1 = arc4random_uniform(4)
var randomImageC2 = arc4random_uniform(4)
var randomImageC3 = arc4random_uniform(4)
var randomImageC4 = arc4random_uniform(4)
var randomImageD1 = arc4random_uniform(4)
var randomImageD2 = arc4random_uniform(4)
var randomImageD3 = arc4random_uniform(4)
var randomImageD4 = arc4random_uniform(4)
#IBAction func onePressed() {
blueColour.setBackgroundImageNamed("colour\(randomImageA1).jpg")
pinkColour.setBackgroundImageNamed("colour\(randomImageA2).jpg")
greenColour.setBackgroundImageNamed("colour\(randomImageA3).jpg")
yellowColour.setBackgroundImageNamed("colour\(randomImageA4).jpg")
}
#IBAction func twoPressed() {
blueColour.setBackgroundImageNamed("colour\(randomImageB1).jpg")
pinkColour.setBackgroundImageNamed("colour\(randomImageB2).jpg")
greenColour.setBackgroundImageNamed("colour\(randomImageB3).jpg")
yellowColour.setBackgroundImageNamed("colour\(randomImageB4).jpg")
}
#IBAction func threePressed() {
blueColour.setBackgroundImageNamed("colour\(randomImageC1).jpg")
pinkColour.setBackgroundImageNamed("colour\(randomImageC2).jpg")
greenColour.setBackgroundImageNamed("colour\(randomImageC3).jpg")
yellowColour.setBackgroundImageNamed("colour\(randomImageC4).jpg")
}
#IBAction func fourPressed() {
blueColour.setBackgroundImageNamed("colour\(randomImageD1).jpg")
pinkColour.setBackgroundImageNamed("colour\(randomImageD2).jpg")
greenColour.setBackgroundImageNamed("colour\(randomImageD3).jpg")
yellowColour.setBackgroundImageNamed("colour\(randomImageD4).jpg")
}

You are only calling randomImage = arc4random_uniform(5) one time. If that function randomly chooses an image for you, then you need to call it before every call to setBackgroundImage()
Your success of randomness will also depend on how you are randomizing your image within randomImage = arc4random_uniform(5). Hard to say whether that will always return the same image or not without seeing your implementation of randomness.
Example:
#IBOutlet var blueColour: WKInterfaceButton!
#IBOutlet var pinkColour: WKInterfaceButton!
#IBOutlet var greenColour: WKInterfaceButton!
#IBOutlet var yellowColour: WKInterfaceButton!
var randomImage
#IBAction func onePressed() {
randomImage = arc4random_uniform(4)
blueColour.setBackgroundImageNamed("colour\(randomImage).jpg")
randomImage = arc4random_uniform(4)
pinkColour.setBackgroundImageNamed("colour\(randomImage).jpg")
randomImage = arc4random_uniform(4)
greenColour.setBackgroundImageNamed("colour\(randomImage).jpg")
randomImage = arc4random_uniform(4)
yellowColour.setBackgroundImageNamed("colour\(randomImage).jpg")
}

Related

Swift 2 how to expand and collapse a view?

I have scrollView in which if there is no data, I need to hide (collapse the space occupied by it) so that the lower view can come upwards.
I tried this code with no luck. Please help me.
if(dataForScroll==0){
var newFrame:CGRect = self.myScroll.frame;
newFrame.size.height = 0;
self.myScroll.frame = newFrame
}
A simple example with Swift 3 version, i think it might be solves your problem. Let me know if have any queries
#IBOutlet var mainScrollView: UIScrollView!
#IBOutlet var view1: UIView!
#IBOutlet var view2: UIView!
#IBOutlet var view3: UIView!
var data1 = NSArray()
var data2 = NSArray()
var data3 = NSArray()
func setFrame()
{
// data = Something you need to get
if data1.count == 0
{
self.view1.frame.size.height = 0
}
else
{
// return its actual height you need
}
if data2.count == 0
{
self.view2.frame.size.height = 0
}
else
{
// return its actual height you need
}
if data3.count == 0
{
self.view3.frame.size.height = 0
}
else
{
// return its actual height you need
}
var frame = self.view1.frame
frame.origin.y = 5
self.view1.frame = frame
frame = self.view2.frame
frame.origin.y = self.view1.frame.origin.y + self.view1.frame.size.height + 5
self.view2.frame = frame
frame = self.view3.frame
frame.origin.y = self.view2.frame.origin.y + self.view2.frame.size.height + 5
self.view3.frame = frame
var scrollHeight:CGFloat = 0.0
var contentRect:CGRect = CGRect.zero
for views in self.mainScrollView.subviews
{
let subView:UIView = views
contentRect = contentRect.union(subView.frame)
print(subView.frame.size.height)
scrollHeight = scrollHeight + subView.frame.size.height
}
self.mainScrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: scrollHeight + 20) // the "+ 20" reamains the spaces between the views, you can change as per your need
}

How to programmatically create several NSTextFields?

I have an array of CGPoints. I need a personal label for every fourth point in array, so I need to create several NSTextFields programmatically. I can add points with mouse clicks and can create as many points as I wish. Labels for these points must be all active to show text for user simultaneously. How can I do it?
(macOS, Xcode 7, Swift 2)
Here's my code:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
#IBOutlet weak var drawView: DrawView!
#IBOutlet weak var view: NSView!
let label = NSTextField(frame: NSMakeRect(0,0,100,50))
var pointsArray: [CGPoint] = []
func applicationWillUpdate(aNotification: NSNotification) {
label.backgroundColor = NSColor.clearColor()
label.bezeled = false
label.stringValue = "\(pointsArray.count/4)"
var multiple = (1...25).map { _ in label }
for index in 0..<(pointsArray.count/4) {
let point = CGPoint(x: pointsArray[index*4].x, y: pointsArray[index*4].y)
label.frame = CGRect(origin: point, size: CGSize(width: label.bounds.width, height: label.bounds.height))
let sticker = multiple[index]
view.addSubview(sticker)
}
}
}
At runtime I see only one label but I need to see several labels simultaneously (on every fourth CGPoint). If I have 100 CGPoints I must have 25 labels.
I see only one label
Now that I've straightened out your curly braces and indentation, it's easy to see why. Your loop is incorrectly constructed, so that you create one label and change its frame four times. You need to create four separate labels with four separate frames.
Code for creating several NSTextFields:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var drawView: DrawView!
var pointsArray: [CGPoint] = []
var label1 = NSTextField(frame: NSMakeRect(0,0,100,50))
var label2 = NSTextField(frame: NSMakeRect(0,0,100,50))
var label3 = NSTextField(frame: NSMakeRect(0,0,100,50))
// ....................................................
var label25 = NSTextField(frame: NSMakeRect(0,0,100,50))
override func awakeFromNib() {
super.awakeFromNib()
var labelArray = [label1, label2, label3, ....., label25]
for i in 0 ..< (pointsArray.count / 4) {
labelArray[i].backgroundColor = NSColor.clearColor()
labelArray[i].bezeled = false
labelArray[i].stringValue = "\(i + 1)"
let point = CGPoint(x: (pointsArray[i * 4].x),
y: (pointsArray[i * 4].y))
var originPoint: [CGPoint] = []
originPoint.append(point)
labelArray[i].frame = .init(origin: originPoint[0],
size: CGSize(width: labelArray[i].bounds.width,
height: labelArray[i].bounds.height))
self.view.addSubview(labelArray[i])
}
}
}

For loop for multiple UITextFields

I have multiple UITextFields and I'm making the same changes to the border, radius and color.
#IBOutlet weak var answer1Text: UITextField!
#IBOutlet weak var answer2Text: UITextField!
#IBOutlet weak var answer3Text: UITextField!
#IBOutlet weak var answer4Text: UITextField!
#IBOutlet weak var answer5Text: UITextField!
self.answer1Text.layer.cornerRadius = 5
self.answer1Text.layer.borderWidth = 2
let borderColor = UIColor(colorLiteralRed: 125.0/255.0, green:210.0/255.0, blue: 238.0/255.0, alpha: 1.0)
self.answer1Text.layer.borderColor = borderColor.CGColor
Repeating the code five times for each textfield is very inefficient. I was thinking a for loop would be the best solution but I can't figure out how to replace the int in the text field name. For example,
for var i = 0; i < 6; i++ {
self.answer1Text.layer.cornerRadius = 5 // Not sure how to replace the 1 here
}
If a for loop is the best solution, how do you do so? If not, what's the best way to implement?
Thanks!
You need to store all your answerTexts to NSArray and loop through this array. In iteration of loop you can reach to your UITextField object from an array by index and set your properties:
var answerTextsArray = [self.answer1Text, self.answer2Text, self.answer3Text, self.answer4Text, self.answer5Text]
for var i = 0; i < answerTextsArray!.count; i++ {
var myTextField = answerTextsArray[i]
myTextField.layer.cornerRadius = 5
myTextField.layer.borderWidth = 2
let borderColor = UIColor(colorLiteralRed: 125.0/255.0, green: 210.0/255.0, blue: 238.0/255.0, alpha: 1.0)
myTextField.layer.borderColor = borderColor.CGColor
}

Resizing the window according to a variable swift

I have a NSViewController and a variable num. I want to change the size of the window dynamically according to that variable. Is there any way to do that in swift?
Let's say your window has an IBOutlet named "window", and your dynamic number is named "myDynamicNumber":
func resize() {
var windowFrame = window.frame
let oldWidth = windowFrame.size.width
let oldHeight = windowFrame.size.height
let toAdd = CGFloat(myDynamicNumber)
let newWidth = oldWidth + toAdd
let newHeight = oldHeight + toAdd
windowFrame.size = NSMakeSize(newWidth, newHeight)
window.setFrame(windowFrame, display: true)
}
In Swift 3 to resize the window you use setFrame.
An example from the ViewController:
func resizeWin(size:(CGFloat,CGFloat)){
self.view.window?.setFrame(NSRect(x:0,y:0,width:size.0,height:size.1), display: true)
}
I needed to toggle viewing a text view so I overlaid the window an invisible view - hideRect just short of the text view; in this way I can resize to the smaller (hideRect) and restore later to the original size - origRect. Hide and original rect captured at viewDidLoad(). Swift 3/Xcode 8.3.3
// class global contants
let kTitleUtility = 16
let kTitleNormal = 22
#IBOutlet var hideView: NSView!
var hideRect: NSRect?
var origRect: NSRect?
#IBAction func toggleContent(_ sender: Any) {
// Toggle content visibility
if let window = self.view.window {
let oldSize = window.contentView?.bounds.size
var frame = window.frame
if toggleButton.state == NSOffState {
frame.origin.y += ((oldSize?.height)! - (hideRect?.size.height)!)
window.setFrameOrigin(frame.origin)
window.setContentSize((hideRect?.size)!)
window.showsResizeIndicator = false
window.minSize = NSMakeSize((hideRect?.size.width)!,(hideRect?.size.height)!+CGFloat(kTitleNormal))
creditScroll.isHidden = true
}
else
{
let hugeSize = NSMakeSize(CGFloat(Float.greatestFiniteMagnitude), CGFloat(Float.greatestFiniteMagnitude))
frame.origin.y += ((oldSize?.height)! - (origRect?.size.height)!)
window.setFrameOrigin(frame.origin)
window.setContentSize((origRect?.size)!)
window.showsResizeIndicator = true
window.minSize = NSMakeSize((origRect?.size.width)!,(origRect?.size.height)!+CGFloat(kTitleNormal))
window.maxSize = hugeSize
creditScroll.isHidden = false
}
}
}
This also preserved the widow's visual origin, and sizing minimum.

2 Text boxes optional inserting in one or both

I have two text fields to insert numbers, I am trying to find out how it could work out if the user is just inserting one value in one of the text fields or two. I tried to do it with if statements, but that does not work. Looks also like I have a mistake some where in the code I get the issue: fatal error: unexpectedly found nil while unwrapping an Optional value I would be happy for some help - as you can see I am a beginner in swift coding. Thanks so Far!
#IBOutlet var budgetShow: UILabel!
#IBOutlet var restShow: UILabel!
#IBOutlet var daysShow: UILabel!
#IBOutlet var dayssShow: UILabel!
#IBOutlet var inputDays: UITextField!
#IBOutlet var inputBudget: UITextField!
#IBAction func findResult(sender: AnyObject) {
var inputBudgetInt = inputBudget.text.toInt()
var inputDaysInt = inputDays.text.toInt()
var dailyRate = 85.50
if inputDays != nil {
var days = Double(inputBudgetInt!) / dailyRate
var daysCosts = dailyRate * days
var daysShow = Int(days)
var costsShow = Int(daysCosts)
dayssShow.text = "For \(costsShow) you can stay \(daysShow) Days."
}
if inputBudget != nil {
var budget = dailyRate / Double(inputBudgetInt!)
var budgetShow = Int(budget)
daysShow.text = "You need /(budgetShow)"
}
var daysBudget = Double(inputBudgetInt!) / Double(inputDaysInt!)
var show = daysBudget - dailyRate
var costs = Double(inputDaysInt!) * dailyRate
var rest = Double(inputBudgetInt!) - costs
var could = Double(inputBudgetInt!) / dailyRate
var couldShow = Int(could)
var restedShow = Int(rest)
var costShow = Int(costs)
var dayShow = Int(inputDaysInt!)
if show > 0 {
budgetShow.text = "For \(dayShow) Days you need \(costShow) €"
restShow.text = "Rest Budget after \(dayShow) Days is \(restedShow) €"
daysShow.text = "With your budget you could stay up to \(couldShow) days"
} else {
budgetShow.text = "Change your budget or days"
}
}
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.
}
}
One way to handle optionals safely is if let, like follows:
if let inputBudgetInt = inputBudgetInt {
// safely use it without need for "!" or "?"
var days = Double(inputBudgetInt) / dailyRate
}
This basically means "if this optional has a value, unwrap it and use it here".
I like to keep the name the same personally, you can use a different name if you want.
Another way is using "?", especially good for chaining. If you have a reference to a cell for example:
cell.textField?.text = "Foo"
If textField (optional) has no value, this line silently does nothing.
You should avoid "!" as much as possible as it can easily cause a crash. Only if you are 100% sure it has a value should you risk it. As a beginner I would stick to if let to make sure your optionals have values.

Resources