Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
iOS

How to run your app on the iPhone with the newest OS version via an older version of Xcode?

In this short post, I’ll explain how to run your app via an older version of Xcode (9.2 in my particular case) on your iPhone that has the newest OS (11.4.1 in my case at the time of this writing).

Say you update your iPhone OS to the newest version, and you open the project in an older version of Xcode and try to run it. You will most probably get an error similar to this (version numbers may vary):

Could not locate device support files on iPhone X (11.1) with Xcode (9.2 9C32c)

The problem has been addressed in these two StackOverflow posts:

  • Xcode not supported for iOS 11.3 by Xcode 9.2 needed 9.3
  • How to fix Xcode error: Could not locate device support files on iPhone X (11.1) with Xcode Beta (9.2 9C32c)

The solution is basically to go on this Github project and download the device support files and place them in the DeviceSupport folder of your Xcode app.

You can get to the DeviceSupport folder by going into your Applications, find the Xcode app, right-click on it and select Show Package Contents. Then navigate to Contents > Developer > Platforms > iPhoneOS.platform > DeviceSupport and paste the contents of the downloaded file there.

All you have to do now is to restart Xcode and run the app again.

⚠️ Now here’s the potentially tricky party; you may realize that even though you’ve downloaded the correct support files from Github (and restarted Xcode) the Xcode is still not happy with it. Say for example you’ve downloaded 11.4 (15F79) but after restarting and running again you get an error mentioning something like 11.4.1 (15G77). The solution there is to just rename the folder to that, restart Xcode and voila, it works!

Hope this helps someone ?

Programming

Code Complete 2 – Steve McConnell – General Control Issues

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes
  • Chapter 7: High-Quality Routines
  • Chapter 8: Defensive programming
  • Chapter 9: Pseudocode Programming Process
  • Chapter 10: General Issues in Using Variables
  • Chapter 11: General Issues in Using Variables
  • Chapter 12: Fundemental Data Types
  • Chapter 13: Unusual Data Types
  • Chapter 15: Using Conditionals
  • Chapter 16: Controlling Loops
  • Chapter 17: Unusual Control Structures
  • Chapter 18: Table-Driven Methods

Boolean Expressions

Except for the simplest control structure, the one that calls for the execution of statements in sequence, all control structures depend on the evaluation of boolean expressions.

Using true and false for Boolean Tests

Use the identifiers true and false in boolean expressions rather than using values like 0 and 1.

You can write clearer tests by treating the expressions as boolean expressions. For example, write

while ( !done ) ...
while ( a > b ) ...

rather than

while ( done == false ) ...
while ( (a > b) == true ) ...

Using implicit comparisons reduces the numbers of terms that someone reading your code has to keep in mind, and the resulting expressions read more like conversational English.

Making Complicated Expressions Simple

Break complicated tests into partial tests with new boolean variables rather than creating a monstrous test with half a dozen terms, assign intermediate values to terms that allow you to perform a simpler test.

Move complicated expressions into boolean functions if a test is repeated often or distracts from the main flow of the program. For example:

If ( ( document.AtEndOfStream ) And ( Not inputError ) ) And 
    ( ( MIN_LLINES <= lineCount ) And ( lineCount <= MAX_LINES ) ) And 
    ( Not ErrorProcessing() ) Then
    ...
End If

This is an ugly test to have to read through if you’re not interested in the test itself. By putting it into a function, you can isolate the test and allow the reader to forget about it unless it’s important.

If ( DocumentIsValid( document , lineCount, inputError) ) Then
    ' do something other
    ...
End If

If you use the test only once, you might not think it’s worthwhile to put it into a routine. But putting the test into a well-named function improves readability and makes it easier for you to see what your code is doing, and that’s sufficient reason to do it.

Forming Boolean Expressions Positively

I ain’t not no undummy.

~ Homer Simpson

Not a few people don’t have not any trouble understanding a nonshort string of nonpositives-that is, most people have trouble understanding a lot of negatives.

You can do several things to avoid complicated negative boolean expressions in your program:

  • In if statements, convert negatives to positives and flip-flop the code in the if and else clauses
    • You shouldn’t write if ( !statusOK ). Alternatively, you could choose a different variable name, one that would reverse the truth value of the test. In the example, you could replace statusOK with ErrorDetected, which would be true when statusOK was false.
  • Apply DeMorgean’s Theorems to simplify boolean test with negatives
    • DeMorgan’s Theorem lets you exploit the logical relationship between an expression and version of the expression that means the same thing because it’s doubly negated. For example:

if ( !displayOK || !printerOK ) ...

This is logically equvalent ot the following:

if ( !( displayOK && printerOK ) ) ...

Using Parentheses to Clarify Boolean Expressions

Using parentheses isn’t like sending a telegram: you’re not charged for each character – the extra characters are free.

Knowing How Boolean Expressions Are Evaluated

The pseudocodeThe pseudocode example of when “short-circuit” or “lazy” evaluation is necessary:

while( i < MAX_ELEMENTS and item[ i ] <> 0 ) ...

If the whole expression is evaluated, you’ll get an error on the last pass through the loop. The variable i equals MAX_ELEMENTS, so the expression item[ i ] is an array-index error.

In the pseudocode, you could restructure the test so that the error doesn’t occur:

while ( i < MAX_ELEMENTS )
    if (item[ i ] <> 0 ) then 
        ...

C++ uses short-circuit evaluation: if the first operand of the and is false, the second isn’t evaluated because the whole expression would be false anyway.

Write Numeric Expressions in Number-Line Order

MIN_ELEMENTS <= i and i <= MAX_ELEMENTS

