Swift 4 Page Controll Watcher - ios

I'm using xcode 9.1 and swift 4.
I have 2 Buttons in my View Controller, and i want their colors changed when my carousel page is changed.
Here's my code but it.
I want it to check every time my carousel Scrolls.
is there any "OnPageControl" Methods in swift 4?
Here's my code ( in viewDidLoad ) :
if (self.carousel.pageControl.currentPage == 0)
{
self.registerButton.layer.borderColor = UIColor(red:68/255.0, green:180/255.0, blue:194/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:68/255.0, green:180/255.0, blue:194/255.0, alpha: 1.0).cgColor
NSLog("1")
}
else if (self.carousel.pageControl.currentPage == 1)
{
self.registerButton.layer.borderColor = UIColor(red:139/255.0, green:21/255.0, blue:21/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:139/255.0, green:21/255.0, blue:21/255.0, alpha: 1.0).cgColor
NSLog("2")
}
else if (self.carousel.pageControl.currentPage == 2)
{
self.registerButton.layer.borderColor = UIColor(red:174/255.0, green:135/255.0, blue:46/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:174/255.0, green:135/255.0, blue:46/255.0, alpha: 1.0).cgColor
NSLog("3")
}

There is nothing like a UIPageControlDelegate but UIScrollViewDelegate offers scrollViewDidScroll for that purpose. Using scrollView.contentOffset.x you can get the current page, assign it to the pageControl.currentPage and update your buttons there.

Related

RangeSeekSlider should start from Right to Left if language is Arabic

I am using RangeSeekSlider for displaying slider in my app. In normal case i.e. for all the LTR languages(Left to Right) it is working perfectly. But when working with languages like Arabic which require the slider to start from Right to Left i.e. opposite of the normal it is not working for me.
For your reference i have tried following piece of code but it did not worked for me,
#IBOutlet weak var sliderAmount: RangeSeekSlider!
override func viewDidLoad() {
super.viewDidLoad()
if AppUtils.checkIfArabic() == true{
sliderAmount.semanticContentAttribute = .forceRightToLeft
}else{
self.sliderAmount.semanticContentAttribute = .forceLeftToRight
}
// Do any additional setup after loading the view.
}
Following is the screenshot of normal slider which is setup using below code
//MARK:- Setup Slider View
func setupSliderView(){
sliderAmount.disableRange = true
sliderAmount.enableStep = true
sliderAmount.step = 500
sliderAmount.delegate = self
sliderAmount.minValue = 500.0
lblAmt.text = "500"
sliderAmount.maxValue = 25000.0
sliderAmount.handleImage = UIImage(named: "ic_SliderHandler")
sliderAmount.handleDiameter = 35.0
sliderAmount.lineHeight = 7.0
sliderAmount.hideLabels = true
sliderAmount.tintColor = UIColor(displayP3Red: 235/255, green: 235/255, blue: 235/255, alpha: 1.0)
sliderAmount.colorBetweenHandles = UIColor(displayP3Red: 135/255, green: 102/255, blue: 123/255, alpha: 1.0)
}
Current output:
TIA.
Solved the issue using following piece of code
if L102Language.currentAppleLanguage() == "ar" { //Arabic
UIView.animate(withDuration: 0.1) {
self.sliderAmount.transform = CGAffineTransform(scaleX: -1, y: 1);
}
}
So, the Output now is,

My app doesn't do the code I've been write Swift

I'm trying to understand why my code is not totally played by my application?
In fact I have a button on a viewController when the user press the button two textfield is normal become interactive and the background will change to show the possibility of interaction. When I've do the code and make the first test it work ! It work also in an other view but after some tests the button juste change his hidden property but do nothing else. Cf code :
#IBAction func modifyBtnWasPressed(_ sender: UIButton) {
//We change the button by the save button
modifyBtn.isHidden = true
saveBtn.isHidden = false
//We enable 2 tf and we show to the user the 2 TF which will be enable
acftRegistrationTxt.isUserInteractionEnabled = true
acftModelTxt.isUserInteractionEnabled = true
acftRegistrationTxt.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0);
acftModelTxt.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0);
}
Now in this case only the isHidden property work the next 4 lines doesn't apply on the application.

Random number corresponding to array of UIColors- ERROR

I have a function that creates a CGRect and I am trying to assign a random color to each of them.
I create the colors as variables with the type UIColor and then put them into an array called colors. Then, I create a random number generator and call it when defining the background color of the CGRect, but I get the error:
Cannot call value of non-function type "[UIColor}"
Why is this? Here is my code:
func addBox(location: CGRect) -> UIView {
let newBox = UIView(frame: location)
let red = UIColor(red: (242.0/255.0), green: (186.0/255.0), blue: (201.0/255.0), alpha: 1.0)
let green = UIColor(red: (186.0/255.0), green: (242.0/255.0), blue: (216.0/255.0), alpha: 1.0)
let yellow = UIColor(red: (242.0/255.0), green: (226.0/255.0), blue: (186.0/255.0), alpha: 1.0)
let blue = UIColor(red: (186.0/255.0), green: (216.0/255.0), blue: (242.0/255.0), alpha: 1.0)
let colors = [red, green, yellow, blue]
let randomNum:UInt32 = arc4random_uniform(4)
newBox.backgroundColor = UIColor(colors(randomNum))
hView.insertSubview(newBox, at: 0)
return newBox
}
If anyone could solve this that would be amazing. Any help would be immensely appreciated!! Thanks a ton in advance.
This:
newBox.backgroundColor = UIColor(colors(randomNum))
should be:
newBox.backgroundColor = colors[randomNum]
colors is an array of UIColor. You just need one element from the array.
You should also change:
let randomNum:UInt32 = arc4random_uniform(4)
to:
let randomNum = Int(arc4random_uniform(colors.count))
This way if you add more colors to the array, you don't need to adjust this line. It makes your code less error prone.

How to loop through array and start again if the array is at the end?

