Using variables in CGRectMake, Swift, UIkit - ios

For an App I'm making i need to use variables to change the size and position of objects (Labels). I've tried var example = CGRectMake(0, 0, 0, 100), hoping it would ignore the zeros (Not really thinking it would though). I then tried:
var example = 100
Label1.frame = CGRectMake(20, 20, 50, example)
I changed the syntax a bit, adding "" and replacing the CGRectMake with CGRect etc, but nothing worked... I don't get what I'm doing wrong here... Help!

Below is the new syntax used since Swift 3.
CGRect(x: 0, y: 0, width: 100, height: 100)

CGRectMake takes CGFloats for all of its arguments. Your sample code should work fine if you specify that example is supposed to be a CGFloat, using a type identifier:
// v~~~~ add this...
var example: CGFloat = 100
Label1.frame = CGRectMake(20, 20, 50, example)
Otherwise, swift infers the type of example to be Int, and the call to CGRectMake fails, cuz it can't take an Int as a parameter...

So, there is many ways to skin the cat. It all depends what your needs and requirements are (maybe you could elaborate a bit on what you are trying to achieve?). But one way to do it could be to set a variable when something happens, and then update the frame of the label. If you added a tap gesture recognizer to your view, and updated your label like so:
let myLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
let tapGestRecog = UITapGestureRecognizer(target: self, action: "handleTap:")
self.view.addGestureRecognizer(tapGestRecog)
}
func handleTap(sender:UIGestureRecognizer) {
let newXposition = sender.locationInView(self.view).x
let newYposition = sender.locationInView(self.view).y
myLabel.frame = CGRectMake(newXposition, newYposition, 200, 200)
}
This is just an example, and a very crude way of doing it. There are many other ways of doing it, but it hopefully gives you an idea of how to achieve it.

Swift allows syntax that Objective-C does not:
var example = 100
label.frame.size.height = example
In objective-C you would have to do it differently:
CGRect frame = label.frame; //Create a temporary rect to hold the frame value
frame.size.height = example;
label.frame = frame;

Related

Avoid redundant dereferencing in iOS

Suppose I want to change size of an uiView: UIView to w,h. I can do it like that:
uiView.frame.size.width = w
uiView.frame.size.height = h
In another system I can avoid replication of dereferencing (which means waste of both size and performance) by keeping a reference in a variable (using Swift syntax):
let ref = uiView.frame.size
ref.width = v
ref.height = h
This however doesn't work in iOS, where CGSize is a structure and therefore is copied when assigned to another value.
Is there a way to avoid redundant dereferencing (something like with(uiView.frame.size){...} available in some languages)
I don't think there is a way to do it exactly because the frame is a value-copied structure. You could set the frame directly as Reiner Melian suggests, but to me that seems even longer and uses dereferencing at least the same amount of time as your approach.
There is a way how to make it simpler this using extensions, but behind the scenes it will again be using dereferencing:
extension UIView {
var width: CGFloat {
get {
return self.frame.size.width
}
set {
self.frame.size.width = newValue
}
}
var height: CGFloat {
get {
return self.frame.size.height
}
set {
self.frame.size.height = newValue
}
}
}
And then you could use:
uiView.width = w
uiView.height = h
on any UIView instance.
This is even simpler:
uiView.frame.size = CGSize(width: w, height: h)
As I understand it, RHS is a temporary value released as soon as the content has been copied to frame structure.

Cannot seem to use CGRectIntegral and CGRectInset functions in Swift

Sorry for the novice question.
But just as the title says, I can't seem to use these functions in Swift 3. I have tried by importing the CoreGraphics library, but to no avail.
Does anyone know why?
Thanks in advance.
The functions are working fine, but their names have changed (a bit):
let frame = CGRect.zero
let x = frame.integral
frame.insetBy(dx: 0, dy: 0)
import CoreGraphics
let rect = CGRect()
let rectIntegral = rect.integral
Thanks:)
Actually you don't need to import CoreGraphics.
In Swift 3 Objective-C function
CGRect CGRectIntegral(CGRect rect)
has become
var integral: CGRect { get }
and
CGRect CGRectInset(CGRect rect, CGFloat dx, CGFloat dy);
has become
func insetBy(dx: CGFloat, dy: CGFloat) -> CGRect
Both API have to be called on the CGRect instance for example
let newFrame = view.frame.insetBy(dx: 10.0, dy:10.0)
A hint to find out yourself
Press ⇧⌘0
Type CGRectIn in the search field
In the popup menu set the language to Objective C
Select one of the functions
Set the language to Swift

Regular Expression to replace CGRectMake