The idea is to order the elements left to right, from smallest to largest. In the first line, MIN_ELEMENTS and MAX_ELEMENTS are the two endpoints, so they go at the ends. The variable i is supposed to be between them, so it goes in the middle.

Compound Statements (Blocks)

A “compound statement” or “block” is a collection of statements that are treated as a single statement for purposes of controlling the flow of a program. Compound statements are created by writing { and } around a group of statements in C++, C#, C, and Java.

⚠️ Use the block to clarify your intentions regardless of whether the code inside the block is 1 line or 20.

Taming Dangerously Deep Nesting

Excessive indentation, or “nesting,” has been pilloried in computing literature for 25 years and is still one of the chief culprits in confusing code.

Many researchers recommend avoiding nesting to more than three or four levels (Myers 1976, Marca 1981, and Ledgard and Tauer 1987a). Deep nesting works against what Chapter 5 describes as Software’s Major Technical Imperative: Managing Complexity. That is reason enough to avoid deep nesting.

It’s not hard to avoid deep nesting. If you have deep nesting, you can redesign the tests performed in the if and else clauses or you can break the code into simpler routines. Here are the tips to reduce the nesting depth:

Simplify the nested if by testing part of the condition

if ( inputStatus == InputStatus_Success ) {
   // lots of code
   ...
   if ( printerRoutine != NULL ) {
    // lots of code
        ...
        if ( SetupPage() ) {
            // lots of code
            ...
            if ( AllocMem( &printData ) ) {
                // lots of code
                ... 
        }
    } 
}

Here’s the code revised to use retesting rather than nesting:

if ( inputStatus == InputStatus_Success ) {
   // lots of code
   ...
   if ( printerRoutine != NULL ) {
      // lots of code
... }
}
if ( ( inputStatus == InputStatus_Success ) &&
   ( printerRoutine != NULL ) && SetupPage() ) {
   // lots of code
   ...
   if ( AllocMem( &printData ) ) {
      // lots of code
      ...
    } 
}

This is a particularly realistic example because it shows that you can’t reduce the nesting level for free; you have to put up with a more complicated test in return for the reduced level of nesting.

Simplify a nested if by using break

If some condition in the middle of the block fails, execution continues at the end of the block.

do {
   // begin break block
   if ( inputStatus != InputStatus_Success ) {
      break; // break out of block
   }
   // lots of code
   ...
   if ( printerRoutine == NULL ) {
      break; // break out of block
   }
   // lots of code
   ...
   if ( !SetupPage() ) {
      break; // break out of block
   }
   // lots of code
   ...
   if ( !AllocMem( &printData ) ) {
      break; // break out of block
   }
   // lots of code
   ...
} while (FALSE); // end break block

This technique is uncommon enough that it should be used only when your entire team is familiar with it.

Convert a nested if to a set of if-then-elses

If you think about a nested if test critically, you might discover that you can reorganize it so that it uses if-then-elses rather than nested ifs. Suppose you have a busy decision tree like this:

if ( 10 < quantity ) {
   if ( 100 < quantity ) {
      if ( 1000 < quantity ) {
        discount = 0.10;
      } 
      else {
        discount = 0.05;
      }
    }
    else {
      discount = 0.025;
    } 
}
else {
   discount = 0.0;
}

You can reorganize the code for better readability and reduced complexity:

if ( 1000 < quantity ) {
   discount = 0.10;
}
else if ( 100 < quantity ) {
   discount = 0.05;
}
else if ( 10 < quantity ) {
   discount = 0.025;
}
else {
   discount = 0;
}

Convert a nested if to a case statement

You can recode some kinds of tests, particularly those with integers, to use a case statement rather than chains of ifs and elses. You can’t use this technique in some languages, but it’s a powerful technique for those in which you can.

Factor deeply nested code into its own routine

If deep nesting occurs inside a loop, you can often improve the situation by putting the inside of the loop into its own routine. This is especially effective if the nesting is a result of both conditionals and iterations. Leave the if-then-else branches in the main loop to show the decision branching, and then move the statements within the branches to their own routines.

The new code has several advantages. First, the structure is simpler and easier to understand. Second, you can read, modify, and debug the shorter while loop on one screen; it doesn’t need to be broken across the screen or printed- page boundaries.

⚠️ Complicated code is a sign that you don’t understand your program well enough to make it simple.

A Programming Foundation: Structured Programming

The core of structured programming is a simple idea that a program should use only one-in, one-out control constructs (also called single-entry, single-exit control constructs).

A structured program progresses in an orderly, disciplined way, rather than jumping around unpredictably. You can read it from top to bottom, and it executes in much the same way.

The Three Components of Structured Programming

  • Sequence
    • A sequence is a set of statements executed in order. Typical sequential statements include assignments and calls to routines.
  • Selection
    • A selection is a control structure that causes statements to be executed selectively. The if-then-else statement is a common example.
  • Iteration
    • An iteration is a control structure that causes a group of statements to be executed multiple times. An iteration is commonly referred to as a “loop”.
  • The core thesis of structured programming is that any control flow whatsoever can be created from these three constructs of sequence, selection, and iteration (Böhm Jacopini 1966).

How important is complexity?

The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility

~ Edsger Dijkstra

Control-flow complexity is important because it has been correlated with low reliability and frequent errors.

Recent posts

  • Discipline is also a talent
  • Play for the fun of it
  • The importance of failing
  • A fresh start
  • Perseverance

Categories

  • Android (3)
  • Books (114)
    • Programming (22)
  • CodeProject (35)
  • Daily Thoughts (77)
  • Go (3)
  • iOS (5)
  • JavaScript (127)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • React (1)
    • Three.js (1)
    • Vue.js (2)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (77)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (40)
  • Servers (8)
    • Heroku (1)
    • Linux (3)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak