Why the second "if" is not working? - ios

I am trying to populate a view and I am writing the code of this view. The code:
class DetailViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var tituloView: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
var txtTitulo: String?
var txt1: String?
var imageView: UIImageView?
var img1: String?
var txt2: String?
var texto2: String?
var imageView2: UIImageView?
var img2: String?
var txt3: String?
var img3: String?
var txt4: String?
var img4: String?
var arrayHeights: [Int] = []
override func viewDidLoad() {
super.viewDidLoad()
tituloView.text = txtTitulo
tituloView.textAlignment = .Center
tituloView.font = UIFont(name: "HelveticaNeue-UltraLight", size: 40)
scrollView.zoomScale = 1
var paragraphStyle1 = NSMutableParagraphStyle()
paragraphStyle1.alignment = NSTextAlignment.Justified
var attributedString1 = NSAttributedString(string: txt1!,
attributes: [
NSParagraphStyleAttributeName: paragraphStyle1,
NSBaselineOffsetAttributeName: NSNumber(float: 0)
])
let texto1 = UILabel(frame: CGRectMake(154, -55, 697, 200))
texto1.attributedText = attributedString1
texto1.numberOfLines = 0
texto1.font = UIFont(name: "HelveticaNeue-UltraLight", size: 28)
texto1.lineBreakMode = .ByWordWrapping
texto1.sizeToFit()
scrollView.addSubview(texto1)
let imagem = UIImage(named: img1!)
let imageView = UIImageView(image: imagem)
imageView.frame = CGRect(x: 320, y: texto1.frame.size.height, width: 400, height: 250)
imageView.contentMode = .ScaleAspectFit
scrollView.addSubview(imageView)
if (txt2 != nil) {
var paragraphStyle2 = NSMutableParagraphStyle()
paragraphStyle2.alignment = NSTextAlignment.Justified
var attributedString2 = NSAttributedString(string: txt2!,
attributes: [
NSParagraphStyleAttributeName: paragraphStyle2,
NSBaselineOffsetAttributeName: NSNumber(float: 0)
])
let texto2 = UILabel(frame: CGRectMake(164, imageView.frame.origin.y + imageView.frame.size.height + 20, 697, 200))
texto2.attributedText = attributedString2
texto2.numberOfLines = 0
texto2.font = UIFont(name: "HelveticaNeue-UltraLight", size: 28)
texto2.lineBreakMode = .ByWordWrapping
texto2.sizeToFit()
scrollView.contentSize = CGSizeMake(texto1.frame.size.width, texto1.frame.size.height + imageView.frame.size.height + texto2.frame.size.height + 20)
scrollView.addSubview(texto2)
if (img2 != nil) {
let imagem2 = UIImage(named: img2!)
let imageView2 = UIImageView(image: imagem2)
imageView2.frame = CGRect(x: 320, y: texto2.frame.origin.y + texto2.frame.size.height, width: 400, height: 250)
imageView2.contentMode = .ScaleAspectFit
scrollView.contentSize = CGSizeMake(texto1.frame.size.width, texto1.frame.size.height + imageView.frame.size.height + imageView2.frame.size.height + texto2.frame.size.height + 20)
scrollView.addSubview(imageView2)
} else {
scrollView.contentSize = CGSizeMake(texto1.frame.size.width, texto1.frame.size.height + imageView.frame.size.height)
}
}
scrollView.scrollEnabled = true
}
}
The problem is: if the img2 is nil, this code is not executed and my scrollView is not set properly:
var paragraphStyle2 = NSMutableParagraphStyle()
paragraphStyle2.alignment = NSTextAlignment.Justified
var attributedString2 = NSAttributedString(string: txt2!,
attributes: [
NSParagraphStyleAttributeName: paragraphStyle2,
NSBaselineOffsetAttributeName: NSNumber(float: 0)
])
let texto2 = UILabel(frame: CGRectMake(164, imageView.frame.origin.y + imageView.frame.size.height + 20, 697, 200))
texto2.attributedText = attributedString2
texto2.numberOfLines = 0
texto2.font = UIFont(name: "HelveticaNeue-UltraLight", size: 28)
texto2.lineBreakMode = .ByWordWrapping
texto2.sizeToFit()
scrollView.contentSize = CGSizeMake(texto1.frame.size.width, texto1.frame.size.height + imageView.frame.size.height + texto2.frame.size.height + 20)
scrollView.addSubview(texto2)
Why is this happening? If I img2 is not nil, the code runs with no problems. I added a println to see if the code inside the if statements were executed, and it was.
All infos (txtTitulo, txt1, imageView, txt2....) are being sent by another View Controller through a segue.
This view, the DetailViewController was created in StoryBoard with a label and a scrollView, the rest was added programmatically as you can see here.
I am sorry if this problem might seem too easy, but this is my first iOS app. Thanks for answering!

