Connecting UIButtons by drawing a line - ios

I need to connect those buttons with a line but have issues as you can see on the screenshot. I need the last line to go vertical (green circles). Any suggestions?
here is the code:
#IBAction func drawButtons (sender: AnyObject) {
buttonContainerView.removeFromSuperview() // Clear containerView
buttonContainerView = UIView() // Create a new instance
let buttonCount = array.count
let n = Int(self.view.frame.size.width) / 90 //check how many buttons can fit in the screen
let buttonsPerRow = n
let horizontalSpace: CGFloat = 80
let verticalSpace: CGFloat = 80
// Create the alignment points
var points = [CGPointZero]
var direction: CGFloat = 1
for i in 1..<buttonCount {
let previousPoint = points[i-1]
let point: CGPoint
if i % buttonsPerRow == 0 {
direction *= -1
point = CGPointMake(previousPoint.x, previousPoint.y + verticalSpace)
} else {
point = CGPointMake(previousPoint.x + direction * horizontalSpace, previousPoint.y)
}
points.append(point)
}
// Make the buttons
var containerWidth: CGFloat = 0
var containerHeight: CGFloat = 0
for (index, point) in points.enumerate() {
let button = UIButton(frame: CGRectMake(point.x, point.y, 60, 60))
button.setTitle("Button \(index)", forState: .Normal)
button.setTitleColor(button.tintColor, forState: .Normal)
button.layer.cornerRadius = 30
button.layer.borderColor = UIColor .redColor().CGColor
button.layer.borderWidth = 1
buttonContainerView.addSubview(button)
// Determine size needed in the container to show all button
if button.frame.maxX > containerWidth {
containerWidth = button.frame.maxX
}
if button.frame.maxY > containerHeight {
containerHeight = button.frame.maxY
}
let myBezierPath = UIBezierPath()
myBezierPath.moveToPoint(CGPointMake(point.x + 60, point.y + 30))
myBezierPath.addLineToPoint(CGPointMake(point.x + 80, point.y + 30))
let shapeLayer = CAShapeLayer()
shapeLayer.path = myBezierPath .CGPath
shapeLayer.strokeColor = UIColor.blueColor().CGColor
shapeLayer.lineWidth = 2
shapeLayer.fillColor = UIColor.clearColor().CGColor
buttonContainerView.layer.addSublayer(shapeLayer)
}
// Optional: draw the alignment points and give the container view a background color
// so it's easier to visualize
for _ in points {
for (index, point) in points.enumerate() {
let circleLabel = UILabel(frame: CGRectMake(point.x, point.y, 11, 11))
circleLabel.layer.cornerRadius = 5.5
circleLabel.text = String(index + 1)
circleLabel.textAlignment = NSTextAlignment.Center
circleLabel.font = circleLabel.font.fontWithSize(8)
buttonContainerView.addSubview(circleLabel)
}
}
// buttonContainerView.backgroundColor = UIColor.lightGrayColor()
// Center the containerView on the screen
buttonContainerView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(buttonContainerView)
let c1 = NSLayoutConstraint(item: buttonContainerView, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1, constant: 0)
let c2 = NSLayoutConstraint(item: buttonContainerView, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1, constant: 0)
let c3 = NSLayoutConstraint(item: buttonContainerView, attribute: .Width, relatedBy: .Equal , toItem: nil, attribute: .Width, multiplier: 0, constant: containerWidth)
let c4 = NSLayoutConstraint(item: buttonContainerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 0, constant: containerHeight)
NSLayoutConstraint.activateConstraints([c1, c2, c3, c4])
}
}

I have also tried this which seems to be working now, but I'm open to suggestions
for i in 1..<buttonCount {
let previousPoint = points[i-1]
let point: CGPoint
if i % buttonsPerRow == 0 {
direction *= -1
point = CGPointMake(previousPoint.x, previousPoint.y + verticalSpace)
let lineView = UIView (frame: CGRectMake(previousPoint.x + 30, previousPoint.y + lineVerticalSpace, 1, 20))
lineView.layer.borderColor = UIColor .blueColor().CGColor
lineView.layer.borderWidth = 3
buttonContainerView.addSubview(lineView)
} else {
point = CGPointMake(previousPoint.x + direction * horizontalSpace, previousPoint.y)
}
points.append(point)
// print(direction)
if direction == -1 {
let lineView = UIView (frame: CGRectMake(previousPoint.x + (direction * lineHorizontalSpace + 40), point.y + 30, 20, 1))
lineView.layer.borderColor = UIColor .redColor().CGColor
lineView.layer.borderWidth = 3
buttonContainerView.addSubview(lineView)
}
else {
let lineView = UIView (frame: CGRectMake(previousPoint.x + direction * lineHorizontalSpace, point.y + 30, 20, 1))
lineView.layer.borderColor = UIColor .redColor().CGColor
lineView.layer.borderWidth = 3
buttonContainerView.addSubview(lineView)
}
}
Which results in this:

Related

SWIFT Alamofire Graph issue

I am new to IOS development. Please help me with issue. I am not getting data on Y axis. Fetching data through Alamofire using webAPI. Data is coming nil. Same code is working fine with UIViewController table. I am getting the response. But when using in Graph it is not working.
Issue: I am using Alamofire to parse WebAPI. 'SLPercent' is the value which i want to display on Y-axis.But xml value coming as nil.
class ViewController: UIViewController, ScrollableGraphViewDataSource {
var xml = try! XML.parse("")
var graphView: ScrollableGraphView!
var currentGraphType = GraphType.bar
var graphConstraints = [NSLayoutConstraint]()
var label = UILabel()
var reloadLabel = UILabel()
// Data for the different plots
var numberOfDataItems = day
// Data for graphs with a single plot
/*lazy var simpleLinePlotData: [Double] = self.generateRandomData(self.numberOfDataItems!, max: 100, shouldIncludeOutliers: false)
*/
lazy var barPlotData: [Double] = self.generateRandomData(self.numberOfDataItems!, max: 100, shouldIncludeOutliers: false)
// Data for graphs with multiple plots
lazy var blueLinePlotData: [Double] = self.generateRandomData(self.numberOfDataItems!, max: 50)
// lazy var orangeLinePlotData: [Double] = self.generateRandomData(self.numberOfDataItems!, max: 40, shouldIncludeOutliers: false)
// Init
override func viewDidLoad() {
super.viewDidLoad()
let user = "ndbd#gmail.com"
let passwort = "xdc"
var url = URL(string: "https://ceef")
let configuration = URLSessionConfiguration.default
configuration.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
configuration.timeoutIntervalForResource = 10
let credentialData = "\(user):\(passwort)".data(using: String.Encoding.utf8)!
let base64Credentials = credentialData.base64EncodedString(options: [])
let headers = ["Accept": "application/xml","Authorization": "Basic \(base64Credentials)"]
DispatchQueue.main.async {
Alamofire.request(
url!,
method: .get,
parameters: nil,
encoding: URLEncoding.default,
headers:headers)
.responseString
{ response in
debugPrint(response)
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if response.result.value != nil
{
self.xml = try! XML.parse(response.result.value!)
}
}
}
// self.CallWebAPI()
// Labels for the x-axis
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
let nameOfMonth = dateFormatter.string(from: now)
var xAxisLabels: [String] = self.generateSequentialLabels(self.numberOfDataItems!, text: nameOfMonth);
graphView = createMultiPlotGraphOne(self.view.frame)
graphView.topMargin = 200
graphView.bottomMargin = 20
addReloadLabel(withText: "RELOAD")
self.view.insertSubview(graphView, belowSubview: reloadLabel)
setupConstraints()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "⬅", style: .plain, target: self, action: #selector(backAction))
}
func backAction()
{
//print("Back Button Clicked")
dismiss(animated: true, completion: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewDidLoad()
// self.CallWebAPI()
graphView = createMultiPlotGraphOne(self.view.frame)
graphView.topMargin = 200
graphView.bottomMargin = 20
addReloadLabel(withText: "RELOAD")
self.view.insertSubview(graphView, belowSubview: reloadLabel)
setupConstraints()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidLoad()
graphView = createMultiPlotGraphOne(self.view.frame)
graphView.topMargin = 200
graphView.bottomMargin = 20
addReloadLabel(withText: "RELOAD")
self.view.insertSubview(graphView, belowSubview: reloadLabel)
setupConstraints()
}
// Implementation for ScrollableGraphViewDataSource protocol
// #########################################################
// You would usually only have a couple of cases here, one for each
// plot you want to display on the graph. However as this is showing
// off many graphs with different plots, we are using one big switch
// statement.
func value(forPlot plot: Plot, atIndex pointIndex: Int) -> Double {
switch("bar") {
// Data for the graphs with a single plot
case "bar":
return barPlotData[pointIndex]
default:
return 30
}
}
func label(atIndex pointIndex: Int) -> String {
// Ensure that you have a label to return for the index
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
let nameOfMonth = dateFormatter.string(from: now)
var xAxisLabels: [String] = self.generateSequentialLabels(self.numberOfDataItems!, text: nameOfMonth);
return xAxisLabels[pointIndex]
}
func numberOfPoints() -> Int {
return numberOfDataItems!
}
// Creating Different Kinds of Graphs
// min: 0
// max: 100
// Will not adapt min and max reference lines to range of visible points
private func createBarGraph(_ frame: CGRect) -> ScrollableGraphView {
let graphView = ScrollableGraphView(frame: frame, dataSource: self)
graphView.topMargin = 200
graphView.bottomMargin = 20
// Setup the plot
let barPlot = BarPlot(identifier: "bar")
barPlot.barWidth = 25
barPlot.barLineWidth = 1
barPlot.barLineColor = UIColor.colorFromHex(hexString: "#777777")
barPlot.barColor = UIColor.colorFromHex(hexString: "#555555")
barPlot.adaptAnimationType = ScrollableGraphViewAnimationType.elastic
barPlot.animationDuration = 1.5
// Setup the reference lines
let referenceLines = ReferenceLines()
referenceLines.referenceLineLabelFont = UIFont.boldSystemFont(ofSize: 8)
referenceLines.referenceLineColor = UIColor.white.withAlphaComponent(0.2)
referenceLines.referenceLineLabelColor = UIColor.white
referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(0.5)
// Setup the graph
graphView.backgroundFillColor = UIColor.colorFromHex(hexString: "#333333")
graphView.shouldAnimateOnStartup = true
graphView.rangeMax = 100
graphView.rangeMin = 0
// Add everything
graphView.addPlot(plot: barPlot)
graphView.addReferenceLines(referenceLines: referenceLines)
return graphView
}
fileprivate func createMultiPlotGraphOne(_ frame: CGRect) -> ScrollableGraphView {
let graphView = ScrollableGraphView(frame: frame, dataSource: self)
graphView.topMargin = 200
graphView.bottomMargin = 20
// Setup the first plot.
let blueLinePlot = LinePlot(identifier: "multiBlue")
blueLinePlot.lineColor = UIColor.colorFromHex(hexString: "#16aafc")
blueLinePlot.adaptAnimationType = ScrollableGraphViewAnimationType.elastic
// dots on the line
let blueDotPlot = DotPlot(identifier: "multiBlueDot")
blueDotPlot.dataPointType = ScrollableGraphViewDataPointType.circle
blueDotPlot.dataPointSize = 5
blueDotPlot.dataPointFillColor = UIColor.colorFromHex(hexString: "#16aafc")
blueDotPlot.adaptAnimationType = ScrollableGraphViewAnimationType.elastic
// Setup the reference lines.
let referenceLines = ReferenceLines()
referenceLines.referenceLineLabelFont = UIFont.boldSystemFont(ofSize: 8)
referenceLines.referenceLineColor = UIColor.white.withAlphaComponent(0.2)
referenceLines.referenceLineLabelColor = UIColor.white
referenceLines.relativePositions = [0, 0.2, 0.4, 0.6, 0.8, 1]
referenceLines.dataPointLabelColor = UIColor.white.withAlphaComponent(1)
// Setup the graph
graphView.backgroundFillColor = UIColor.colorFromHex(hexString: "#333333")
graphView.dataPointSpacing = 80
graphView.shouldAnimateOnStartup = true
graphView.shouldAdaptRange = true
graphView.shouldRangeAlwaysStartAtZero = true
// Add everything to the graph.
graphView.addReferenceLines(referenceLines: referenceLines)
graphView.addPlot(plot: blueLinePlot)
graphView.addPlot(plot: blueDotPlot)
return graphView
}
// Constraints and Helper Functions
// ################################
private func setupConstraints() {
self.graphView.translatesAutoresizingMaskIntoConstraints = false
graphConstraints.removeAll()
let topConstraint = NSLayoutConstraint(item: self.graphView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: self.graphView, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.graphView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let leftConstraint = NSLayoutConstraint(item: self.graphView, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 0)
graphConstraints.append(topConstraint)
graphConstraints.append(bottomConstraint)
graphConstraints.append(leftConstraint)
graphConstraints.append(rightConstraint)
self.view.addConstraints(graphConstraints)
}
// Adding and updating the graph switching label in the top right corner of the screen.
private func addLabel(withText text: String) {
label.removeFromSuperview()
label = createLabel(withText: text)
label.isUserInteractionEnabled = true
let rightConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -20)
let topConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 80)
let heightConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 40)
let widthConstraint = NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: label.frame.width * 1.5)
let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(didTap))
label.addGestureRecognizer(tapGestureRecogniser)
self.view.insertSubview(label, aboveSubview: reloadLabel)
self.view.addConstraints([rightConstraint, topConstraint, heightConstraint, widthConstraint])
}
private func addReloadLabel(withText text: String) {
reloadLabel.removeFromSuperview()
reloadLabel = createLabel(withText: text)
reloadLabel.isUserInteractionEnabled = true
let leftConstraint = NSLayoutConstraint(item: reloadLabel, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 20)
let topConstraint = NSLayoutConstraint(item: reloadLabel, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 80)
let heightConstraint = NSLayoutConstraint(item: reloadLabel, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 40)
let widthConstraint = NSLayoutConstraint(item: reloadLabel, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: reloadLabel.frame.width * 1.5)
let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(reloadDidTap))
reloadLabel.addGestureRecognizer(tapGestureRecogniser)
self.view.insertSubview(reloadLabel, aboveSubview: graphView)
self.view.addConstraints([leftConstraint, topConstraint, heightConstraint, widthConstraint])
}
private func createLabel(withText text: String) -> UILabel {
let label = UILabel()
label.backgroundColor = UIColor.black.withAlphaComponent(0.5)
label.text = text
label.textColor = UIColor.white
label.textAlignment = NSTextAlignment.center
label.font = UIFont.boldSystemFont(ofSize: 14)
label.layer.cornerRadius = 2
label.clipsToBounds = true
label.translatesAutoresizingMaskIntoConstraints = false
label.sizeToFit()
return label
}
// Button tap events
func didTap(_ gesture: UITapGestureRecognizer) {
currentGraphType.next()
self.view.removeConstraints(graphConstraints)
graphView.removeFromSuperview()
switch(currentGraphType) {
case .bar:
graphView = createBarGraph(self.view.frame)
addReloadLabel(withText: "RELOAD")
addLabel(withText: "BAR")
}
self.view.insertSubview(graphView, belowSubview: reloadLabel)
setupConstraints()
}
func reloadDidTap(_ gesture: UITapGestureRecognizer) {
// TODO: Currently changing the number of data items is not supported.
// It is only possible to change the the actual values of the data before reloading.
// numberOfDataItems = 30
// data for graphs with a single plot
barPlotData = self.generateRandomData(self.numberOfDataItems!, max: 100, shouldIncludeOutliers: false)
blueLinePlotData = self.generateRandomData(self.numberOfDataItems!, max: 50)
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
let nameOfMonth = dateFormatter.string(from: now)
var xAxisLabels: [String] = self.generateSequentialLabels(self.numberOfDataItems!, text: nameOfMonth);
xAxisLabels = self.generateSequentialLabels(self.numberOfDataItems!, text: nameOfMonth)
graphView.reload()
}
// Data Generation
private func generateRandomData(_ numberOfItems: Int, max: Double, shouldIncludeOutliers: Bool = true) -> [Double] {
var data = [Double]()
var counter = 1
for _ in 0 ..< numberOfItems
{
for Result in xml["WebAPiResponse","Result"]
{
let SLPercent = Result["SLPercent"].text!;
let Date = Result["DateCST"].text!;
let DateFromService = Int(Date.substring(to:Date.index(Date.startIndex, offsetBy: 2)))
if (counter == DateFromService!)
{
data.append(Double(SLPercent)!)
}
}
data.append(Double(counter))
counter = counter + 1;
}
return data
}
private func generateRandomData(_ numberOfItems: Int, variance: Double, from: Double) -> [Double] {
var data = [Double]()
for _ in 0 ..< numberOfItems {
let randomVariance = Double(arc4random()).truncatingRemainder(dividingBy: variance)
var randomNumber = from
if(arc4random() % 100 < 50) {
randomNumber += randomVariance
}
else {
randomNumber -= randomVariance
}
data.append(randomNumber)
}
return data
}
private func generateSequentialLabels(_ numberOfItems: Int, text: String) -> [String] {
var labels = [String]()
for i in 0 ..< numberOfItems {
labels.append("\(text) \(i+1)")
}
return labels
}
// The type of the current graph we are showing.
enum GraphType {
case bar
mutating func next() {
switch(self) {
case .bar:
self = GraphType.bar
}
}
}
override var prefersStatusBarHidden : Bool {
return true
}
}