I have an array of colors, that I want to apply to uitableviewcells in iOS.
let colorPalet = [
UIColor(red: 255.0/255.0, green: 159.0/255.0, blue: 112.0/255.0, alpha: 1),
UIColor(red: 81.0/255.0, green: 218.0/255.0, blue: 168.0/255.0, alpha: 1),
UIColor(red: 2.0/255.0, green: 207.0/255.0, blue: 255.0/255.0, alpha: 1),
UIColor(red: 144.0/255.0, green: 153.0/255.0, blue: 166.0/255.0, alpha: 1)
]
cell.backgroundColor = colorPalet[indexPath.row]
The problem is, then when indexPath.row is greater then the colorPalet array, it will crash, because there is no more entries in the array. How to start iteratie again through the array if it is at the end of the array in Swift?
you can use modulo:
cell.backgroudColor = colorPalet[indexPath.row % colorPalet.count]
for index in 0..array.count {
//Do stuff here
if (index == array.count -1)
{
index = 0
}
}
You can use something like this:
let index = indexPath.row%4
cell.something = colorPalet[index]
Make colorPalet an instance variable. You can just move the code below to the top of the class:
let colorPalet = [
UIColor(red: 255.0/255.0, green: 159.0/255.0, blue: 112.0/255.0, alpha: 1),
UIColor(red: 81.0/255.0, green: 218.0/255.0, blue: 168.0/255.0, alpha: 1),
UIColor(red: 2.0/255.0, green: 207.0/255.0, blue: 255.0/255.0, alpha: 1),
UIColor(red: 144.0/255.0, green: 153.0/255.0, blue: 166.0/255.0, alpha: 1)
]
That way you're not creating an array of colors for each cell you configure. Then use the modulo (`%) Code in ROC's answer:
cell.backgroudColor = colorPalet[indexPath.row % colorPalet.count]
The accepted answer already covers the specific situation of the OP (cell colors in a table view), whereas this answer will approach the more general question title:
How to loop through array and start again if the array is at the end?
The modulo operation naturally comes to mind,
truncatedIndex = runningIndexDividend % divisor
But what if we're to use this in a long running application, where the runningIndexDividend needlessly increase to values much larger than the divisor (possibly, in a theoretic contrived situation, even leading to integer overflow ...)? For such a case, an alternative, mainly to tap into the Sequence neatness of Swift, is to use an on-the-fly generating sequence: one which lazily constructs its next element upon demand.
Using the global sequence(state:next:) function
For the case of constructing a (infinite) sequence which repeatedly traverses a given array ("joining" the head with the tail), you could make use of the global sequence(state:next:) function.
E.g., applied to your example (here storing the colorPalet as a static member of ColorSettings utility class, just know the possible non-thread safety if using static properties in threaded applications):
class ColorSettings {
private static let colorPalet = [
UIColor(red: 255.0/255.0, green: 159.0/255.0, blue: 112.0/255.0, alpha: 1),
UIColor(red: 81.0/255.0, green: 218.0/255.0, blue: 168.0/255.0, alpha: 1),
UIColor(red: 2.0/255.0, green: 207.0/255.0, blue: 255.0/255.0, alpha: 1),
UIColor(red: 144.0/255.0, green: 153.0/255.0, blue: 166.0/255.0, alpha: 1)
]
static let colorSequence = sequence(
state: 1,
next: { (idx: inout Int) -> UIColor? in
guard colorPalet.count > 0 else { return nil }
defer { idx == colorPalet.count ? (idx = 1) : (idx += 1) }
/* alternatively (loose clarity/semantics to gain brevity)
defer { idx = idx % colorPalet.count + 1 } */
return colorPalet[idx-1]
})
}
Example "usage" (not really intended for this application)
// example usage
let numberOfRowsInSection = 7
for (row, color) in zip(0..<numberOfRowsInSection,
ColorSettings.colorSequence) {
// ...
print(row, color)
} /* 0 UIExtendedSRGBColorSpace 1 0.623529 0.439216 1
1 UIExtendedSRGBColorSpace 0.317647 0.854902 0.658824 1
2 UIExtendedSRGBColorSpace 0.00784314 0.811765 1 1
3 UIExtendedSRGBColorSpace 0.564706 0.6 0.65098 1
4 UIExtendedSRGBColorSpace 1 0.623529 0.439216 1
5 UIExtendedSRGBColorSpace 0.317647 0.854902 0.658824 1
6 UIExtendedSRGBColorSpace 0.00784314 0.811765 1 1 */
Note that the state will not be saved between two separate traversals of colorSequence. I.e., if copying the loop above and applying elsewhere, the first state will always correspond to the first color.
Also beware that when constructing an infinitely generating sequence as the one above, the sequence can naturally not terminate by itself (no nil return, apart from the empty colorPalet array case). Hence its practical use will mostly be in conjunction with a finite sequence with use of zip as above.
Using an external state property with AnyIterator
If you'd rather keep the end state in one traversal as a starting point for the subsequent one (not resetting it, as above), you could use an approach similar to the one above, but using a help state property combined with AnyIterator:
class ColorSettings {
private static let colorPalet = [
UIColor(red: 255.0/255.0, green: 159.0/255.0, blue: 112.0/255.0, alpha: 1),
UIColor(red: 81.0/255.0, green: 218.0/255.0, blue: 168.0/255.0, alpha: 1),
UIColor(red: 2.0/255.0, green: 207.0/255.0, blue: 255.0/255.0, alpha: 1),
UIColor(red: 144.0/255.0, green: 153.0/255.0, blue: 166.0/255.0, alpha: 1)
]
private static var idx: Int = 1
static let colorIterator: AnyIterator<UIColor> = AnyIterator {
guard colorPalet.count > 0 else { return nil }
defer { idx == colorPalet.count ? (idx = 1) : (idx += 1) }
return colorPalet[idx-1]
}
}
Example usage:
// first traversal
for (i, color) in zip(0..<2, ColorSettings.colorIterator) {
// ...
print(i, color)
} /* 0 UIExtendedSRGBColorSpace 1 0.623529 0.439216 1
1 UIExtendedSRGBColorSpace 0.317647 0.854902 0.658824 1 */
// state from previous traversal will be used
// to decide starting state here, in next
for (i, color) in zip(0..<4, ColorSettings.colorIterator) {
// ...
print(i, color)
} /* 0 UIExtendedSRGBColorSpace 0.00784314 0.811765 1 1
1 UIExtendedSRGBColorSpace 0.564706 0.6 0.65098 1
2 UIExtendedSRGBColorSpace 1 0.623529 0.439216 1
3 UIExtendedSRGBColorSpace 0.317647 0.854902 0.658824 1 */