In a comment, you said:
The problem here is that when this happens, I mean, when the img2 is
nil, the
scrollView.contentSize = CGSizeMake(texto1.frame.size.width,
texto1.frame.size.height + imageView.frame.size.height +
texto2.frame.size.height + 20)
never gets executed. See what I am saying?
That code is not being executed because you told it not to. You have an if statement that says if img2 != nil and then a block of code that is only run if img2 != nil. Now you're asking why that code isn't executed when img2 == nil?
The answer is "Because that's how if statements work."

Related

How to check current font size of UILabel?

I have 3 UILabels and I want to set same (the smallest one from all of 3 possibilities) font for all of them. What is the problem? I don't know how to check the current font - each of UILabels use Autoshrink with minimal font scale and lines amount equaled to 0. The text of UILabels is set in ViewDidLoad() method (there are many combinations of possible label texts).
I tried to get the current font size with UILabel.font.pointSize property (called in viewDidAppear() method) and than compare all of them. The problem is that that UILabel.font.pointSize returns not current value of UILabel text font size (after Autoshrink has been done) but the value that is set in storyboard.
I'm totally out of ideas so thanks for the help!
Greetings, John
use this extention
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.height)
}
}
get height
height = strDesc.height(withConstrainedWidth: UIScreen.main.bounds.size.width - 160, font: UIFont.systemFont(ofSize: 14.0))
This is one way to get the current size of the UILabel pointsize although I know of more ways if this does not work. This is the cleanest and fastest. See example and extension included.
import UIKit
class ViewController: UIViewController {
lazy var label1 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: 80, width: self.view.bounds.width - 40, height: 40))
lbl.text = "This is some large text to make it fit to size with a big font size"
lbl.font = UIFont.systemFont(ofSize: 50, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
lazy var label2 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: label1.frame.maxY + 5, width: self.view.bounds.width - 40, height: 40))
lbl.text = "This is one line"
lbl.font = UIFont.systemFont(ofSize: 20, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
lazy var label3 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: label2.frame.maxY + 10, width: self.view.bounds.width - 40, height: 80))
lbl.text = "This is some large text to make it fit to size with a big font size"
lbl.font = UIFont.systemFont(ofSize: 100, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.addSubview(label1)
self.view.addSubview(label2)
self.view.addSubview(label3)
var minSize : CGFloat = .greatestFiniteMagnitude
for sub in self.view.subviews{
if let lbl = sub as? UILabel{
//get the size
let font = lbl.adjustedFont()
print("the size is \(font.pointSize)")
minSize = min(font.pointSize,minSize)
}
}
print("the minimum for all fonts is \(minSize)")
print("i am going to delay for 3 seconds and then reset all the labels to the minimum size :)")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {
for sub in self.view.subviews{
if let lbl = sub as? UILabel{
lbl.font = lbl.font.withSize(minSize)
}
}
}
}
}
extension UILabel{
func adjustedFont()->UIFont {
guard let txt = text else {
return self.font
}
let attributes: [NSAttributedString.Key: Any] = [.font: self.font]
let attributedString = NSAttributedString(string: txt, attributes: attributes)
let drawingContext = NSStringDrawingContext()
drawingContext.minimumScaleFactor = self.minimumScaleFactor
attributedString.boundingRect(with: bounds.size,
options: [.usesLineFragmentOrigin,.usesFontLeading],
context: drawingContext)
let fontSize = font.pointSize * drawingContext.actualScaleFactor
return font.withSize(CGFloat(floor(Double(fontSize))))
}
}
Example in Action
What I've found is that inside viewDidLoad() your constraints are not fully defined yet. You can try to do these calculations in another method for example viewWillAppear() or any other that suits you and is executed after viewDidLoad().