UISearchBarDelegate methods not being called

I had a working search bar and out of nowhere I stopped being able to even to activate any delegate methods. I created the search bar programmatically.
Here is my initialization code:
self.searchBar.delegate = self
self.searchBar.translatesAutoresizingMaskIntoConstraints = false
self.searchBar.searchBarStyle = .minimal
self.searchBar.isUserInteractionEnabled = true
let image = self.getImageWithColor(color: UIColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 0.19), size: CGSize(width: self.customNavBar.frame.width * 0.9440, height: self.customNavBar.frame.height * 0.47727))
searchBar.setSearchFieldBackgroundImage(image, for: .normal)
self.customNavBar.addSubview(self.searchBar)
var horizCenter = NSLayoutConstraint(item: self.searchBar, attribute: .centerX, relatedBy: .equal, toItem: self.customNavBar, attribute: .centerX, multiplier: 1, constant: 0)
var vertConstraints = NSLayoutConstraint(item: self.searchBar, attribute: .top, relatedBy: .equal, toItem: self.customNavBar, attribute: .top, multiplier: 1, constant: 30)
var widthConstraint = NSLayoutConstraint(item: self.searchBar, attribute: .width, relatedBy: .equal, toItem: self.customNavBar, attribute: .width, multiplier: 0.9440, constant: 0)
var heightConstraint = NSLayoutConstraint(item: self.searchBar, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: self.customNavBar.frame.height * 0.47727 )
NSLayoutConstraint.activate([horizCenter, vertConstraints, widthConstraint, heightConstraint])
Here is the getImageWithColor method I referenced above:
func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
let rect = CGRect(x:0, y:0, width:size.width,height: size.height)
let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
path.fill()
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
And I continue to customize the textField inside the searchBar:
UITextField.appearance().tintColor = UIColor.white
let cancelButtonAttributes: NSDictionary = [NSForegroundColorAttributeName: UIColor.white, NSFontAttributeName : UIFont(name: "Gotham-Book", size: 14.0)!]
UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes as? [String : AnyObject], for: UIControlState.normal)
let textFieldInsideSearchBar = self.searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 1.0)
textFieldInsideSearchBar?.font = UIFont(name: "Gotham Medium", size: 20.0)
textFieldInsideSearchBar?.clearsOnBeginEditing = true
textFieldInsideSearchBar?.borderStyle = .none
textFieldInsideSearchBar?.clearButtonMode = .whileEditing
textFieldInsideSearchBar?.isUserInteractionEnabled = true
And all my delegate methods:
extension ListViewController : UISearchBarDelegate {
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
print("\nfunc searchBarTextDidBeginEditing\n")
self.hideDayDropDown()
UIView.animate(withDuration: 0.25) {
self.dayButton.alpha = 0.0
self.dayButtonLabel.alpha = 0.0
self.dayDropDownArrow.alpha = 0.0
self.mapButton.alpha = 0.0
self.mapButton.isEnabled = false
self.dayButton.isUserInteractionEnabled = false
self.tableView.transform = CGAffineTransform(translationX: 0.0, y: -(self.tableView.frame.minY - self.customNavBar.frame.maxY))
self.tableView.translatesAutoresizingMaskIntoConstraints = true
self.tableView.frame = CGRect(x: 0, y: self.customNavBar.frame.maxY, width: self.view.frame.width, height: 300)
self.dealOfTheDayLabel.alpha = 0.00
self.exploreSpecialView.alpha = 0.0
self.exploreSpecialsLabel.alpha = 0.0
}
searchActive = true
self.searchBar.setShowsCancelButton(true, animated: true)
UIView.animate(withDuration: 0.25) {
self.searchIconImage.alpha = 0.0
self.searchIconWhileEditing.alpha = 1.0
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
print("\nfunc searchBarTextDidEndEditing\n")
UIView.animate(withDuration: 0.25) {
self.dayButton.alpha = 1.0
self.dayButtonLabel.alpha = 1.0
self.dayDropDownArrow.alpha = 1.0
self.dayButton.isUserInteractionEnabled = true
self.searchIconImage.alpha = 1.0
self.searchIconWhileEditing.alpha = 0.0
self.tableView.transform = CGAffineTransform(translationX: 0.0, y: 0.0)
self.tableView.translatesAutoresizingMaskIntoConstraints = false
self.mapButton.alpha = 1.0
self.mapButton.isEnabled = true
self.dealOfTheDayLabel.alpha = 1.0
self.exploreSpecialView.alpha = 1.0
self.exploreSpecialsLabel.alpha = 1.0
}
searchActive = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
print("\nfunc searchBarCancelButtonClicked\n")
self.searchBar.setShowsCancelButton(false, animated: true)
self.searchBar.text = ""
self.searchBar.resignFirstResponder()
searchActive = false
self.searchIconImage.alpha = 1.0
self.searchIconWhileEditing.alpha = 0.0
self.dayDropDownArrow.alpha = 1.0
self.tableView.transform = CGAffineTransform(translationX: 0.0, y: 0.0 )
self.dealOfTheDayLabel.alpha = 1.0
self.exploreSpecialView.alpha = 1.0
self.exploreSpecialsLabel.alpha = 1.0
tableView.reloadData()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.searchResults = self.library.filter({ (bar: BarLibrary) -> Bool in
let tmp: String = bar.name!
let range = tmp.localizedLowercase.range(of: searchText.localizedLowercase)
return range != nil
})
if(self.searchResults.count == 0){
searchActive = false
} else {
searchActive = true
}
self.tableView.reloadData()
}
}
Here is also an image from my interface capture of my navigation bar with the search bar:
Screen Capture Image as seen in Interface Capture: View names from front to back: UITextFieldBorderView, UISearchBarTextField, UIView, UISearchBar
Note I'm not sure what the UIView right before the UISearchBar is for
I understand there are a lot of questions on SO about why others can't access their UISearchBar delegate methods. None of those solutions have worked for me. Why can't I access my delegate methods thus far?
If none of the delegate methods are working my guess is that your searchBarDelegate is being deallocated for some reason, it is hard to tell without seeing the whole code, but be sure to keep a strong reference to whoever is your searchBarDelegate, because the delegate itself is weak meaning if no one else is retaining it it could be deallocated and thus there is no delegate to respond to the calls.

add individual amount of buttons to cell programmatically

I want to build the following programmatically:
but I want to add the custom buttons programmatically. Here I have no idea, how the tell the buttons to respect the space between them and how to resize the height of the cell if the next button didn't fits into the same "row".
i tried with constraints:
import Material
class ChipButton: Button {
override func prepare() {
super.prepare()
cornerRadiusPreset = .cornerRadius5
backgroundColor = UIColor.lightGray
titleColor = Color.darkText.primary
pulseAnimation = .none
contentEdgeInsets = EdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
isUserInteractionEnabled = false
titleLabel?.font = RobotoFont.regular
isOpaque = true
let constraintTop = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: superview, attribute: .top, multiplier: 1, constant: 4)
let constraintLeading = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: superview, attribute: .leading, multiplier: 1, constant: 4)
superview?.addConstraint(constraintTop)
superview?.addConstraint(constraintLeading)
}
}
and I add the buttons like the following:
for tag in item.tags {
let chip = ChipButton()
chip.title = tag.text
cell!.layout(chip).edges(top: 4, left: 4, bottom: 4, right: 4)
}
but the declaration of constrainTop and constrainLeading throws an error and without the constraints the buttons r on top of each other the and the size of the buttons r false.
The comment of #Palpatim inspired to do it like the following:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell?
if let item: TagItem = items[indexPath.section][indexPath.row] as? TagItem {
if (item.tags.count > 0) {
// show all tags as a Chip
cell = TableViewCell()
cell?.isUserInteractionEnabled = false
var hStackView = UIStackView()
hStackView.axis = .horizontal
hStackView.spacing = 8
hStackView.alignment = .fill
hStackView.distribution = .fill
let vStackView = UIStackView()
vStackView.axis = .vertical
vStackView.spacing = 8
vStackView.alignment = .top
var tagsWidth: CGFloat = 0
for tag in item.tags {
let chip = ChipButton()
chip.title = tag.text
chip.sizeToFit()
if (tagsWidth + chip.bounds.width < (cell?.bounds.width)!) {
tagsWidth += chip.bounds.width
hStackView.addArrangedSubview(chip)
}
else {
vStackView.addArrangedSubview(hStackView)
tagsWidth = chip.bounds.width
hStackView = UIStackView()
hStackView.axis = .horizontal
hStackView.spacing = 8
hStackView.alignment = .fill
hStackView.distribution = .fill
hStackView.addArrangedSubview(chip)
}
}
vStackView.addArrangedSubview(hStackView)
cell!.layout(vStackView).edges(left: 16, right: 16).centerVertically()
return cell!
}
else {
cell = TableViewCell(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 40))
// show a label
let infoLabel = UILabel()
infoLabel.text = "no tags"
cell!.layout(infoLabel).centerVertically().edges(left: 16)
return cell!
}
}
cell = TableViewCell()
return cell!
}
and the result is:

Swift : How to make a Black screen to guidelines for user to use app

Im using swift 1.2.
I need to create a guideline for user to use my app.
it look like: a black transparent screen, 1 button highlight with note how to use, what is it.
i have searching for solution but still get stuck.
Can anybody help me?
Thanks!
If I understood correctly what you want, it can be done something like this*:
class TutorialView : UIView
{
override init(frame: CGRect)
{
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5)
}
convenience init()
{
self.init(frame: CGRectZero)
}
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
func showFromWindow()
{
let window = UIApplication.sharedApplication().keyWindow!
self.translatesAutoresizingMaskIntoConstraints = false
window.addSubview(self)
window.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[tutorialView]-0-|", options: NSLayoutFormatOptions.DirectionLeftToRight, metrics: nil, views: ["tutorialView": self]))
window.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[tutorialView]-0-|", options: NSLayoutFormatOptions.DirectionLeftToRight, metrics: nil, views: ["tutorialView": self]))
}
func addCommentToTopRightItem(comment: String, afterDelay: NSTimeInterval)
{
let topMargin : Int32 = 54
let rightMargin : Int32 = 24
let height : Int32 = 100
// we need two views - one for arrow and second for text
let commentLabel = UILabel()
let arrowView = UIView()
commentLabel.translatesAutoresizingMaskIntoConstraints = false
arrowView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(commentLabel)
self.addSubview(arrowView)
// setup layout for views
// |^^^^^|
// |^^^^^|arrow|
// |label|_____|
// |_____|
//
// we place center of Y label to the bottom of arrow view
// to an arrow coming out of the middle of text
let metrics = ["topmargin" : NSNumber(int: topMargin), "rightmargin": NSNumber(int: rightMargin),"height" : NSNumber(int: height)]
let views = ["label": commentLabel, "arrow": arrowView]
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-topmargin-[arrow(==height)]", options: NSLayoutFormatOptions.DirectionLeftToRight, metrics: metrics, views: views))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[label(==height)]", options: NSLayoutFormatOptions.DirectionLeftToRight, metrics: metrics, views: views))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-rightmargin-[arrow(==height)]-[label]-0-|", options: NSLayoutFormatOptions.DirectionRightToLeft, metrics: metrics, views: views))
self.addConstraint(NSLayoutConstraint(item: commentLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: arrowView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 1.0))
// configure text label
commentLabel.textColor = UIColor.whiteColor()
commentLabel.numberOfLines = 0
commentLabel.textAlignment = NSTextAlignment.Right
commentLabel.font = UIFont(name: "HelveticaNeue-Light", size: 16)
commentLabel.text = comment
// configure arrow view
self.layoutIfNeeded()
let d : CGFloat = min(arrowView.frame.size.height, arrowView.frame.size.width)
// draw arc line from {0, 1} to {1, 0}
// | /|
// |/_|
let linePath = UIBezierPath()
linePath.moveToPoint(CGPointMake(0, d))
linePath.addCurveToPoint(CGPointMake(d, 0), controlPoint1: CGPointMake(d*0.5, d), controlPoint2: CGPointMake(d, d*0.5))
let lineLayer = CAShapeLayer()
lineLayer.path = linePath.CGPath
lineLayer.strokeColor = UIColor.redColor().CGColor
lineLayer.backgroundColor = UIColor.clearColor().CGColor
lineLayer.fillColor = UIColor.clearColor().CGColor
lineLayer.lineWidth = 2
// draw triangle near {1, 0} point
let trianglePath = UIBezierPath()
trianglePath.moveToPoint(CGPointMake(d, 0))
trianglePath.addLineToPoint(CGPointMake(d - 5, 15))
trianglePath.addLineToPoint(CGPointMake(d + 5, 15))
trianglePath.closePath()
let triangleLayer = CAShapeLayer()
triangleLayer.path = trianglePath.CGPath
triangleLayer.strokeColor = UIColor.redColor().CGColor
triangleLayer.backgroundColor = UIColor.clearColor().CGColor
triangleLayer.fillColor = UIColor.redColor().CGColor
triangleLayer.lineWidth = 2
// line + triangle = arrow :)
arrowView.layer.addSublayer(lineLayer)
arrowView.layer.addSublayer(triangleLayer)
arrowView.alpha = 0.0
commentLabel.alpha = 0.0
UIView.animateWithDuration(0.8, delay: afterDelay, options: UIViewAnimationOptions.AllowAnimatedContent, animations:
{ () -> Void in
arrowView.alpha = 1.0
commentLabel.alpha = 1.0
}, completion: nil)
}
func addButton(title: String, highlighteAfterDelay: NSTimeInterval)
{
// same as before
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(button)
self.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 1.0))
self.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: -20.0))
self.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 120.0))
self.addConstraint(NSLayoutConstraint(item: button, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 40.0))
button.setTitle(title, forState: UIControlState.Normal)
button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
button.layer.cornerRadius = 20.0
button.layer.masksToBounds = false
button.layer.borderWidth = 1.0
button.layer.borderColor = UIColor.whiteColor().CGColor
button.layer.shadowColor = UIColor.whiteColor().CGColor
button.layer.shadowOpacity = 0.4
button.layer.shadowRadius = 4
button.layer.shadowOffset = CGSizeMake(0, 0)
button.alpha = 0.2
button.enabled = false
UIView.animateWithDuration(0.8, delay: highlighteAfterDelay, options: UIViewAnimationOptions.AllowAnimatedContent, animations:
{ () -> Void in
button.alpha = 1.0
button.enabled = true
}, completion: nil)
}
}
In some view controller:
let tutorial = TutorialView()
tutorial.showFromWindow()
tutorial.addCommentToTopRightItem("Tap this button to do something amazing action!", afterDelay: 1.0)
tutorial.addButton("Done", highlighteAfterDelay: 3.0)
Result:
*I don't have a compiler version 1.2 but I think that there should be no serious differences.
I see the problem now, you can add UView on top of it, give it a color with alpha, and get frame by using
convertRect(button.frame, toView:overlayView)
Hopefuly helps