Colors that will be used throughout an app or a class

I'm trying to improve my object oriented skills and I'm always debating if a class is needed or not.
I have a set of UIColors that I'm constantly using throughout my app in different ViewControllers, I originally started by adding them as constant globals as follow...
import UIKit
// Global COLORS
let myBlueColor = UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
// more global colors here...
class ViewController1{
// using my global color
myButton.layer.borderColor = myBlueColor.CGColor
}
// other viewController
import UIKit
class ViewController2{
// using my global color again
myButton2.layer.borderColor = myBlueColor.CGColor
}
But then I decided to created a class to force myself to think in more oriented way like so...
Color Class
import Foundation
import UIKit
class Color {
var myBlueColor:UIColor{
get{
return UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
}
}
var myLightGrayColor:UIColor{
get{
return UIColor(red: 249.0/255, green: 249.0/255, blue: 249.0/255, alpha: 1.0)
}
}
var myGreenColor:UIColor{
get{
return UIColor(red: 110.0/255, green: 186.0/255, blue: 64.0/255, alpha: 1.0)
}
}
var myRedColor:UIColor{
get{
return UIColor(red: 247.0/255, green: 118.0/255, blue: 113.0/255, alpha: 1.0)
}
}
var myYellowColor:UIColor{
get{
return UIColor(red: 255.0/255, green: 190.0/255, blue: 106.0/255, alpha: 1.0)
}
}
}
View Controller
import UIKit
class ViewController1{
private var myColor = Color()
// some other code here...
myButton.layer.borderColor = myBlueColor.CGColor
}
Other View Controller
import UIKit
class ViewController1{
private var myColor = Color()
// some other code here...
myButton2.layer.borderColor = myBlueColor.CGColor
}
Is my object oriented a better approach? Ok let me rephrase this, is this even how you would do it in a more object oriented way?
I don't know but my Color class looks weird by just using getters (computed properties).
Any suggestions to improve my code.
EDIT: Not a duplicate because I was interested on improving my object oriented example more than knowing if globals were ok to use.
Thanks
Definitely a good idea, but you can probably make it even more clear by just extending UIColor and making those all class functions, exactly the same way as the built-in UIColor.whiteColor(), etc.
You can do that like this:
extension UIColor {
class func peachColor() -> UIColor {
return UIColor(colorLiteralRed: 100.00 / 100.00, green: 92.9 / 100.0, blue: 65.9 / 100.0, alpha: 1.0)
}
...
}
Then, anywhere in your app, you can say UIColor.peachColor() and it'll work perfectly. These class extensions are a clean way to do it, and it'll allow you to avoid putting a var myColor = Color() in each view controller.
If you want to encapsulate your Colors in a class, and they will not change, the best way to do so in an OOP environment is by using public static final variables.
(My Swift is very rusty at best so this may be incorrect syntax but it should be clear nonetheless.)
final struct MyColors {
public static final blue:UIColor = UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
// etc
}
You can then reference the value by using MyColors.blue wherever you want, and that will refer to the single defined UIColor object.
Assuming that you're trying to theme your app globally with colors, you ought to look into Apple's Appearance API, UIAppearance.
For example, to set the default color of all UINavigationBars in your app, you would call:
UINavigationBar.appearance().tintColor = myColor
You can also set other appearance properties such as background images
For more info, see:
http://nshipster.com/uiappearance/
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAppearance_Protocol/
https://gist.github.com/mattt/5135521

Resources