Not seeing all views in views using views.addSubviews

I am running into a basic problem with views on iPad. I have a viewController. The view is using a UIImageView with a full screen image as a background image. I am trying to overlay labels on the top. If I set labels individually, both views show up. If I call a function with the same information only one view shows up. I need to extend it many labels. Here is the code:
class ViewController: UIViewController {
#IBOutlet weak var backGroundImageView: UIImageView!
var cFrame:[CGRect?] = [CGRect?](repeating: nil, count: 13)
var offsets:[CGRect?] = [CGRect?](repeating: nil, count: 13)
var labels: [UILabel?] = [UILabel?](repeating:UILabel(), count:13)
override func viewDidLoad() {
super.viewDidLoad()
cFrame[0] = CGRect(x:450,y:530,width:251,height:68)
cFrame[1] = CGRect(x:147,y:676,width:222,height:24)
loadFrameValues()
var frame = CGRect(x: 450, y: 520, width: 251, height: 68)
let label0 = UILabel(frame: frame)
label0.backgroundColor = .white
label0.numberOfLines = 0
label0.lineBreakMode = .byWordWrapping
label0.textAlignment = .center
label0.text = "Text 1"
frame = CGRect(x: 152, y: 686, width: 210, height: 16)
let label1 = UILabel(frame: frame)
label1.backgroundColor = .cyan
label1.lineBreakMode = .byWordWrapping
label1.textAlignment = .left
label1.text = "Text 2"
label1.font = label1.font.withSize(12)
backGroundImageView.addSubview(label0)
backGroundImageView.addSubview(label1)
// showView(label: labels[0]!, frame: cFrame[0]!)
// showView(label: labels[1]!, frame: cFrame[1]!)
// }
}
func showView(label: UILabel, frame:CGRect) {
label.frame = frame
label.backgroundColor = .white
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.textAlignment = .center
label.text = "Syed Tariq"
backGroundImageView.addSubview(label)
}
You can't add subview (label in your case) to UIImageView. So add label as subview to the superview of your image view.
override func viewDidLoad() {
cFrame[0] = CGRect(x:50,y:130,width:151,height:68)
cFrame[1] = CGRect(x:114,y:276,width:122,height:24)
showView(frame: cFrame[0]!)
showView(frame: cFrame[1]!)
}
func showView(frame:CGRect) {
let label = UILabel(frame: frame)
label.backgroundColor = .green
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.textAlignment = .center
label.text = "Syed Tariq"
self.view.addSubview(label)
}

Overlapping elements in scroll view

Trying to make scrollView with elements created in code but i got overlapping this elements on each other. Scrollview itself made in storyboard. Here is my code:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView! {
didSet {
scrollView.backgroundColor = .yellow
}
}
lazy var im: UIImageView = {
let im = UIImageView(frame: CGRect(x: 10, y: 74, width: self.view.frame.size.width - 20, height: 200))
im.backgroundColor = .white
return im
}()
lazy var label: UILabel = {
let l = UILabel(frame: CGRect(x: 10, y: 284, width: self.view.frame.size.width - 20, height: CGFloat.greatestFiniteMagnitude))
l.numberOfLines = 0
l.lineBreakMode = .byWordWrapping
l.text = "crazy amount of text"
l.sizeToFit()
self.scrollView.contentSize = CGSize(width: self.view.frame.width, height: l.frame.height + 280)
return l
}()
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView.addSubview(im)
self.scrollView.addSubview(label)
}
}
White rectangle is imageView!
How to prevent overlapping these elements?
You can change the code of lazy variable im to
lazy var im: UIImageView = {
let im = UIImageView(frame: CGRect(x: 10, y: self.label.frame.height, width: self.view.frame.size.width - 20, height: 200))
im.backgroundColor = .white
return im
}()
For image to be on top you can add l.frame.y = self.im.frame.height after l.sizeToFit()
lazy var label: UILabel = {
let l = UILabel(frame: CGRect(x: 10, y: 200, width: self.view.frame.size.width - 20, height: CGFloat.greatestFiniteMagnitude))
l.numberOfLines = 0
l.lineBreakMode = .byWordWrapping
l.text = "Big Text"
l.sizeToFit()
l.frame.y = self.im.frame.height
self.scrollView.contentSize = CGSize(width: self.view.frame.width, height: l.frame.height + 280)
return l
}()
This will give you the desired result.
Hope it helps!
I found solution using Visual Formatting Language. Here I put fully working no-warning code:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView! {
didSet {
scrollView.backgroundColor = .yellow
}
}
lazy var label: UILabel = {
let l = UILabel(frame: .zero)
l.numberOfLines = 0
l.lineBreakMode = .byWordWrapping
l.translatesAutoresizingMaskIntoConstraints = false
l.text = "REALLY HUGE TEXT"
l.sizeToFit()
return l
}()
lazy var im: UIImageView = {
let im = UIImageView(frame: .zero)
im.backgroundColor = .white
im.translatesAutoresizingMaskIntoConstraints = false
return im
}()
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView.addSubview(im)
self.scrollView.addSubview(label)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
configureSizes()
}
fileprivate func configureSizes() {
let metrics = ["elementWidth" : self.view.frame.size.width - 20, "imageHeight" : 220]
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[v1(imageHeight)]-10-[v2]-10-|", options: [], metrics: metrics, views: ["v1" : im, "v2" : label]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[v1(elementWidth)]-10-|", options: [], metrics: metrics, views: ["v1" : im]))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[v2(elementWidth)]-10-|", options: [], metrics: metrics, views: ["v2" : label]))
}
}
Here you will see blank white rectangle on the top - imageView and after imageView you will find multiline label that stretches content size of scroll view if it is needed.
Hope somebody will find this helpful and save you hours :)