How to turn decimal into a fraction - Swift

I have a fraction calculator and when I calculate it, it turns into a decimal. I want to turn it into a fraction. I don't know how to do it in code but I tried separating the calculations but it wouldn't work here is the code with a screenshot of my storyboard https://www.dropbox.com/s/fmapxaou49zap05/iOS%20Simulator%20Screen%20Shot%20Oct%2015%2C%202014%2C%209.37.43%20PM.png?dl=0
//Adding Function
changingSignsLabel.text = "+"
let firstDenomInTextField:Double! = (firstDenominatorTextField.text as NSString).doubleValue
let firstNumInTextField:Double! = (firstNumeratorTextField.text as NSString).doubleValue
let firstWholeInTextField:Double! = (firstWholeNumberTextField.text as NSString).doubleValue
let secondDenomInTextField:Double! = (secondDenominatorTextField.text as NSString).doubleValue
let secondNumInTextField:Double! = (secondNumeratorTextField.text as NSString).doubleValue
let secondWholeInTextField:Double! = (secondWholeNumberTextField.text as NSString).doubleValue
var firstStep = firstDenomInTextField! * firstWholeInTextField! / firstDenomInTextField!
var secondStep = firstStep + firstNumInTextField! / firstDenomInTextField!
var thirdStep = secondDenomInTextField! * secondWholeInTextField! / secondDenomInTextField!
var fourthStep = thirdStep + secondNumInTextField! / secondDenomInTextField!
var calculatedAnswer = (secondStep + fourthStep)
answerLabel.hidden = false
answerLabel.text = "\(calculatedAnswer)"
If you have any questions or concerns please comment them down below
Thank you for your help
For this to work every time, you want to use the Euclidian Algorithm, which in swift looks like this:
func simplify(top:Int, bottom:Int) -> (newTop:Int, newBottom:Int) {
var x = top
var y = bottom
while (y != 0) {
var buffer = y
y = x % y
x = buffer
}
var hcfVal = x
var newTopVal = top/hcfVal
var newBottomVal = bottom/hcfVal
return(newTopVal, newBottomVal)
}
You should just be able to add this to your program, then call it with:
simplify(5,10)
...returning 1 and 2. Hope this helps anyone else trying to find a simpler answer to this question.
Updated Answer
I wrote you a demo app:
Swift Source Code:
Put this inside your view controller.
var numeratorField:UITextField?;
var denominatorField:UITextField?;
var equalButton:UIButton?;
var wholeNumberLabel:UILabel?;
var numeratorLabel:UILabel?;
var denominatorLabel:UILabel?;
var dividerLine:UIView?;
var appName:UILabel?;
var instructions:UILabel?;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initViews();
initConstraints();
}
// ---------------------------------------------------------------------
// MARK: Interface Setup
// ---------------------------------------------------------------------
func initViews()
{
self.numeratorField = UITextField();
self.numeratorField?.layer.cornerRadius = 5.0;
self.numeratorField?.layer.borderWidth = 1.0;
self.numeratorField?.textAlignment = NSTextAlignment.Center;
self.denominatorField = UITextField();
self.denominatorField?.layer.cornerRadius = 5.0;
self.denominatorField?.layer.borderWidth = 1.0;
self.denominatorField?.textAlignment = NSTextAlignment.Center;
self.equalButton = UIButton();
self.equalButton?.setTitle("=", forState: UIControlState.Normal);
self.equalButton?.addTarget(self, action: "calculateAnswer", forControlEvents: UIControlEvents.TouchUpInside);
self.equalButton?.setTitleColor(UIColor.darkGrayColor(), forState: UIControlState.Normal);
self.equalButton?.layer.cornerRadius = 5.0;
self.equalButton?.backgroundColor = UIColor.lightGrayColor();
self.wholeNumberLabel = UILabel();
self.wholeNumberLabel?.textAlignment = NSTextAlignment.Right;
self.wholeNumberLabel?.font = UIFont(name: "HelveticaNeue", size: 20);
self.numeratorLabel = UILabel();
self.numeratorLabel?.textAlignment = NSTextAlignment.Center;
self.numeratorLabel?.font = UIFont(name: "HelveticaNeue", size: 14);
self.denominatorLabel = UILabel();
self.denominatorLabel?.textAlignment = NSTextAlignment.Center;
self.denominatorLabel?.font = UIFont(name: "HelveticaNeue", size: 14);
self.dividerLine = UIView();
self.dividerLine?.backgroundColor = self.numeratorLabel!.textColor;
self.dividerLine?.alpha = 0;
self.appName = UILabel();
self.appName?.text = "Fraction App";
self.appName?.font = UIFont(name: "HelveticaNeue-Bold", size: 24);
self.appName?.textAlignment = NSTextAlignment.Center;
self.instructions = UILabel();
self.instructions?.textAlignment = NSTextAlignment.Center;
self.instructions?.text = "Enter a value in the numerator and denominator field, then press the equal sign to see the answer";
self.instructions?.numberOfLines = 0;
self.instructions?.lineBreakMode = NSLineBreakMode.ByWordWrapping;
self.view.addSubview(self.numeratorField!);
self.view.addSubview(self.denominatorField!);
self.view.addSubview(self.equalButton!);
self.view.addSubview(self.wholeNumberLabel!);
self.view.addSubview(self.numeratorLabel!);
self.view.addSubview(self.denominatorLabel!);
self.view.addSubview(self.dividerLine!);
self.view.addSubview(self.appName!);
self.view.addSubview(self.instructions!);
}
func initConstraints()
{
self.appName?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.numeratorField?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.denominatorField?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.equalButton?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.wholeNumberLabel?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.numeratorLabel?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.denominatorLabel?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.dividerLine?.setTranslatesAutoresizingMaskIntoConstraints(false);
self.instructions?.setTranslatesAutoresizingMaskIntoConstraints(false);
var views:NSMutableDictionary = NSMutableDictionary();
views.setValue(self.appName, forKey: "appName");
views.setValue(self.numeratorField, forKey: "numeratorField");
views.setValue(self.denominatorField, forKey: "denominatorField");
views.setValue(self.equalButton, forKey: "equalButton");
views.setValue(self.wholeNumberLabel, forKey: "wholeNumberLabel")
views.setValue(self.numeratorLabel, forKey: "numeratorLabel");
views.setValue(self.denominatorLabel, forKey: "denominatorLabel");
views.setValue(self.dividerLine, forKey: "dividerLine");
views.setValue(self.instructions, forKey: "instructions");
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[appName]|", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[appName]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[instructions]-20-|", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[instructions]-100-|", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-35-[numeratorField(75)]-10-[denominatorField(==numeratorField)]-10-[equalButton]-10-[wholeNumberLabel(>=20)]-2-[dividerLine(15)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[numeratorField(50)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[denominatorField(==numeratorField)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[equalButton(==numeratorField)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[wholeNumberLabel(==numeratorField)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[numeratorLabel]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[denominatorLabel]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[dividerLine(1)]", options: nil, metrics: nil, views: views));
self.view.addConstraint(NSLayoutConstraint(item: self.numeratorLabel!, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.wholeNumberLabel, attribute: NSLayoutAttribute.Right, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.denominatorLabel!, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.wholeNumberLabel, attribute: NSLayoutAttribute.Right, multiplier: 1.0, constant: 0.0));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[numeratorLabel(==wholeNumberLabel)]", options: nil, metrics: nil, views: views));
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[denominatorLabel(==wholeNumberLabel)]", options: nil, metrics: nil, views: views));
self.view.addConstraint(NSLayoutConstraint(item: self.numeratorField!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.denominatorField!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.equalButton!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.wholeNumberLabel!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.dividerLine!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.numeratorLabel!, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.wholeNumberLabel, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
self.view.addConstraint(NSLayoutConstraint(item: self.denominatorLabel!, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.wholeNumberLabel, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0.0));
}
func getLowestCommonDenominator(Numerator numerator:Int, Denominator denominator:Int) -> Int
{
var finalDenominator = denominator;
//println("\(numerator) / \(finalDenominator) = \(numerator % finalDenominator)");
if(numerator % 2 == 0 && finalDenominator % 2 == 0) // even number
{
return self.getLowestCommonDenominator(Numerator: numerator / 2.0, Denominator: finalDenominator / 2.0);
}
else if(numerator % 3 == 0 && finalDenominator % 3 == 0) // odd number
{
return self.getLowestCommonDenominator(Numerator: numerator / 3.0, Denominator: finalDenominator / 3.0);
}
else // prime number, always have a remainder
{
//println("lowest common denominator = \(finalDenominator)");
return finalDenominator;
}
}
func calculateAnswer()
{
// prevent division by zero
if(self.denominatorField?.text == "0")
{
var alert:UIAlertView = UIAlertView(title: "Division By Zero", message: "Divide by zero yields undefined value", delegate: self, cancelButtonTitle: "OK");
alert.show();
return;
}
// clear previous values;
self.wholeNumberLabel?.text = "";
self.numeratorLabel?.text = "";
self.denominatorLabel?.text = "";
var numeratorString:NSString = self.numeratorField!.text;
var denominatorString:NSString = self.denominatorField!.text;
if (numeratorString.length == 0 || denominatorString.length == 0)
{
//var alert:UIAlertView = UIAlertView(title: "Input Missing", message: "Enter a value for numerator and denominator then press the equal sign to get the answer", delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: nil, nil);
var alert:UIAlertView = UIAlertView(title: "Input Missing", message: "Enter a value for numerator and denominator then press the equal sign to get the answer", delegate: nil, cancelButtonTitle: "OK");
alert.show();
}
else
{
var shouldShowWholeParts:Bool = false;
var shouldShowFractionParts:Bool = false;
var numerator:Int = self.numeratorField!.text.toInt()!;
var denominator:Int = self.denominatorField!.text.toInt()!;
var finalNumerator = numerator;
var finalDenominator = self.getLowestCommonDenominator(Numerator: numerator, Denominator: denominator);
if(finalDenominator < denominator)
{
denominator = finalDenominator;
numerator = numerator / finalDenominator;
}
var wholeNumbers:Int = numerator / denominator;
var remainder:Int = numerator % denominator;
//println("wholeNumbers = \(wholeNumbers), remainder = \(remainder)");
//println("\(denominator) % \(remainder) = \(denominator % remainder)");
if(wholeNumbers != 0)
{
shouldShowWholeParts = true;
}
else
{
shouldShowWholeParts = false;
}
if(remainder > 0)
{
// see if we can simply the fraction part as well
if(denominator % remainder == 0) // no remainder means remainder can be simplified further
{
finalDenominator = denominator / remainder;
finalNumerator = remainder / remainder;
}
else
{
finalNumerator = remainder;
finalDenominator = denominator;
}
shouldShowFractionParts = true;
}
else
{
shouldShowFractionParts = false;
}
var answer:NSString?;
if(wholeNumbers > 0 && remainder > 0)
{
answer = NSString(format: "\(wholeNumbers) \(finalNumerator)/\(finalDenominator)");
// prints out whole number and fraction parts
//println("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers) \(finalNumerator)/\(finalDenominator)");
}
else if (wholeNumbers > 0 && remainder == 0)
{
answer = NSString(format: "\(wholeNumbers)");
// prints out whole number only
//println("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers)");
}
else
{
answer = NSString(format: "\(finalNumerator)/\(finalDenominator)");
// prints out fraction part only
//println("Simplified fraction of \(numerator)/\(denominator) = \(finalNumerator)/\(finalDenominator)");
}
if(shouldShowWholeParts)
{
self.wholeNumberLabel?.text = NSString(format: "\(wholeNumbers)");
}
if(shouldShowFractionParts)
{
self.numeratorLabel?.text = NSString(format: "\(finalNumerator)");
self.denominatorLabel?.text = NSString(format: "\(finalDenominator)");
self.dividerLine?.alpha = 1;
}
else
{
self.dividerLine?.alpha = 0;
}
}
}
Original Answer
Is this what you're looking for?
Results:
Simplified fraction of 7/8 = 7/8
Simplified fraction of 12/8 = 1 1/2
Simplified fraction of 5/16 = 5/16
Simplified fraction of 342/23 = 14 20/23
Simplified fraction of 129/72 = 1 57/72
Source Code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
printSimplifiedFraction(Numerator: 7, Denominator: 8);
printSimplifiedFraction(Numerator: 12, Denominator: 8);
printSimplifiedFraction(Numerator: 5, Denominator: 16);
printSimplifiedFraction(Numerator: 342, Denominator: 23);
printSimplifiedFraction(Numerator: 129, Denominator: 72);
}
func printSimplifiedFraction(Numerator numerator: Int, Denominator denominator:Int)
{
var finalNumerator = numerator;
var finalDenominator = denominator;
var wholeNumbers:Int = numerator / denominator;
var remainder:Int = numerator % denominator;
//println("wholeNumbers = \(wholeNumbers), remainder = \(remainder)");
//println("\(denominator) % \(remainder) = \(denominator % remainder)");
if(remainder > 0)
{
// see if we can simply the fraction part as well
if(denominator % remainder == 0) // no remainder means remainder can be simplified further
{
finalDenominator = denominator / remainder;
finalNumerator = remainder / remainder;
}
else
{
finalNumerator = remainder;
finalDenominator = denominator;
}
}
if(wholeNumbers > 0 && remainder > 0)
{
// prints out whole number and fraction parts
println("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers) \(finalNumerator)/\(finalDenominator)");
}
else if (wholeNumbers > 0 && remainder == 0)
{
// prints out whole number only
println("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers)");
}
else
{
// prints out fraction part only
println("Simplified fraction of \(numerator)/\(denominator) = \(finalNumerator)/\(finalDenominator)");
}
}
Unfortunately there is not framework you can import to display a fraction in swift or Xcode. What I would recommend is using the same method you used in your storyboard: Have two UILabelView's, one on top of each other, with a line between them.
Instead of calculating the decimal, use basic math to find the numerator and denominator and display them on the top and bottom of the UILabelView.
This method will require changing your program at a fundamental level, however it will work.

Resources