Will this statement always evaluate to nil in Swift? - swift

open var buttonInit: ((_ index: Int) -> UIButton?)?
...
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
I don't find any function description about buttonInit in AZDialogViewController. Does it mean button: UIButton = self.buttonInit?(i) will always be nil and finButton = button will not be executed?

The latter part of the code you quoted is in the setUpButton method:
fileprivate func setupButton(index i:Int) -> UIButton{
if buttonHeight == 0 {buttonHeight = CGFloat(Int(deviceHeight * 0.07))}
let finButton: UIButton
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
This method is called here:
open func addAction(_ action: AZDialogAction){
actions.append(action)
if buttonsStackView != nil{
let button = setupButton(index: actions.count-1)
self.buttonsStackView.addArrangedSubview(button)
//button.frame = buttonsStackView.bounds
button.center = CGPoint(x: buttonsStackView.bounds.midX,y: buttonsStackView.bounds.maxY)
animateStackView()
}
}
From this we can see that buttonInit seems to be used to let the user of the library specify what kind of button they want as the action buttons. Another piece of evidence is that buttonInit is declared open, so it is likely that it is the client code who should set this, not the AZDialogViewController.
Plus, the README file showed this usage:
Use custom UIButton sub-class:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
So to answer your question, the if branch will be executed if you set buttonInit.

#Huwell,
the documentation in the repository states to initialize the button in the following manner:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
The button should be part of your DialogViewController.

Related

What am I doing wrong when updating my user's credits and storing it to userDefaults?

My code below has a button, pressing which should increase the number of credits my user has by 3. I have used get/set property observers for my variable to be saved to userDefaults. While the credits label reflects the change (increases by 3), the number isn't saved to userDefaults, and consequently resets back to the base number when I kill and restart the app.
var livesLeft: Int {
get {
return UserDefaults.standard.integer(forKey: "livesLeftSaved")
}
set {
UserDefaults.standard.set(newValue, forKey: "livesLeftSaved")
}
}
lazy var livesLeftLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
livesLeft = 0
label.text = String(livesLeft)
label.font = UIFont(name: "GillSans-BoldItalic", size: 25)
label.textAlignment = .center
label.numberOfLines = 2
return label
}()
let addLivesButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(named: "icon"), for: .normal)
button.addTarget(self, action: #selector(pressedButton), for: .touchUpInside)
return button
}()
#objc func pressedButton() {
livesLeft += 3
//I think the mistake I'm making is in the next line of code//
livesLeftLabel.text = String(livesLeft)
}
While the label gets updated from 0 to 3 on pressing the button, it fails to save the increased number to userDefaults and consequently the user loses his credits once I kill the app.
I know I'm missing out on something very trivial here, I can't figure out what I'm doing wrong
Your issue is here:
lazy var livesLeftLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
livesLeft = 0 *** HERE ***
You are resetting the livesLeft value when you load the label.
Just change this line to
livesLeftLabel.text = String(livesLeft)

removeFromSubView disables interaction

I have a UICollectionView that is basically a chat log. I have an imageView in some of the cells and added the ability to expand an image to full screen on tap.
///
ChatLogMessageCell.swift
/**
*
* I add the target to the UIButton with an image as a background
*/
messageImage.addTarget(self, action: #selector(fullscreenImage), for: .touchUpInside)
/*
* Full screen code
*/
#objc func fullscreenImage() {
if let chatlog = parentViewController as? ChatLogController {
let imageScroll = UIScrollView()
imageScroll.delegate = self
imageScroll.minimumZoomScale = 1.0
imageScroll.maximumZoomScale = 5.0
imageScroll.frame = UIScreen.main.bounds
let newImageView = UIImageView(image: messageImage.backgroundImage(for: .normal))
newImageView.frame = UIScreen.main.bounds
newImageView.backgroundColor = .black
newImageView.contentMode = .scaleAspectFit
newImageView.isUserInteractionEnabled = true
imageScroll.addSubview(newImageView)
chatlog.view.addSubview(imageScroll)
chatlog.navigationController?.isNavigationBarHidden = true
chatlog.tabBarController?.tabBar.isHidden = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
newImageView.addGestureRecognizer(tap)
}
}
#objc func dismissFullscreenImage(_ sender: UITapGestureRecognizer) {
if let chatlog = parentViewController as? ChatLogController {
chatlog.navigationController?.isNavigationBarHidden = false
chatlog.tabBarController?.tabBar.isHidden = false
sender.view?.removeFromSuperview()
}
}
When The fullscreen image is removed the ChatLogController is no longer interactable. I can't scroll or re-enter fullscreen mode on an image.What am I missing here? I simply want to dismiss the full screen image and allow the user to choose another image or just scroll through the messages.
Here you remove the imageView
sender.view?.removeFromSuperview()
while you need to remove the scrollView like
sender.view?.superview?.removeFromSuperview()