Swift add Gesture to UIImageView?

Now i am working on IOS project with Swift!
I already made coverflow object.
And now i want some function to run when i click on each images in that coverflow.
I tried to add some gesture on it but seems didn't work.
This is my code below.
func carousel(carousel: iCarousel!, viewForItemAtIndex index: Int, var reusingView view: UIView!) -> UIView!
{
var label: UILabel! = nil
var labelSecond: UILabel! = nil
var labelVol: UILabel! = nil
var viewRec: UITapGestureRecognizer! = nil
var itemsVol = [itemsInside01.count,itemsInside02.count,itemsInside03.count,itemsInside04.count,itemsInside05.count]
println(itemsVol[2])
//create new view if no view is available for recycling
if (view == nil)
{
//don't do anything specific to the index within
//this `if (view == nil) {...}` statement because the view will be
//recycled and used with other index values later
view = UIImageView(frame:CGRectMake(0, 0, 200, 156))
(view as UIImageView!).image = UIImage(named: "coverFlowBg.png")
view.contentMode = .Center
var wBounds = view.bounds.width
var hBounds = view.bounds.height
var labelSize = CGRect(x: 0, y: hBounds, width: wBounds, height: 52)
var labelSmallSize = CGRect(x: 0, y: hBounds + 30, width: wBounds, height: 24)
label = UILabel()
label.frame = labelSize
label.backgroundColor = UIColor.clearColor()
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()
label.font = UIFont(name: "supermarket" , size: 18)
label.tag = 1
labelSecond = UILabel()
labelSecond.frame = labelSize
labelSecond.backgroundColor = UIColor.clearColor()
labelSecond.textAlignment = .Center
labelSecond.textColor = UIColor.whiteColor()
labelSecond.font = UIFont(name: "supermarket" , size: 18)
labelSecond.tag = 1
labelVol = UILabel()
labelVol.frame = labelSmallSize
labelVol.backgroundColor = UIColor.clearColor()
labelVol.textAlignment = .Center
labelVol.textColor = UIColor.whiteColor()
labelVol.font = UIFont(name: "supermarket" , size: 12)
labelVol.tag = 1
imageTypeIcon = UIImage(named: cardTypeImageSrc[index])
imageTypeIconView = UIImageView(image: imageTypeIcon)
imageTypeIconView.contentMode = .Center
imageTypeIconView.frame = CGRect(x: 0, y: 0, width: wBounds, height: hBounds)
viewRec = UITapGestureRecognizer()
viewRec.addTarget(self, action: "viewIsClicked:")
imageTypeIconView.addGestureRecognizer(viewRec)
imageTypeIconView.userInteractionEnabled = true
view.addSubview(label)
//view.addSubview(labelSecond)
view.addSubview(labelVol)
view.addSubview(imageTypeIconView)
}
else
{
//get a reference to the label in the recycled view
label = view.viewWithTag(1) as UILabel!
}
//set item label
//remember to always set any properties of your carousel item
//views outside of the `if (view == nil) {...}` check otherwise
//you'll get weird issues with carousel item content appearing
//in the wrong place in the carousel
label.text = "\(items[index])"
//labelSecond.text = "\(items[index])"
labelVol.text = "\(itemsVol[index]) " + "ชุดการ์ด"
return view
}
func carousel(carousel: iCarousel!, valueForOption option: iCarouselOption, withDefault value: CGFloat) -> CGFloat
{
if (option == .Spacing)
{
return value * 1
}
return value
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func goBackToIndex(sender: AnyObject) {
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
}
func viewIsClicked(){
println("uuteosuteo")
}
So if someone know why it didn't work please help me
Thanks!
Your function viewIsClicked() doesn't contain any parameters, but your selector contains a colon - "viewIsClicked:", so you probably getting runtime error.
Try to change:
viewRec.addTarget(self, action: "viewIsClicked:")
To:
viewRec.addTarget(self, action: "viewIsClicked")
Changing following snippet of code will do your work
viewRec = UITapGestureRecognizer(target: self, action: "viewIsClicked")
viewRec.numberOfTapsRequired = 1
viewRec.numberOfTouchesRequired = 1

Place Label under each point from spaceBetweenPoints

I'm using a custom UIView for creating this control with 4 hotspots with the same space between the points. I'm trying to create for labels exactly under the points and it seems like the first label is correctly aligned, but i cant seem to figure out why all of them aren't correct?
Here you see the space between each point and the radius on the points.
customSlider?.spaceBetweenPoints = 95
customSlider?.radiusPoint = 5
illustration at the moment:
customSlider?.frame = CGRectMake((self.frame.width-335)/2, 20, 335, 34)
for var i = 0;i<4;i++
{
var xPointSpace = 95
var xPos = xPointSpace * i
var xSpace = (self.frame.width-335)/2
var xWidth = Int(xSpace) + xPos
var xFloat = CGFloat(xWidth)
var textLabel:UILabel = UILabel(frame: CGRectMake(xFloat, 34, 30, 21))
textLabel.text = "lol"
textLabel.backgroundColor = UIColor.redColor()
textLabel.textAlignment = NSTextAlignment.Center
textLabel.font = UIFont(name: "HelveticaNeue", size: 12)
self.addSubview(textLabel)
}
adding the labels:
customSlider?.frame = CGRectMake((self.frame.width-335)/2, 20, 335, 34)
for var i = 0;i<4;i++
{
var xPointSpace = 95
var radiusPoint = 5
var xPos = (xPointSpace + radiusPoint * 2)* i
var xSpace = customSlider?.frame.origin.x
var xWidth = xSpace + xPos
var xFloat = CGFloat(xWidth)
var textLabel:UILabel = UILabel(frame: CGRectMake(xFloat, 34, 30, 21))
textLabel.text = "lol"
textLabel.backgroundColor = UIColor.redColor()
textLabel.textAlignment = NSTextAlignment.Center
textLabel.font = UIFont(name: "HelveticaNeue", size: 12)
self.addSubview(textLabel)
}

Resources