As CGRectMake is not available in swift 3.0 and migrator did not convert it i need to manually replace it and it is used more than 300 times in my code so can anyone help me in this to develop regular expression so i can find and replace code. What i want to do is to convert
CGRectMake(a,a,a,a) here a is some value.
to
CGRect(x: a, y: a, w: a, h: a)
Find by this:
CGRectMake\(([^,]*),([^,]*),([^,]*),([^,]*)\)
and Replace by this:
CGRect\(x:\1, y:\2, w:\3, h:\4\)
Tried it in notepad++
EDIT - With Regex:
CGRectMake\(([^,]*),([^,]*),([^,]*),([a-z|0-9|.|A-Z]*)\)
and replace with
CGRect\(x:\1, y:\2, width:\3, height:\4\)
Using regex we can not get the value of x,y,width,height dynamically.
So Alternative solution to above is,
Replace all the CGRectMake( with
appdelegateobject.CGRectMakeWrapper("
At the end add " only.
Means in your case you will replace CGRectMake(a,a,a,a) to appdelegateobject.CGRectMakeWrapper("a,a,a,a"
where appdelegateobject is the appdelegate shared instance object where you will define CGRectMakeWrapper function having string parameter as shown below :
func CGRectMakeWrapper(str: String) -> CGRect {
var rect = CGRectZero
if(str.characters.count > 0)
{
var arr = str.componentsSeparatedByString(",")
if(arr.count == 4)
{
rect = CGRect(x: CGFloat((arr[0] as NSString).doubleValue), y: CGFloat((arr[1] as NSString).doubleValue), width: CGFloat((arr[2] as NSString).doubleValue), height: CGFloat((arr[3] as NSString).doubleValue))
}
}
return rect
}
var rect = "10.0,10.0,100,100" //String
var rect1 = CGRectMakeWrapper(rect) //CGRect
I have shown sample string as rect and passed to CGRectMakeWrapper function which will return a rect. You can define this CGRectMakeWrapper function in common class which is accessible to all classes(e.g Appdelegate file).
I have one different way to solve this problem.
Step 1
In the following line
CGRectMake(a,a,a,a)
Just replace CGRectMake with CGRectMakeCustom so all will look like
CGRectMakeCustom(a,a,a,a)
Step 2
Create new Global function in the project
as follows
func CGRectMakeCustom(x: Double, y: Double, width: Double, height: Double) -> CGRect
{
return CGRect(x: x, y: y, width: width, height: height)
}
In this way it will be easy for you to start woking on Swift3
You can change mode to regular expression while searching and search for:
CGRectMake\(([^,]*),([^,]*),([^,]*),([^,]*)\)
which should be replaced by
CGRect\(x:\1, y:\2, w:\3, h:\4\)

Swift Change UIView Image

I am trying to make a basic game for iOS10 using swift 3 and scenekit. In one part of my games code I have a function that adds fishes to the screen, and gives each one a certain tag so i can find them later:
let fish = UIImageView(frame: CGRect(x: 0, y: 0, width: CGFloat(fishsize.0), height: CGFloat(fishsize.1)))
fish.contentMode = .scaleAspectFit
fish.center = CGPoint(x: CGFloat(fishsize.0) * -0.6, y: pos)
fish.animationImages = fImg(Fishes[j].size, front: Fishes[j].front)
fish.animationDuration = 0.7
fish.startAnimating()
fish.tag = j + 200
self.view.insertSubview(fish, belowSubview: big1)
What I would like is to be able to, at a certain point, recall the fish and
Change the images shown, and
Stop the animation.
Is this possible? I've been trying it with var fish = view.viewWithTag(killer+200)! but from this I can't seem to change any image properties of the new variable fish.
Any help would be much appreciated.
Tom
Try to cast the UIView to UIImageView like this.
if let fish = view.viewWithTag(killer+200) as? UIImageView {
//Perform your action on imageView object
}

Batch variable creation in Swift

So im writing my first lines of code in Swift, and i want to make a game where you need to tilt the device to make a gravity shift and by doing so make a ball drop to the floor while maneuvering around obstacles.
Ive been looking up different methods, and I found one where you can make the obstacles by just using let, For example (Im using UIKit)
let barrier1 = UIView(frame: CGRect(x: 0, y: 300, width: 20, height: 20))
barrier1.backgroundColor = UIColor.redColor()
view.addSubview(barrier1)
Its quite a bit of code to declare every barrier this way, and I was hoping if there was a way of doing this in a while loop where every time the loop runs, x = x + 1 is stated and you make variables that way in batch. Can anyone help me? Thanks!
This is what arrays are for. Declare a variable called barriers of type [UIView] and then append each new barrier to this array.
var barriers:[UIView] = []
for i in 1...20 {
let newbarrier = UIView(frame: CGRect(x: 0, y: 300 + i * 30, width: 20, height: 20))
newbarrier.backgroundColor = UIColor.redColor()
view.addSubview(newbarrier)
barriers.append(newbarrier)
}
// Now you can refer to each barrier by its index: barriers[0], barriers[1]
// up to barriers[19]

Resources