Programming & Web Design Articles
Ever wonder what makes the software, websites, and blogs you use every day function properly (or improperly)? It's programming. Our articles reveal the ins and outs of programming and web design.
Articles From Programming & Web Design
Filter Results
Article / Updated 08-10-2022
SwiftUI makes creating your iOS applications easy and efficient. However, there are neat tricks that are not so obvious. Here, you learn some of these tips and tricks so that you can become a better SwiftUI developer. Resume SwiftUI’s live preview My number-one pet peeve about SwiftUI is that the live preview feature in Xcode doesn’t always work. Very often, changes made to your code will cause the automatic previewing feature to pause. Even though your code is perfectly correct and there is no error, the live preview just can’t seem to update automatically. Of course, you could click the Resume button to update the preview, but you waste precious time moving your mouse to click the button. A better way is to press ⌘+Option+P. This causes the live preview to resume and update itself. Now that you know this trick, there is no reason to click the Resume button anymore! You may also want to check out the list of shortcuts for working in Xcode. Combine text views in SwiftUI Here is a neat little trick that you should know if you want to display the various words in a sentence in different colors and sizes. Instead of using the HStack view to group various Text views together, you can simply use the plus (+) operator to add different Text views together, like this: struct ContentView: View { var body: some View { Text("Red ") .foregroundColor(.red) .font(.largeTitle) + Text("Green ") .foregroundColor(.green) .font(.body) + Text("Blue") .foregroundColor(.blue) .font(.title) } } How cool is that? Here’s the output. If you want all the texts to be of the same font size, group them together using a Group view and apply the font() modifier on the Group view: struct ContentView: View { var body: some View { Group { Text("Red ") .foregroundColor(.red) + Text("Green ") .foregroundColor(.green) + Text("Blue") .foregroundColor(.blue) } .font(.largeTitle) } } Create custom modifiers in SwiftUI Swift modifiers allow you to change the behaviors of views. Consider the following example: import SwiftUI struct ContentView: View { var body: some View { VStack { Text("Leonardo da Vinci") .bold() .font(.largeTitle) .foregroundColor(.blue) .shadow(radius: 2) Text("Vincent van Gogh") .bold() .font(.largeTitle) .foregroundColor(.blue) .shadow(radius: 2) } } } Here, you apply the same set of modifiers to the two Text views. You often do that when you want to ensure consistencies in your UI (for example, applying the same set of UI styles when displaying certain information in your application). Instead of repeating the same set of modifiers again and again, wouldn’t it be easier if you could just encapsulate all the modifiers into yet another modifier? What you can do it is create another struct that conforms to the ViewModifier protocol. This protocol requires you to implement a body() method that has a Content parameter. You then apply whatever modifiers you want to this Content argument and return it: import SwiftUI struct Title: ViewModifier { func body(content: Content) -> some View { content .font(.largeTitle) .foregroundColor(.blue) .shadow(radius: 2) } } To use the newly created Title struct on the Text view, apply the modifier() modifier and pass in the Title struct, like this: struct ContentView: View { var body: some View { VStack { Text("Leonardo da Vinci") .bold() .modifier(Title()) Text("Vincent van Gogh") .bold() .modifier(Title()) } } } To make the Title struct look more like a true modifier, create an extension to the View protocol and give it a name — say, titleStyle: import SwiftUI extension View { func titleStyle() -> some View { self.modifier(Title()) } } You can now apply the titleStyle() modifier to the two Text views: struct ContentView: View { var body: some View { VStack { Text("Leonardo da Vinci") .bold() .titleStyle() Text("Vincent van Gogh") .bold() .titleStyle() } } } Display multiple alerts in SwiftUI Usually, in SwiftUI you apply a single alert() modifier to a single view. For example, when the user taps a button, you can display an alert by using the alert() modifier to the button. If you have multiple buttons, you can attach an alert() modifier to each button. However, there are times when you need to display multiple different alerts for a single view. Applying multiple alert() modifiers to a single view will not work correctly, because the last modifier will override the earlier ones. To solve this problem, you can use a single alert() modifier, and use a switch statement within the modifier to decide which alert to display. The following example shows a button that, when it’s clicked, generates a random number of either 1 or 2 and uses it to decide which alert to display: struct ContentView: View { @State private var displayAlert = false @State private var alertToDisplay = 0 var body: some View { Button(action: { self.alertToDisplay = Int.random(in: 1..<3) self.displayAlert = true }) { Text("Display Alert") } .alert(isPresented: $displayAlert) { switch alertToDisplay { case 1: return Alert(title: Text("Alert 1"), message: Text("This is Alert 1")) default: return Alert(title: Text("Alert 2"), message: Text("This is Alert 2")) } } } } Enable debug preview in SwiftUI By default, the preview canvas doesn’t display outputs printed using the print() function. This isn’t useful, however, because often you want to use the print() function as a quick debugging option. The good news is, you can easily fix this. In the preview canvas, right-click the Play button and select Debug Preview. Now if you tap the button, your code will print the output in the Output window: struct ContentView: View { var body: some View { Button ("Tap Me") { print("Button was tapped...") } } } If the Output window is not shown in Xcode, press ⌘+Shift+C and it should appear. Preview your SwiftUI app using different devices You’re familiar with using the preview canvas to preview your app. By default, Xcode automatically picks an appropriate device based on your target. You can preview your app on different modes — light mode and dark mode — using the environment() modifier: struct ContentView_Previews: PreviewProvider { static var previews: some View { Group { ContentView() .environment(\.colorScheme, .light) ContentView() .environment(\.colorScheme, .dark) } } } In addition to previewing in different modes, you can alter the size of the preview window, allowing you to have a glimpse of how your UI will look under different screen dimensions. You can do so using the previewLayout() modifier: static var previews: some View { Group { ContentView() .environment(\.colorScheme, .light) .previewLayout((.fixed(width: 400, height: 600))) ContentView() .environment(\.colorScheme, .dark) } } The image below shows the top preview displaying your UI in a dimension of 400 x 600 pixels. Note that clicking the Live Preview button will revert the preview back to the default size. If you want to preview your UI on multiple devices, you can use a ForEach loop, supply a list of device names, and then use the previewDevice() modifier on the ContentView, like this: static var previews: some View { ForEach(["iPhone 11", "iPhone SE"], id: \.self) { deviceName in ContentView() .environment(\.colorScheme, .light) .previewDevice(PreviewDevice( rawValue: deviceName)) .previewDisplayName(deviceName) } } The following image shows the preview on the iPhone 11 and the iPhone SE. Notice that you can display the name of the device using the previewDisplayName() modifier. Check out the full list of devices that you can preview. Dark mode only works on NavigationView As stated, you can use the environment() modifier to set the preview to dark mode so that you can see how your UI will look like in dark mode. However, it seems like the dark preview mode only works for the NavigationView. For example, consider the following example where you have two Text views contained within a VStack view: import SwiftUI struct ContentView: View { var body: some View { VStack { Text("Leonardo da Vinci") Text("Vincent van Gogh") } } } Suppose you use the environment() modifier to set the preview mode to dark, like this: struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .environment(\.colorScheme, .dark) } } The words in the Text views automatically change to white, but the background remains white (running on the simulator or an actual device doesn’t have this issue), as shown below. So, essentially, you get a white screen. To fix this problem, wrap the ContentView view using a ZStack and set its background to black, like this: struct ContentView_Previews: PreviewProvider { static var previews: some View { ZStack { Color(.black) ContentView() } .edgesIgnoringSafeArea(.all) .environment(\.colorScheme, .dark) } } The image below shows the text showing up on a black background. Extract subviews in SwiftUI Your UI may contain quite a large number of views. This is very common if you have a complicated UI. However, you can simplify your UI by extracting some of the views as subviews. Consider the following example: import SwiftUI struct ContentView: View { var body: some View { HStack { Image("weimenglee") .resizable() .frame(width: CGFloat(120), height: CGFloat(120)) .cornerRadius(CGFloat(15), antialiased: true) VStack { Text("Wei-Meng Lee") .font(.largeTitle) .bold() Text("Founder") Text("Developer Learning Solutions") .italic() Text("http://calendar.learn2develop.net") Text("@weimenglee") } } } } To break down the UI into smaller subviews so that your UI is more modular and manageable, follow these steps: In the preview canvas, select the Image view and press the ⌘ key. Select Extract Subview. Name the new view PhotoView. The Image view will now be extracted as a new struct named PhotoView: struct ContentView: View { var body: some View { HStack { PhotoView() VStack { Text("Wei-Meng Lee") .font(.largeTitle) .bold() Text("Founder") Text("Developer Learning Solutions") .italic() Text("http://calendar.learn2develop.net") Text("@weimenglee") } } } } struct PhotoView: View { var body: some View { Image("weimenglee") .resizable() .frame(width: CGFloat(120), height: CGFloat(120)) .cornerRadius(CGFloat(15), antialiased: true) } } You can now also extract the VStack and save it as another struct named DetailsView. Now your UI looks like the following, which is more maintainable: struct ContentView: View { var body: some View { HStack { PhotoView() DetailsView() } } } struct PhotoView: View { ... } struct DetailsView: View { var body: some View { VStack { Text("Wei-Meng Lee") .font(.largeTitle) .bold() Text("Founder") Text("Developer Learning Solutions") .italic() Text("http://calendar.learn2develop.net") Text("@weimenglee") } } } Display a context menu in SwiftUI One of the innovative features of iPhone is the support for Haptic Touch (which replaces the 3D Touch on older iPhones). Using Haptic Touch, you can long-press an item on your iPhone and a context-sensitive menu appears (if the app you’re using supports it). You can support this feature in SwiftUI as well. To attach a context menu to a view, use the contextMenu() modifier: To attach a context menu to a view, use the contextMenu() modifier: struct ContentView: View { var body: some View { Image("Mac Pro") .resizable() .frame(width: 300, height: 280) .contextMenu { Button(action: { print("Save Image button tapped...") }) { Text("Save Image") Image(systemName: "tray.and.arrow.down") } Button(action: { print("Add to Cart button tapped...") }) { Text("Add to Cart") Image(systemName: "plus") } } } } To create a context menu, you provide a list of Button views, and the content of each button is automatically wrapped using an HStack view. Now when you long-press the Image view, a context menu appears. Want to learn more? Check out our SwifUI Cheat Sheet.
View ArticleArticle / Updated 08-10-2022
SwiftUI is a declarative programming framework for developing UIs for iOS, iPadOS, watchOS, tvOS, and macOS applications. In fact, SwiftUI was invented by the watchOS group at Apple. Before SwiftUI was introduced, most developers use UIKit and Storyboard (which is still supported by Apple in the current version of Xcode to design a UI. Using UIKit and Storyboard, developers drag and drop View controls onto View Controllers and connect them to outlets and actions on the View Controller classes. This model of building UIs is known as Model View Controller (MVC), which creates a clean separation between UI and business logic. The following shows a simple implementation in UIKit and Storyboard. Here, a Button and Label view have been added to the View Controller in Storyboard; two outlets and an action have been created to connect to them: class ViewController: UIViewController { @IBOutlet weak var lbl: UILabel! @IBOutlet weak var button: UIButton! @IBAction func btnClicked(_ sender: Any) { lbl.text = "Button tapped" } For laying out the views, you use auto-layout to position the button and label in the middle of the screen (both horizontally and vertically). To customize the look and feel of the button, you can code it in the loadView() method, like this: override func loadView() { super.loadView() // background color button.backgroundColor = UIColor.yellow // button text and color button.setTitle("Submit", for: .normal) button.setTitleColor(.black, for: .normal) // padding button.contentEdgeInsets = UIEdgeInsets( top: 10, left: 10, bottom: 10, right: 10) // border button.layer.borderColor = UIColor.darkGray.cgColor button.layer.borderWidth = 3.0 // text font button.titleLabel!.font = UIFont.systemFont(ofSize: 26, weight: UIFont.Weight.regular) // rounder corners button.layer.cornerRadius = 10 // auto adjust button size button.sizeToFit() } The following image shows the button that has customized. UIKit is an event-driven framework, where you can reference each view in your view controller, update its appearance, or handle an event through delegates when some events occurred. In contrast, SwiftUI is a state-driven, declarative framework. In SwiftUI, you can implement all the above with the following statements: struct ContentView: View { @State private var label = "label" var body: some View { VStack { Button(action: { self.label = "Button tapped" }) { Text("Submit") .padding(EdgeInsets( top: 10, leading: 10, bottom: 10, trailing: 10)) .background(Color.yellow) .foregroundColor(Color.black) .border(Color.gray, width: 3) .font(Font.system(size: 26.0)) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(Color.gray, lineWidth: 5) ) } Text(label) .padding() } } } Notice that all the views are now created declaratively using code — no more drag-and-drop in Storyboard. Layouts are now also specified declaratively using code (the VStack in this example stacks all the views vertically). Delegates are now replaced with closures. More important, views are now a function of state (and not a sequence of events) — the text displayed by the Text view is now bound to the state variable label. When the button is tapped, you change the value of the label state variable, which automatically updates the text displayed in the Text view. This programming paradigm is known as reactive programming. The image below shows the various views in action. Want to learn more? Check out our SwiftUI Cheat Sheet.
View ArticleArticle / Updated 08-10-2022
Are you ready to build iOS apps using an innovative and intuitive user interface? Then, SwiftUI is for you! But before you dive in, you’ll need to know about Swift functions. Here’s a quick intro. In Swift, a function is defined using the func keyword, like this: func doSomething() { print("doSomething") } The preceding code snippet defines a function called doSomething. It does not take in any inputs (known as parameters) and does not return a value (technically, it does return a Void value). To call the function, simply call its name followed by a pair of empty parentheses: doSomething() Understanding input parameters A function can also optionally define one or more named typed inputs. The following function takes in one single typed input parameter: func doSomething(num: Int) { print(num) } To call this function, call its name and pass in an integer value (known as an argument) with the parameter name, like this: doSomething(num: 5) The following function takes in two input parameters, both of type Int: func doSomething(num1: Int, num2: Int) { print(num1, num2) } To call this function, pass it two integer values as the argument: doSomething(num1: 5, num2: 6) Returning a value Functions are not required to return a value. However, if you want the function to return a value, use the -> operator after the function declaration. The following function returns an integer value: func doSomething(num1: Int, num2: Int, num3: Int) -> Int { return num1 + num2 + num3 } You use the return keyword to return a value from a function and then exit it. When the function returns a value, you can assign it to a variable or constant, like this: var sum = doSomething(num1:5, num2:6, num3: 7) Functions are not limited to returning a single value. In some cases, it’s important for functions to return multiple values (or even functions). In Swift, you can use a tuple type in a function to return multiple values. Want to learn more? Check out these SwiftUI tips and tricks.
View ArticleArticle / Updated 08-10-2022
Swift is a type-safe language, which means that the programming language makes it clear to you the types of values your code is working with. The following article discusses how to declare constants and variables and how to work with strings and comments when programming with Swift. Swift constants In Swift, you create a constant using the let keyword: let radius = 3.45 // Double let numOfColumns = 5 // Int let myName = "Wei-Meng Lee" // String Notice that there is no need to specify the data type — the data types are inferred automatically. If you want to declare the type of constant, you can do so using the colon operator (:) followed by the data type, as shown here: let diameter:Double = 8 After a constant is created, you can no longer change its value. Always use a let when you need to store values that do not change. Swift variables To declare a variable, you use the var keyword: var myAge = 25 var circumference = 2 * 3.14 * radius After a variable is created, you can change its value. In Swift, values are never implicitly converted to another type. For example, suppose you’re trying to concatenate a string and the value of a variable. In the following example, you need to explicitly use the String() function to convert the value of myAge to a string value before concatenating it with another string: var strMyAge = "My age is " + String(myAge) To get the text representation of a value (constant or variable), you can also use the description property, like this: myAge.description. Swift strings One of the common tasks in programming is inserting values of variables into a string. In Swift, you use string interpolation and it has the following format: "Your string literal \(variable_name)" The following statement shows an example: let firstName = "Wei-Meng" let lastName = "Lee" var strName = "My name is \(firstName) \(lastName)" You can also use this method to include a Double value in your string (or even perform mathematical operations or function calls): var strResult = "The circumference is \(circumference)" Swift comments In Swift, as in most programming languages, you insert comments into your code using two forward slashes (//): // this is another comment If you have several lines of comments, it’s better to use the /* and */ combination to denote a block of statements as comments: /* this is a comment this is another comment */ Want to learn more? Check out our SwiftUI Cheat Sheet.
View ArticleArticle / Updated 08-10-2022
One important feature in Swift is closure. Closures are self-contained blocks of code that can be passed to functions to be executed as independent code units. Think of a closure as a function without a name. In fact, functions are actually special cases of closures. Swift offers various ways to optimize closures so that they’re brief and succinct. The various optimizations include the following: Inferring parameter types and return types Implicit returns from single-statement closures Shorthand argument names Trailing closure syntax Operator closure Understanding Swift closures The best way to understand Swift closures is to use an example. Suppose you have the following array of integers: let numbers = [5,2,8,7,9,4,3,1] Assume you want to sort this array in ascending order. You could write your own function to perform the sorting, or you could use the sorted() function available in Swift. The sorted() function takes two arguments: An array to be sorted A closure that takes two arguments of the same type as the array and returns a true if the first value appears before the second value Using Swift functions as closures In Swift, functions are special types of closures. As mentioned, the sorted() function needs a closure that takes two arguments of the same type as the array, returning a true if the first value appears before the second value. The following Swift function fulfils that requirement: func ascending(num1:Int, num2:Int) -> Bool { return num1 The ascending() function takes two arguments of type Int and returns a Bool value. If num1 is less than num2, it returns true. You can now pass this function to the sorted() function, as shown here: var sortedNumbers = numbers.sorted(by: ascending) The sorted() function now returns the array that is sorted in ascending order. The sorted() function does not modify the original array. It returns the sorted array as a new array. Assigning Swift closures to variables As mentioned earlier, functions are special types of closures. In fact, a closure is a function without a name. However, you can assign a closure to a variable — for example, the ascending() function discussed earlier can be written as a closure assigned to a variable: var compareClosure : (Int, Int)->Bool = { (num1:Int, num2:Int) -> Bool in return num1 < num2 } To use the compareClosure closure with the sorted() function, pass in the compareClosure variable: sortedNumbers = numbers.sorted(by: compareClosure) Writing Swift closures inline You can pass a function into the sorted() function as a closure function, but a better way is to write the closure inline, which obviates the need to define a function explicitly or assign it to a variable. Rewriting the earlier example would yield the following: sortedNumbers = numbers.sorted(by: { (num1:Int, num2:Int) -> Bool in return num1 < num2 } ) As you can see, the ascending() function name is now gone; all you’ve supplied is the parameter list and the content of the function. If you want to sort the array in descending order, you can simply change the comparison operator: sortedNumbers = numbers.sorted(by: { (num1:Int, num2:Int) -> Bool in return num1 > num2 } ) Understanding type inference Because the type of the first argument of the closure function must be the same as the type of array you’re sorting, it’s actually redundant to specify the type in the closure, because the compiler can infer that from the type of array you’re using: var fruits = ["orange", "apple", "durian", "rambutan", "pineapple"] print(fruits.sorted(by: { (fruit1, fruit2) in return fruit1 If your closure has only a single statement, you can even omit the return keyword: print(fruits.sorted(by: { (fruit1, fruit2) in fruit1 Using shorthand argument names Above, names were given to arguments within a closure. In fact, this is also optional, because Swift automatically provides shorthand names to the parameters, which you can refer to as $0, $1, and so on. The previous code snippet could be rewritten as follows without using named parameters: print(fruits.sorted(by: { $0<$1 }) ) To make the closure really terse, you can write everything on one line: print(fruits.sorted(by:{ $0<$1 })) Working with Swift’s operator function You saw that the closure for the sorted() function was reduced to the following: print(fruits.sorted(by:{ $0<$1 })) One of the implementations of the lesser than (<) operator is actually a function that works with two operands of type String. Because of this, you can actually simply specify the < operator in place of the closure, and the compiler will automatically infer that you want to use the particular implementation of the < operator. The preceding statement can be reduced to the following: print(fruits.sorted(by:<)) If you want to sort the array in descending order, simply use the greater than (>) operator: print(fruits.sorted(by:>)) Using trailing closures in Swift Consider the closure that you saw earlier: print(fruits.sorted(by: { (fruit1, fruit2) in return fruit1 Notice that the closure is passed in as a second argument of the sorted() function. For long closures, this syntax may be a little messy. If the closure is the final argument of a function, you can rewrite this closure as a trailing closure. A trailing closure is written outside of the parentheses of the function call. The preceding code snippet, when rewritten using the trailing closure, looks like this: print(fruits.sorted() { (fruit1, fruit2) in return fruit1 Using the shorthand argument name, the closure can be shortened to the following: print(fruits.sorted(){$0<$1}) Want to learn more? Check out our SwiftUI Cheat Sheet.
View ArticleArticle / Updated 08-10-2022
To animate a view in SwiftUI, apply the animation() modifier on it. SwiftUI animates any changes made to animatable properties of a view. For example, the various properties of a view in SwiftUI — such as its color, opacity, rotation, size, and other properties — are all animatable. As usual, the best way to understand this concept is to use an example. First, create a rounded button that shows the Confirm caption: struct ContentView: View { var body: some View { Button(action: { }) { Text("Confirm") .bold() } .padding(40) .background(Color.green) .foregroundColor(.white) .clipShape(Circle()) } } Apply some scaling (zooming) to the button using the scaleEffect() modifier: struct ContentView: View { @State private var scaleFactor: CGFloat = 1 var body: some View { Button(action: { }) { Text("Confirm") .bold() } .onAppear(perform: { self.scaleFactor = 2.5 }) .padding(40) .background(Color.green) .foregroundColor(.white) .clipShape(Circle()) .scaleEffect(scaleFactor) } } What you want to do here is zoom the button to two and a half times its original size. The scaling will be performed as soon as the Button view is shown in SwiftUI. The following image shows the button zoomed in to two and a half times its original size when it first appears. What you really want is to slow down the scaling, so that users can see the zooming-in process. For this, you can use the animation() modifier on the Button view: struct ContentView: View { @State private var scaleFactor: CGFloat = 1 var body: some View { Button(action: { }) { Text("Confirm") .bold() } .onAppear(perform: { self.scaleFactor = 2.5 }) .padding(40) .background(Color.green) .foregroundColor(.white) .clipShape(Circle()) .scaleEffect(scaleFactor) .animation(.default) } } The .default property actually belongs to the Animation struct, so you can rewrite the above statement as follows: .animation(Animation.default) When you now load the Button view again, the button zooms in two and a half times. Specifying the type of animation in SwiftUI By default, the button will zoom in at a linear speed. You can also use the easeInOur() modifier if you want the animation to start slow, pick up speed, and then slow down again: .animation( .easeInOut(duration: 2) ) The duration parameter indicates how much time is given for the animation to complete in SwiftUI. In this example, the zoom animation must complete in two seconds. If you want to start fast and then slow down, use the easeOut() modifier: .animation( .easeOut(duration: 2) ) Both the easeInOut() and easeOut() modifiers are type methods of the Animation struct. Repeating the animation in SwiftUI Many times, you want the animation to repeat a number of times. For this you can apply the repeatCount() modifier: .animation( Animation.easeInOut(duration: 2) .repeatCount(2, autoreverses: true) ) The easeInOut() is a type method of the Animation struct, and it returns an Animation struct. So, in this case, you call the repeatCount() modifier of the Animation struct to repeat the animation a number of times (twice, in this case). The autoreverses parameter allows you to reverse the animation, so for this particular case the size of the button changes from small to big, and then reverses and changes from big to small. The image below shows the animation that is repeated twice. Notice that at the end of the second animation, the button reverts back to the larger size as specified in the scaleFactor state variable: .scaleEffect(scaleFactor) // changed to 2.5 in onAppear() If you want the animation to repeat forever, use the repeatForever() modifier: .animation( Animation.easeInOut(duration: 2) .repeatForever(autoreverses: true) ) Stopping the animation in SwiftUI Although you can animate nonstop in SwiftUI, there are times where you need to stop the animation. Here’s another example: struct ContentView: View { @State private var opacity:Double = 1.0 var body: some View { Button(action: { }) { Text("Click Me") .fontWeight(.bold) .font(.title) .foregroundColor(.blue) .padding() .background(Color.yellow) .overlay( Rectangle() .stroke(Color.blue, lineWidth: 5) ) .opacity(opacity) .onAppear() { let baseAnimation = Animation.linear(duration: 1) withAnimation ( baseAnimation.repeatForever( autoreverses: true)) { self.opacity = 0.2 } } } } } The preceding code snippet shows a Button view with its opacity initially set to 1.0. When it appears, you perform a linear animation (animating with constant speed) to change the opacity of the button down to 0.2, all within a duration of 1 second. In the next 1 second, it then changes to fully opaque again. Unlike the earlier example, this example does not use the animation() modifier for animation. Instead, you use the withAnimation block. The withAnimation block lets you explicitly tell SwiftUI what to animate. The image below shows the button fully opaque when it’s loaded and then gradually changes its opacity to 0.2. The animation is perpetual, so to stop it, you need to do some work in SwiftUI. For this, you can use a Boolean state variable (let’s call it animate) and use it to determine if the animation should continue: withAnimation (self.animate ? baseAnimation.repeatForever( autoreverses: true) : Animation.default) { self.opacity = 0.2 } In the preceding Swift code snippet, if the animate state variable is true, you’ll perform the animation perpetually, or you can set the animation to default (which will only perform the animation once). The following code snippet stops the animation when the button is tapped and sets the opacity of the button back to 1: struct ContentView: View { @State private var opacity:Double = 1.0 @State private var animate = true var body: some View { Button(action: { self.animate = false self.opacity = 1.0 }) { Text("Click Me") .fontWeight(.bold) .font(.title) .foregroundColor(.blue) .padding() .background(Color.yellow) .overlay( Rectangle() .stroke(Color.blue, lineWidth: 5) ) .opacity(opacity) .onAppear() { let baseAnimation = Animation.linear(duration: 1) withAnimation (self.animate ? baseAnimation.repeatForever( autoreverses: true) : Animation.default) { self.opacity = 0.2 } } } } } Remember to follow the Apple Human Interface Guidelines (HIG) when it comes to animating your UI. This also applies to custom animations. Want to learn more? Check out these SwiftUI resources.
View ArticleArticle / Updated 08-04-2022
The programming adventure has its pitfalls and most C programmers can’t claim to be free of some mistakes. Many of them are common; the same mistakes, over and over. Even after decades of coding, C programmers often still find themselves doing stupid, silly things. Most often they’re done in haste — usually, simple things. But isn’t that the way of everything? Conditional Foul-Ups When you employ an if statement or initiate a while or for loop, the code makes a comparison. Properly expressing this comparison is an art form, especially when you try to do multiple things at once. My advice is to first split up the code before you load everything into the parentheses. For example: while((c=fgetc(dumpme)) != EOF) The code on the preceding line works, but before you get there, try this: c = 1; /* initialize c */ while(c != EOF) c=fgetc(dumpme); This improvement is more readable and less error prone. The situation grows more hair when you use logical operators to combine conditions. It’s highly recommended that you limit the expression to two choices only: if( a==b || a==c) The statements belonging to if are executed when the value of variable a is equal to either the value of variable b or variable c. Simple. But what about this: if( a==b || a==c && a==d) Oops. Now the order of precedence takes over, and for the if statement to be true, a must be equal to b, or a must be equal to both c and d. The situation can also be improved by using parentheses: if( a==b || (a==c && a==d)) When you’re unsure about the order of precedence, use parentheses. == v. = A single equal sign is the assignment operator: a=65; A double equal sign is used for comparison: a==65 To get your brain to appreciate the difference, in your head you can say “is equal to” when you type two equal signs. Despite this reminder, it’s still easy to goof up, especially in a conditional statement. When you assign a value in a conditional statement, you generally create a TRUE condition unless the result of the assignment is zero: if(here=there) This if statement evaluates to the value of variable there. If it’s 0, the if condition evaluates as FALSE; otherwise, it’s true. Regardless, it’s most likely not what you intended. Most compilers, such as clang, catch this mistake. Dangerous loop semicolons in your C code You can get into a rut when you’re typing code, using the semicolon as a prefix before typing the Enter key to end a line. This practice has unintended consequences! It’s especially toxic when you code loops: for(x=0;x<10;x++); This loop works, but its statements aren’t repeated. When it’s done, the value of variable x is 10. That’s it. The same problem exists for a while loop: while(c<255); This loop may spin endlessly, depending on the value of variable c. If the value is greater than or equal to 255, the loop won’t execute. Otherwise, it executes forever. These semicolons are unintentional and unwanted. They’re also perfectly legitimate; the compiler doesn’t flag them as errors, though you may see a warning — which is quite helpful. For example, the suggested resolution is to place the semicolon on the next line: while(putchar(*(ps++))) ; This sole semicolon on a line by itself shouts to the compiler, as well as to any programmer reading the code, that the while loop is intentionally empty. Commas in a C for loop The three items in a for loop’s parentheses are separated by semicolons. Both those semicolons are required, and they are not commas. The compiler doesn’t like this statement: for(a=0,a<10,a++) Because commas are allowed in a for statement, the compiler merely thinks that you’ve omitted the last two required items. In fact, the following is a legitimate for statement: The preceding statement assigns the value 0 to variable a, generates a TRUE comparison (which is ignored), and increments the value of a to 1. Then, because the second and third items are empty, the loop repeats endlessly. (Well, unless a break statement belongs to the loop.) Missing break in a switch structure It’s perfectly legitimate to write a switch structure where the execution falls through from one case statement to the other: In this example, the first five case conditions capture the same set of statements. When you forget the break, however, execution falls through with more tests and, eventually, the default. Unless this control is what you want, remember to add break statements as necessary. Suppose that you have a switch structure that’s several dozen lines high. One case condition has multiple rows of statements, so many that it scrolls up and off the screen. In such a setup, it’s easy to forget the break as you concentrate instead on crafting the proper statements. I know — I’ve done it. Another situation happens when you code a loop inside a switch structure and you use break to get out of that loop. This inner break escapes from the for loop, only: A second break is required in order to get out of the switch structure. Many editors, such as the one used in Code::Blocks, let you collapse and expand parts of your code. To make this feature work in a switch structure, you must enclose the case statements in curly brackets. Missing parentheses and curly brackets in your C code Forgetting a parenthesis or two is one of the most common C coding mistakes. The compiler catches it, but usually the error isn’t flagged until the end of the function. For example, a missing parenthesis in the main() function causes the error to be flagged at the final line of the function. This warning is a good clue to a missing parenthesis or curly bracket, but it doesn’t help you locate it. Today’s editors are good at matching up parentheses and brackets. For example, the Code::Blocks editor inserts both characters when you type the first one. This feature helps keep things organized. Other editors, such as vim, highlight both sets of brackets when the cursor hovers over one. Use these hints as you type to ensure that things match up. Another editor clue is that the formatting, text coloring, and indents screw up when you forget a parenthesis or bracket. The problem with recognizing this reminder is that the human brain automatically assumes that the editor has screwed up. So you need to train yourself to recognize improper indentation by the editor as a sign of a missing parenthesis or curly bracket. Don’t ignore a warning from your C program When the compiler generates a warning, the program (or object code) is still created. This condition can be dangerous, especially when dealing with pointer errors. The problem is that warnings can be ignored; the code compiles anyway. For example, you may be using printf() to display a value that you know is an int, but somehow the compiler insists that it’s some other value. If so, you can typecast the variable as an int. For example: printf("%-14s %5ld %s", file->d_name, (long)filestat.st_size, ctime(&filestat.st_mtime)); In this example, the filestate.st_size variable is of the off_t data type. The printf() function lacks a conversion character for off_t, so it has typecast it to a long int. Similar typecasting can be done with other variable types for which printf() lacks a conversion character. But before you go nuts with this trick, check the man page for printf() to ensure that the specific data type lacks a conversion character. A common warning happens when you try to display a long int value by using the %d When that happens, just edit %d to %ld. An “lvalue required” warning indicates that you’ve written a malformed equation. The lvalue is the left value, or the item on the left side of the equation. It must be present and be of the proper type so that the equation is properly handled. The degree to which the compiler flags your code with warnings can be adjusted. Various flags are used to adjust the compiler’s warning level. These flags are set in the Code::Blocks IDE by choosing the Project→Build Options command. The Compiler Flags tab in the Project Build Options dialog box lets you set and reset the various warnings. The “turn on all warnings” option for a command-line C compiler is the -Wall It looks like this: clang -Wall source.c - Wall stands for “warnings, all.” Endless loops in C There’s got to be a way outta here, which is true for just about every loop. The exit condition must exist. In fact, it’s highly recommended that when you set out to code a loop, the first thing you code is the exit condition. As long as it works, you can move forward and write the rest of the joyous things that the loop does. Unintentional endless loops do happen. C programmers run code many times, only to watch a blank screen for a few moments. Oops. Console applications, such as the kind created throughout this book, are halted by pressing the Ctrl+C key combination in a terminal window. This trick may not always work, so you can try closing the window. You can also kill the task, which is a process that’s handled differently by every operating system. For example, in a Unix operating system, you can open another terminal window and use the kill command to rub out a program run amok in the first terminal window. scanf() blunders in C The scanf() function is a handy way to read specific information from standard input. It’s not, however, ideal for all forms of input. For example, scanf() doesn’t understand when a user types something other than the format that’s requested. Specifically, you cannot read in a full string of text. This issue is because scanf() discards any part of the string after the first white space character. Though the fgets() function is a great alternative for capturing text, keep in mind that it can capture the newline that ends a line of text. This character, \n, becomes part of the input string. The other thing to keep in mind when using scanf() is that its second argument is an address, a pointer. For standard variable types — such as int, float, and double — you must prefix the variable name with the &, the address operator: scanf("%d",&some_int); The & prefix isn’t necessary for reading in an array: scanf("%s",first_name); Individual array elements, however, aren’t memory locations, and they still require the & prefix: scanf("%c",&first_name[0]); Pointer variables do not require the & prefix, which could result in unintended consequences. Streaming input restrictions in C The basic input and output functions in the C language aren’t interactive. They work on streams, which are continuous flows of input or output, interrupted only by an end-of-file marker or, occasionally, the newline character. When you plan to read only one character from input, be aware that the Enter key, pressed to process input, is still waiting to be read from the stream. A second input function, such as another getchar(), immediately fetches the Enter key press (the \n character). It does not wait, as an interactive input function would. If you desire interactive programs, get a library with interactive functions, such as the NCurses library. The end-of-file marker is represented by the EOF constant, defined in the h header file. The newline character is represented by the \n escape sequence. The newline character’s ASCII value may differ from machine to machine, so always specify the escape sequence \n for the newline. Want to learn more? Check out our C Programming Cheat Sheet.
View ArticleArticle / Updated 08-04-2022
It’s difficult to narrow down the list of reminders and suggestions, especially for a topic as rich and diverse as programming. For example, an expert could suggest ways to fit in with other programmers, which movies to quote, which games to play, and even which foods to eat. A programming subculture exists — even today, though the emphasis on professional workplace attire has thankfully abated. Beyond social suggestions, there are a few things to remind you of — plus, some general-purpose C programming language recommendations. Believe it or not, every programmer has been through the same things you’ve experienced. It’s good to hear advice from a grizzled programming veteran. Maintain good posture when you’re programming Someone in your early life probably drilled into you the importance of having proper posture. Ignore them at your own peril, especially when you’re young and haven’t yet gotten out of bed to say, “Ouch.” For many programmers, coding becomes an obsession. For most C programmers, it’s quite easy to sit and write code for many hours straight. Such a stationary position is hard on the body. So, every few minutes, take a break. If you can’t manage that, schedule a break. Seriously: The next time you compile, stand up! Look outside! Walk around a bit! While you’re working, try as hard as you can to keep your shoulders back and your wrists elevated. Don’t crook your neck when you look at the monitor. Don’t hunch over the keyboard. Look out a window to change your focus. Remember that it’s pleasant to acknowledge others. True, it’s easy to grunt or snarl at someone when you’re in the midst of a project. Keep in mind that other humans may not appreciate the depth of thought and elation you feel when you code. If you can’t be pleasant now, apologize later. Use creative names in your C programs The best code reads like a human language. It’s tough to make the entire source code read that way, but for small snippets, having appropriate variable and function names is a boon to writing clear code. For example, the following expression is a favorite: while(!done) You can read this statement as “while not done.” It makes sense. Until the value of the donevariable is TRUE, the loop spins. But somewhere inside the loop, when the exit condition is met, the value of done is set equal to TRUE and the loop stops. It’s lucid. It also helps to offer descriptive names to your C functions. A name such as setringervolume() is great, but the name set_ringer_volume() is better. It also helps to consider the function in context. For example: ch=read_next_character(); In the preceding line, the function read_next_character() needs no explanation — unless it doesn’t actually return the next character. Write a function in C Anytime you use code more than once, consider throwing it off into a function, even if the code is only one line long or appears in several spots and doesn’t really seem function-worthy. Suppose that you use the fgets() function to read a string, but then you follow fgets() with another function that removes the final newline character from the input buffer. Why not make both items their own function, something like get_input()? Work on your C code a little bit at a time A majority of the time you spend coding is to fix problems, to correct flaws in logic, or to fine-tune. When making such adjustments, avoid the temptation to make three or four changes at one time. Address issues one at a time. The reason for the admonition is that it’s tempting to hop around your code and work on several things at a time. For example: You need to fix the spacing in a printf() statement’s output, adjust a loop, and set a new maximum value. Do those things one at a time! When you attempt to do several things at a time, you can screw up. But which thing did you goof up? You have to go back and check everything, including the related statements and functions, to ensure they work. During situations like these, you will seriously wish for a time machine. Instead, just work on your code a little bit at a time. Break apart larger C projects into several modules No one likes to scroll through 500 lines of code. Unless you’re totally immersed in your project and can keep everything stored in your noggin, break out functions into modules. Many C programmers prefer to group related functions into similar files. C programmers typically have an output file, an input file, an initialization file, and so on. Each file, or module, is compiled and linked separately to form the code. The benefits are that the files are smaller and if they compile and work, you no longer need to mess with them. Know what a pointer is in C A pointer is a variable that stores a memory location. It’s not magic, and it shouldn’t be confusing, as long as you keep the basic mantra in your head: A pointer is a variable that stores a memory location. A memory location stored in a pointer references another variable or a buffer (like an array). Therefore, the pointer must be initialized before it’s used: A pointer must be initialized before it’s used. When the pointer variable in C is prefixed by the *(asterisk) operator, it references the contents of the variable at the memory location. This duality is weird, of course, but it’s highly useful. Declare a pointer variable by using the * Use the & operator to grab the address of any variable in C. Arrays are automatically referenced by their memory locations, so you can use an array name without the & prefix to grab its address. “Address” and “memory location” are the same thing. A great way to explore pointers is to use the Code::Blocks debugger; specifically, the Watches window. Add white space before condensing your C code C programmers love to bunch up statements, cramming as many of them as they can into a single line, such as while(putchar(*(sample++))) Admit it: Such a construction looks cool. It makes it seem like you really know how to code C. But it can also be a source of woe. My advice: Split out the code before you condense it. Make liberal use of white space, especially when you first write the code. For example, the line if( c != '\0' ) is easier to read than the line if(c!='\0') After you write your code with white space — or use several statements to express something — you can condense, move out the spaces, or do whatever else you like. In C language source code, white space is for the benefit of human eyes. I admire programmers who prefer to use white space over cramming their code onto one line, despite how interesting it looks. Know when if-else becomes switch-case Many C programmers are big fans of the if-else decision tree, but they generally avoid stacking up multiple if statements. It usually means that the programming logic is flawed. For example: if(something) ; else if(something_else) ; else(finally) ; This structure is okay, and it’s often necessary to deal with a 3-part decision. But the following structure, which has been built by many budding C programmers, probably isn’t the best way to code a decision tree: if(something) ; else if(something_else_1) ; else if(something_else_2) ; else if(something_else_3) ; else if(something_else_4) ; else(finally) ; Generally speaking, anytime you have that many else-if statements, you probably need to employ the switch-case structure instead. In fact this example is probably what inspired the switch-case structure in the first place. Remember assignment operators in the C language Though it’s nice to write readable code, one handy tool in the C language is an assignment operator. Even if you don’t use one, you need to be able to recognize it. The following equation is quite common in programming: a = a + n; In C, you can abbreviate this statement by using an assignment operator: a += n; The operator goes before the equal sign. If it went afterward, it might change into a unary operator, which looks weird: a =+ n; So the value of variable a equals positive n? The compiler may buy that argument, but it’s not what you intended. Also, don’t forget the increment and decrement operators, ++ and --, which are quite popular in loops. When you get stuck, read your code out loud To help you track down that bug, start reading your code aloud. Pretend that a programmer friend is sitting right next to you. Explain what your code is doing and how it works. As you talk through your code, you’ll find the problem. If you don’t, have your imaginary friend ask you questions during your explanation. Don’t worry about going mental. You’re a C programmer. You’re already mental. As a bonus, talking through your code also helps you identify which portions need to have comments and what the comments should be. For example: a++; /* increment a */ In the preceding line, you see a terrible example of a comment. Duh. Of course, a is incremented. Here’s a better version of that comment: a++; /* skip the next item to align output */ Don’t just comment on what the code is doing — comment on why. Again, pretend that you’re explaining your code to another programmer — or to future-you. Future-you will thank present-you for the effort. Want to learn more? Check out our C Programming For Dummies Cheat Sheet.
View ArticleArticle / Updated 08-02-2022
Two big categories of strategies have been employed over the years to support web design for mobile devices: graceful degradation and progressive enhancement. Much of the web is currently nearly unusable on mobile devices because it was designed for desktop browsers and doesn't adapt well to small screens. Mobile web users are often forced to zoom, scroll, pinch, squint, and make their fingers as small as possible to use the majority of websites designed more than a couple years ago. Graceful degradation web design strategy for mobile devices The idea behind graceful degradation is to design your website primarily for desktop users, but to also design it in such a way that features of the desktop site that won't work or fit on mobile devices will still be usable — if not pretty or as functional — on mobile devices. Graceful degradation was a good design philosophy in the days before smartphones with full-featured browsers existed. However, graceful degradation does have major problems. Most importantly, graceful degradation forces the user to download your whole website, only to be shown a degraded version of it. On mobile devices, which often have limited bandwidth, this is not a good thing. Progressive enhancement web design strategy for mobile devices As a result of graceful degradation's limitations, a new strategy called progressive enhancement has become popular. Progressive enhancement starts with the very most basic website and adds on features depending on what the user's browser supports. Progressive enhancement enables websites to be usable even when using a very basic mobile phone. The mobile browser doesn't need to download a lot of CSS and JavaScript code (for example) that it doesn't know what to do with. One way to visualize progressive enhancement is as a system that adds layers onto a website depending on the size of the browser or the features the browser supports. Here's a simple example of how two style sheet links can be used to enhance a mobile webpage for larger browsers: The first link includes style.css for any screen or handheld device. In this case, style.css contains styles that are optimized for a mobile device. The second link is for a style sheet called enhanced.css. If you look at the media attribute for this link, you'll notice that it has a min-width condition. The enhanced.css file will only be included if the device is larger than 800px. Inside enhanced.css, the web designer can override properties from the style.css style sheet to make the browser scale up for larger browser widths. Mobile first design solves the browser size issue Mobile first is a design philosophy that employs the ideas of progressive enhancement to build mobile websites first and then enhance them for desktop. The great thing about mobile first design is that when you build the mobile site first, as opposed to the other way around, you get a functional desktop site for free! Think about all the websites you've seen that don't fit in mobile browsers. Now, imagine visiting a mobile website with a desktop computer. A website that is optimized for a small screen will always work on a desktop browser — even if it does end up not filling the entire browser window.
View ArticleArticle / Updated 08-02-2022
HTML5 brings some pretty amazing new functionality to JavaScript web pages, and the HTML 5 APIs are rapidly giving web browsers access to new universes of data and making installable computer applications a thing of the past. However, not every browser is on board with the future yet. Or, not every browser can agree on what that future should be. As a result, it’s quite possible, and quite common to want to use a particular HTML tag or API and find that it just doesn’t work in some browsers. Fortunately, some ingenious folks have come up with a strategy, called polyfills, for implementing features in browsers that don’t yet support them. Modernizr is a JavaScript library that detects whether a browser supports features of HTML5 and CSS3. A typical way to use a polyfill is to first detect whether the user’s browser supports the feature in question, using Modernizr, and then use the polyfill if not. To install Modernizr, select the particular tests that you'll be using in your web application, and build a custom version of the library that you can then import into your website using the script element. Modernizr uses a simple syntax to select between different paths based on whether a user’s browser supports a feature. For example, here’s a Modernizr test that checks for geolocation support: Modernizr.load({ test: Modernizr.geolocation, yep : 'geo.js', nope: 'geo-polyfill.js' }); A common case in which you would want to use a polyfill is with video. The HTML5 video element allows browsers to play videos without using any plugins. However, different browsers require different video formats, and some older browsers don’t support the video element at all. In order to smooth over these differences, you can include and use a JavaScript polyfill called MediaElement.js. To use it, you can simply download and include the appropriate JavaScript and CSS files and include the following script elements in the head of your document: Then, using just a single video file in any browser can be as simple as just using the video element and specifying a single .mp4 source file. If the browser doesn’t support the video element or this format, a Flash video player will be used as a backup. Polyfills exist for nearly every new HTML5 feature. A complete list of polyfills is maintained by Modernizr.
View Article