How to remove underline from UIBarButtonItem? (Swift)

I created a UIBarButtonItem programmatically and the text is underlined. Is there a way to remove the underline?
let editButton = UIButton.init(type: .Custom)
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.title = "General Information"
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
editButton.addTarget(self, action: #selector(editButtonPressed(_:)), forControlEvents: .TouchUpInside)
editButton.frame.size = CGSize(width: 60, height: 30)
editButton.titleLabel?.adjustsFontSizeToFitWidth = true
let barButtonItem = UIBarButtonItem.init(customView: editButton)
self.tabBarController?.navigationItem.setRightBarButtonItem(barButtonItem, animated: true)
updateEditButtonTitle()
self.navigationController!.navigationItem.backBarButtonItem?.tintColor = UIColor.blackColor()
}
here is an image of the result I get, with the underline.
here is the function where I set the button's text. when it is pressed, it becomes a save button.
func updateEditButtonTitle() {
if let button = self.tabBarController?.navigationItem.rightBarButtonItem?.customView as? UIButton {
var title = ""
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
editButton.layer.cornerRadius = 7.0
if isInEditMode {
title = "Save"
editButton.setTitleColor(UIColor.redColor(), forState: .Normal)
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.5)
editButton.layer.cornerRadius = 7.0
editButton.frame.size = CGSize(width: 60, height: 30)
} else {
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
title = "Edit"
}
button.setTitle(title, forState: .Normal)
}
}
Try this code ..
var attrStr: NSMutableAttributedString = yourBtnHere.attributedTitleForState(.Normal).mutableCopy()
//or whatever the state you want
attrStr.enumerateAttributesInRange(NSMakeRange(0, attrStr.characters.count), options: .LongestEffectiveRangeNotRequired, usingBlock: {(attributes: [NSObject : AnyObject], range: NSRange, stop: Bool) -> Void in
var mutableAttributes: [NSObject : AnyObject] = [NSObject : AnyObject](dictionary: attributes)
mutableAttributes.removeObjectForKey(.AttributeName)
attrStr.setAttributes(mutableAttributes, range: range)
})
With the inspector/IB: Select your UIButton.
Show the Attributes Inspector.
The Text settings should be in Attributed. Select the text, click on the fond item remove the Underlining setting it at none.
enter image description here
But..
Let me get this straight. Apple added an accessibility feature that lets users mark buttons with underlines if they want to.
You want a way to defeat this feature, specifically designed to help people with handicaps use their devices, when the feature is something that the user has to ask for.
Why?
It is very likely not possible using standard buttons. If you did figure out a way to do it, Apple would likely reject your app because it defeats a system function meant to help the disabled.
So the answer is: Don't do that.

how to create multiple UIButton on viewDidLoad (Swift)

I'm sorry but if I have a number of buttons that comes from a plist file ...
how do I re-create all the buttons?
Example I tried in this way :
func loadSavedButtons() {
// I extract the number from the plist file
var number: AnyObject? = data.valueForKey("NumberOfButton")
var someNumb: Int = ("\(number!)").toInt()!
if (someNumb != 0) {
self.countButton = someNumb
for (var i=0; i < someNumb; i++) {
In This Point I should do
var newButton6: () = CreateButtonWithIndex(i)
self.view.addSubview(newButton6)
}}}
and
#IBAction func CreateButtonWithIndex(sender: AnyObject){
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
ecc…
self.view.addSubview(button)
but don't go ... i don't have all save button please help me !!!
In your function
Change the following
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
to
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
then after
self.view.addSubview(button)
add the following:
button = UIButton.new()

how to add buttons to a page controller

I wonder how you can add buttons (left and right) to change page controll views.
I'm working on this tutorial [1]: http://www.edumobile.org/iphone/iphone-programming-tutorials/pagecontrol-example-in-iphone/ . How can I add 2 simple buttons (left and right) to turn pages in addition to the swaping function in this example code?
I'm a programmer beginner so any kind of answer is highly appriciated! :)
thanks!
You can add two buttons to the view and when the button is clicked call a method to turn the page according to the button clicked.
UIButton *leftButton = [[UIButton alloc] init];
leftbutton.frame = leftButtonFrame;
[leftbutton setTitle:#"Left" forState:UIControlStateNormal];
[leftbutton addTarget:self action:#selector(leftbuttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[yourView addSubview:leftbutton];
UIButton *rightButton = [[UIButton alloc] init];
rightButton.frame = rightButtonFrame;
[rightButton setTitle:#"Right" forState:UIControlStateNormal];
[rightButton addTarget:self action:#selector(rightButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[yourView addSubview:rightButton];
- (void)leftButtonclicked:(id)sender
{
//Code to turn page left
}
- (void)rightButtonclicked:(id)sender
{
//Code to turn page right
}
I'm going to answer this in swift, but you should be able to translate.
The process is to find the PageControl view, add the two buttons and hide the buttons when appropriate (i.e. no previous button on first page).
I place the buttons on left and right side of PageControl. The default behavior is that touching there does a page back and page forward. So I set the buttons to enabled=false so that touches execute this default behavior.
First we need an enum to help locate buttons. Use values which won't be use elsewhere in view.
enum enumBtnTag: Int {
case tagPrev = 9991
case tagNext = 9992
}
var pageNbr = 0 //Needed to keep track of page being displayed
Now we will add our buttons in ViewDidLoad. First I locate the PageControl, then I look for buttons so as to not create twice. (ViewDidload could be called multiple times)
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews {
if view is UIPageControl {
let curr:UIPageControl = view as! UIPageControl
curr.backgroundColor = UIColor.clear
curr.currentPageIndicatorTintColor = UIColor.red //Page Dot is red
curr.pageIndicatorTintColor = UIColor.black //Other dots are black
let pcSz = view.frame
let btnSz = CGSize(width: 35, height: 50) //Use your button size
if let _ = self.view.viewWithTag(enumBtnTag.tagNext.rawValue) as? UIButton {}
else { //Next Button not found
let Nbtn = UIButton(frame: CGRect(x: pcSz.width - btnSz.width, y: -15, width: btnSz.width, height: btnSz.height))
Nbtn.setTitle(">>", for: UIControlState.normal)
Nbtn.backgroundColor = UIColor.clear
Nbtn.setTitleColor(UIColor.brown, for: UIControlState.normal)
Nbtn.titleLabel?.font = UIFont(name: enumFontNames.MarkerFelt_Wide.rawValue, size: 60.0)
Nbtn.isEnabled = false //Allows touch to fall through to PageControl
Nbtn.tag = enumBtnTag.tagNext.rawValue
view.addSubview(Nbtn)
}
if let _ = self.view.viewWithTag(enumBtnTag.tagPrev.rawValue) as? UIButton {}
else { //Prev Button not found
let Pbtn = UIButton(frame: CGRect(x: 0, y: -15, width: btnSz.width, height: btnSz.height))
Pbtn.setTitle("<<", for: UIControlState.normal)
Pbtn.backgroundColor = UIColor.clear
Pbtn.setTitleColor(UIColor.brown, for: UIControlState.normal)
Pbtn.titleLabel?.font = UIFont(name: enumFontNames.MarkerFelt_Wide.rawValue, size: 60.0)
Pbtn.isEnabled = false
Pbtn.isHidden = true
Pbtn.tag = enumBtnTag.tagPrev.rawValue
view.addSubview(Pbtn)
}
}
}
}
Then I capture the page that is going to be displayed. The page might not be displayed (user didn't drag far enough), but that is handled later.
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
if let identifier = pendingViewControllers[0].restorationIdentifier {
if let index = pages.index(of: identifier) {
pageNbr = index
}
}
}
Now we modify buttons in didFinishAnimating;
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if finished && completed {
if let button = self.view.viewWithTag(enumBtnTag.tagPrev.rawValue) as? UIButton {
if pageNbr > 0 {
button.isHidden = false
} else {
button.isHidden = true
}
}
if let button = self.view.viewWithTag(enumBtnTag.tagNext.rawValue) as? UIButton {
if pageNbr < pages.count - 1 {
button.isHidden = true
} else {
button.isHidden = false
}
}
}
}
Bonus code: I added a Save function at last page where the Next Button is. You need to set the button is enabled (so it registers the touch) and set a target (what ever function you want to execute); mine is "nextSegue".
and of course remove target when not on last page;
if pageNbr < pages.count - 1 {
//Not on last page. Use next button
button.setTitle(">>", for: UIControlState.normal)
button.removeTarget(self, action: #selector(nextSegue), for: UIControlEvents.touchUpInside)
button.isEnabled = false
} else {
//On last page. Use save button
button.setTitle("S", for: UIControlState.normal)
button.addTarget(self, action: #selector(nextSegue), for: UIControlEvents.touchUpInside)
button.isEnabled = true
}
Hope this helps someone.