问:
Moving empty files from current directory into a sub directory
I am trying to make a bash script that will check to see if the subdirectory "Empty_Files" exists in the current directory and if it dosent it will create the subdirectory. It will then check all regular non hidden files in the current directory and if a file is empty it will ask if you want to move the file. If the user says yes it will move the file into the Empty_Files directory. However when I run the script it just says no empty file found in the current directory but still asks if I want to move the file. Not sure why it is doing this. Any help would be apperitaced.</p>

```<code>   #!/bin/bash

#Script to move empty files from current directory into the sub directory Empty_Files

# usage:  ./move_empty

subdirectory="Empty_Files"

if [ -f $subdirectory ]  # does the Empty_Files file exist?
then
   echo $subdirectory "exists!"
else
   mkdir -p /home/student/Empty_Files
   echo "Empty_Files subdirectory created"
fi

currentfiles=$( ls . )  # check all non hidden files in current directory

for eachfile in $currentfiles
do
   checksize=$(du -sh $eachfile | awk '{print $1}')

   if [ "$checksize" = "0" ] # check if any files are empty
   then
      echo -n "Would you like to move the file Y/N:" # if a file is empty ask the user if the want to move the file
      read useranswer
   fi

   if [ "$useranswer" = "y" ] || [ "$useranswer" = "Y" ]
   then
      mv "$eachfile" /home/student/Empty_Files
      echo "mv command successful"
   elif [ "$useranswer" = "n" ] || [ "$useranswer" = "N" ]
   then
      echo "File will not be moved"
   fi

   if [ ! -z "$currentfiles" ]
   then
      echo "no empty files found in the current directory"
      #exit 55
   fi
done
</code>```

答:
You have several problems.

When the file is not empty, you skip the code that asks the user whether they want to move the file, but you still execute the code that moves the file. It uses the value of $useranswer from the previous file, so it will move all non-empty files after it moves an empty file, until it gets to the next empty file. The code that does the move should be inside the if that tests the length.

The test for whether to print "No empty files found" is just wrong. $currentfiles is the list of all files, not empty files. And your test is backwards: you're testing if the variable is not empty. What you should do is set a variable when you find an empty file. Then after the loop is done you can check that variable.

There's a built-in test for whether a file has non-zero size, you don't need to use du for this.

You shouldn't parse the output of ls, use a wildcard.

If you're going to print a message saying the move was successful, you should actually check that it was.

The question asking if they want to move the file doesn't say which file it is.

```<code>emptyfound=n
for eachfile in *
do
    if [ ! -s "$eachfile" ] # check if any files are empty
    then
        emptyfound=y
        echo -n "Would you like to move the file $eachfile Y/N:" # if a file is empty ask the user if the want to move the file
        read useranswer

        if [ "$useranswer" = "y" ] || [ "$useranswer" = "Y" ]
        then
            if mv "$eachfile" /home/student/Empty_Files
            then echo "mv command successful"
            else echo "mv command failed"
            fi
        else
            echo "File will not be moved"
        fi
    fi
done

if [ "$emptyfound" = n ]
then
    echo "no empty files found in the current directory"
    #exit 55
fi
</code>```

Body:
I am trying to make a bash script that will check to see if the subdirectory "Empty_Files" exists in the current directory and if it dosent it will create the subdirectory. It will then check all regular non hidden files in the current directory and if a file is empty it will ask if you want to move the file. If the user says yes it will move the file into the Empty_Files directory. However when I run the script it just says no empty file found in the current directory but still asks if I want to move the file. Not sure why it is doing this. Any help would be apperitaced.

   #!/bin/bash

#Script to move empty files from current directory into the sub directory Empty_Files

# usage:  ./move_empty

subdirectory="Empty_Files"

if [ -f $subdirectory ]  # does the Empty_Files file exist?
then
   echo $subdirectory "exists!"
else
   mkdir -p /home/student/Empty_Files
   echo "Empty_Files subdirectory created"
fi

currentfiles=$( ls . )  # check all non hidden files in current directory

for eachfile in $currentfiles
do
   checksize=$(du -sh $eachfile | awk '{print $1}')

   if [ "$checksize" = "0" ] # check if any files are empty
   then
      echo -n "Would you like to move the file Y/N:" # if a file is empty ask the user if the want to move the file
      read useranswer
   fi

   if [ "$useranswer" = "y" ] || [ "$useranswer" = "Y" ]
   then
      mv "$eachfile" /home/student/Empty_Files
      echo "mv command successful"
   elif [ "$useranswer" = "n" ] || [ "$useranswer" = "N" ]
   then
      echo "File will not be moved"
   fi

   if [ ! -z "$currentfiles" ]
   then
      echo "no empty files found in the current directory"
      #exit 55
   fi
done

Body:
You have several problems.

When the file is not empty, you skip the code that asks the user whether they want to move the file, but you still execute the code that moves the file. It uses the value of $useranswer from the previous file, so it will move all non-empty files after it moves an empty file, until it gets to the next empty file. The code that does the move should be inside the if that tests the length.

The test for whether to print "No empty files found" is just wrong. $currentfiles is the list of all files, not empty files. And your test is backwards: you're testing if the variable is not empty. What you should do is set a variable when you find an empty file. Then after the loop is done you can check that variable.

There's a built-in test for whether a file has non-zero size, you don't need to use du for this.

You shouldn't parse the output of ls, use a wildcard.

If you're going to print a message saying the move was successful, you should actually check that it was.

The question asking if they want to move the file doesn't say which file it is.

emptyfound=n
for eachfile in *
do
    if [ ! -s "$eachfile" ] # check if any files are empty
    then
        emptyfound=y
        echo -n "Would you like to move the file $eachfile Y/N:" # if a file is empty ask the user if the want to move the file
        read useranswer

        if [ "$useranswer" = "y" ] || [ "$useranswer" = "Y" ]
        then
            if mv "$eachfile" /home/student/Empty_Files
            then echo "mv command successful"
            else echo "mv command failed"
            fi
        else
            echo "File will not be moved"
        fi
    fi
done

if [ "$emptyfound" = n ]
then
    echo "no empty files found in the current directory"
    #exit 55
fi


来源: stackexchange

问:
Mean function using values from double array displaying wrong values
Very new to C, anyways been coding a program where you enter pairs of doubles which are stored in separate arrays. I have created a function to get the mean of the numbers but when I call it inside main the values are different. Any ideas?

MEAN FUNCTION:

```<code>mean(double *arr)
{
    double sum = 0.0;
    double meanValue = 0.0;
    int i;

    for (i = 0; i < arr[i]; i++)
    {
        sum += arr[i];
        meanValue = sum / i;
    }

    printf("\nmean: %.3lf", meanValue);
}
</code>```

MAIN:

```<code>double num1[1001];
mean(num1);
</code>```

And, I am getting the num1 and num2 values using:

```<code>for (k = 0; (scanf_s("%lf,%lf", &num1[k], &num2[k] ) == 2); k++)
</code>```

答:
Your function needs to pieces of information:

the pointer to the data array;

the size of the array (number of elements).

However, the way you are computing the mean is subjected to bad numeric conditioning (floating point overflow). Here I suggest using the Incremental Averaging instead. Please consider this code:

```<code>double mean(double *arr, int num)
{
    double res = arr[0];

    for (int i = 1; i < num; ++i)
        res += (arr[i] - res) / (i+1.0);

    return res;
}

</code>```

Note that I'm assuming you are using a C99 compliant compiler for the integer declaration inside the for loop.

ContentLicense: CC BY-SA 4.0

Body:
Very new to C, anyways been coding a program where you enter pairs of doubles which are stored in separate arrays. I have created a function to get the mean of the numbers but when I call it inside main the values are different. Any ideas?

MEAN FUNCTION:

mean(double *arr)
{
    double sum = 0.0;
    double meanValue = 0.0;
    int i;

    for (i = 0; i < arr[i]; i++)
    {
        sum += arr[i];
        meanValue = sum / i;
    }

    printf("\nmean: %.3lf", meanValue);
}

MAIN:

double num1[1001];
mean(num1);

And, I am getting the num1 and num2 values using:

for (k = 0; (scanf_s("%lf,%lf", &num1[k], &num2[k] ) == 2); k++)

Body:
Your function needs to pieces of information:

the pointer to the data array;

the size of the array (number of elements).

However, the way you are computing the mean is subjected to bad numeric conditioning (floating point overflow). Here I suggest using the Incremental Averaging instead. Please consider this code:

double mean(double *arr, int num)
{
    double res = arr[0];

    for (int i = 1; i < num; ++i)
        res += (arr[i] - res) / (i+1.0);

    return res;
}

Note that I'm assuming you are using a C99 compliant compiler for the integer declaration inside the for loop.


问:
Using the g++ C++ compiler from cygwin
I am trying to execute my first "Hello World!" in C++. I am using Windows XP, and I have installed cygwin, in which the g++ C++ compiler is installed. I have written a small hello-world program, and saved it in hello.cpp. From the command prompt I write:

g++ hello.cpp

But I get:

'g++' is not recognized as an internal or external command, operable program or batch file.

I have installed cygwin in my D:\programs\cygwin. I have made another directory with my hello-world file in D:\cpp. Something with my installation or my paths seems to be not Ok, but I cannot figure what. I have run the exe file of cygwin, and in the installation directory I have got all necessary files, I think: bin folder, lib, Cygwin.bat, etc.

I have read that in case of such error message I should check whether the cygwin1.dll file is copied into the main folder of Windows. Is this the C:\WINDOWS directory? I have looked there, and I don't have such a file there. I have cygwin1.dll in the bin folder of cygwin: D:\programs\cygwin\bin.
Also, how do I check whether the bin folder (D:\programs\cygwin\bin) is considered in the search path of commands?

I think that the hello-world program shouldn't contain any syntax errors, I have just copied it. Also, when I write

g++ -v

I get the same error message: that the command is not recognized.
I would appreciate if someone give me a hint what should I look at. Thank you.

Here is the code of the hello-world program:

```<code>#include <iostream>
using namespace std;

int main() {
  cout <<"Hello World!"<<endl;
  return 0;
}
</code>```

I have installed g++, and now when I type g++ -v, I get: Reading specs from: \d\cygnus\cygwin-b20\H-i586-cygwin32\bin..\lib\gcc-lib\i586-cygwin32\egcs-2.91.57\specs gcc version egcs-2.91.57 19980901 (egcs-1.1 release)

In the bin directory I have both g++.exe, and gcc.exe. I don't understand why I get "gcc" above and not "g++". I don't know how important this is, but I receive an error message when I try to compile the program in the DOS command prompt:

g++ hello.cpp

I get:

```<code>hello.cpp:1: parse error before character 0357
hello.cpp: In function 'int main()':
hello.cpp:'cout' undeclared (first use this function)
hello.cpp: (Each undeclared identifier is reported only once
hello.cpp: for each function it appears in.)
hello.cpp: 'endl' undeclared (first use this function)
</code>```

And here is what I get when I try to compile the program in the cygwin shell:

```<code>hello.cpp:1: parse error before character 0357
hello.cpp: In function 'int main()':
hello.cpp:'cout' undeclared (first use this function)
hello.cpp: (Each undeclared identifier is reported only once
hello.cpp: for each function it appears in.)
hello.cpp: 'endl' undeclared (first use this function)
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
</code>```

答:
bring up dos shell.

cd c:\cygwin\bin

type c++ or cpp

or do a directory command do see the contents. Look for cpp or c++.

If they aren't there, you haven't downloaded it.

ContentLicense: CC BY-SA 2.5

Title: Using the g++ C++ compiler from cygwin

Body:
I am trying to execute my first "Hello World!" in C++. I am using Windows XP, and I have installed cygwin, in which the g++ C++ compiler is installed. I have written a small hello-world program, and saved it in hello.cpp. From the command prompt I write:

g++ hello.cpp

But I get:

'g++' is not recognized as an internal or external command, operable program or batch file.

I have installed cygwin in my D:\programs\cygwin. I have made another directory with my hello-world file in D:\cpp. Something with my installation or my paths seems to be not Ok, but I cannot figure what. I have run the exe file of cygwin, and in the installation directory I have got all necessary files, I think: bin folder, lib, Cygwin.bat, etc.

I have read that in case of such error message I should check whether the cygwin1.dll file is copied into the main folder of Windows. Is this the C:\WINDOWS directory? I have looked there, and I don't have such a file there. I have cygwin1.dll in the bin folder of cygwin: D:\programs\cygwin\bin.
Also, how do I check whether the bin folder (D:\programs\cygwin\bin) is considered in the search path of commands?

I think that the hello-world program shouldn't contain any syntax errors, I have just copied it. Also, when I write

g++ -v

I get the same error message: that the command is not recognized.
I would appreciate if someone give me a hint what should I look at. Thank you.

Here is the code of the hello-world program:

#include <iostream>
using namespace std;

int main() {
  cout <<"Hello World!"<<endl;
  return 0;
}

I have installed g++, and now when I type g++ -v, I get: Reading specs from: \d\cygnus\cygwin-b20\H-i586-cygwin32\bin..\lib\gcc-lib\i586-cygwin32\egcs-2.91.57\specs gcc version egcs-2.91.57 19980901 (egcs-1.1 release)

In the bin directory I have both g++.exe, and gcc.exe. I don't understand why I get "gcc" above and not "g++". I don't know how important this is, but I receive an error message when I try to compile the program in the DOS command prompt:

g++ hello.cpp

I get:

hello.cpp:1: parse error before character 0357
hello.cpp: In function 'int main()':
hello.cpp:'cout' undeclared (first use this function)
hello.cpp: (Each undeclared identifier is reported only once
hello.cpp: for each function it appears in.)
hello.cpp: 'endl' undeclared (first use this function)

And here is what I get when I try to compile the program in the cygwin shell:

hello.cpp:1: parse error before character 0357
hello.cpp: In function 'int main()':
hello.cpp:'cout' undeclared (first use this function)
hello.cpp: (Each undeclared identifier is reported only once
hello.cpp: for each function it appears in.)
hello.cpp: 'endl' undeclared (first use this function)
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files
g++.exe: hello.cpp: No such file or directory
g++.exe: No input files

LastEditorDisplayName: Rich B

OwnerDisplayName: Jack BeNimble


问:
UIAlert in Swift that automatically disappears?
I have the following code:

```<code>    /// Creates Alerts on screen for user.
func notifyUser(title: String, message: String) -> Void
{
    let alert = UIAlertController(title: title,
        message: message,
        preferredStyle: UIAlertControllerStyle.Alert)

    let cancelAction = UIAlertAction(title: "OK",
        style: .Cancel, handler: nil)

    alert.addAction(cancelAction)
    UIApplication.sharedApplication().keyWindow?.rootViewController!.presentViewController(alert, animated: true,
        completion: nil)
}
</code>```

Which shows the following Alert:

I would prefer the Alert to appear for maybe 1-2 seconds and auto dismiss without having to click ok or dismiss. Is this possible?

答:
```<code> func notifyUser(message: String) -> Void {
  let alert = UIAlertController(title: "", message: message, preferredStyle: UIAlertController.Style.alert)
  present(alert, animated: true, completion: nil)
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [unowned self] in
   self.dismiss(animated: true)
  }
 }
</code>```

To use:

```<code>  notifyUser(message: "Image Saved")
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have the following code:

    /// Creates Alerts on screen for user.
func notifyUser(title: String, message: String) -> Void
{
    let alert = UIAlertController(title: title,
        message: message,
        preferredStyle: UIAlertControllerStyle.Alert)

    let cancelAction = UIAlertAction(title: "OK",
        style: .Cancel, handler: nil)

    alert.addAction(cancelAction)
    UIApplication.sharedApplication().keyWindow?.rootViewController!.presentViewController(alert, animated: true,
        completion: nil)
}

Which shows the following Alert:

I would prefer the Alert to appear for maybe 1-2 seconds and auto dismiss without having to click ok or dismiss. Is this possible?

Body:
 func notifyUser(message: String) -> Void {
  let alert = UIAlertController(title: "", message: message, preferredStyle: UIAlertController.Style.alert)
  present(alert, animated: true, completion: nil)
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [unowned self] in
   self.dismiss(animated: true)
  }
 }

To use:

  notifyUser(message: "Image Saved")


问:
how to set same page title for all the my account pages in magento 2?
I want to change all the my account page's title to My Account.

For Example:

If you go to My orders page the title will be My Orders by default, but it should be "My Account".

答:
I do not recommend to change all of your titles in My Account, however if that's you want then here is how:

Find all files in the vendor/magento with name is customer_account.xml, the path must looks like module-*/view/frontend/layout/customer_account.xml.

For example, My Orders has been set in module-sales/view/frontend/layout/customer_account.xml.

```<code><page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer_account_navigation">
            <block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-orders-link">
                <arguments>
                    <argument name="path" xsi:type="string">sales/order/history</argument>
                    <argument name="label" xsi:type="string" translate="true">My Orders</argument>
                    <argument name="sortOrder" xsi:type="number">230</argument>
                </arguments>
            </block>
        </referenceBlock>
    </body>
</page>
</code>```

Change "My Orders" to whatever you want and repeat it over and over.

Cheers,

Body:
I do not recommend to change all of your titles in My Account, however if that's you want then here is how:

Find all files in the vendor/magento with name is customer_account.xml, the path must looks like module-*/view/frontend/layout/customer_account.xml.

For example, My Orders has been set in module-sales/view/frontend/layout/customer_account.xml.

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer_account_navigation">
            <block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-orders-link">
                <arguments>
                    <argument name="path" xsi:type="string">sales/order/history</argument>
                    <argument name="label" xsi:type="string" translate="true">My Orders</argument>
                    <argument name="sortOrder" xsi:type="number">230</argument>
                </arguments>
            </block>
        </referenceBlock>
    </body>
</page>

Change "My Orders" to whatever you want and repeat it over and over.

Cheers,


问:
"Unhandled Exception: NoSuchMethodError" when onTap() is called
I'm new to flutter and have recently started working on my first flutter project.

The idea is that when the user touches the button / image it should play a sound.

I'm using android studio to create the app.
I have imported a package called
Audioplayers to help play the audio.

When I run the code, the app is built and it displays the image, but when I tap on the image, it gives me an error that I'm unable to resolve:

```<code>Unhandled Exception: NoSuchMethodError: The getter 'position' was called on null
</code>```

This is the code:

```<code>MaterialApp(
   home: Scaffold(
     backgroundColor: Colors.black,
     body: Center(
       child: GestureDetector(
         onTap: () {
           AudioPlayer audioPlayer = AudioPlayer();
           audioPlayer.setVolume(1.0);

           playLocal() async {
             int result = await audioPlayer.play(
                 'path/to/mp3',
                 isLocal: true);
           }
         },
         child: Image(
           image: AssetImage('assetsproj/images/PngItem_4931119.png'),
         ),
       ),
     ),
   ),
 ),
</code>```

This is the error:

```<code>E/flutter (11532): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'position' was called on null.
E/flutter (11532): Receiver: null
E/flutter (11532): Tried calling: position
E/flutter (11532): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter (11532): #1      TapGestureRecognizer.handleTapDown (package:flutter/src/gestures/tap.dart:456:28)
E/flutter (11532): #2      BaseTapGestureRecognizer._checkDown (package:flutter/src/gestures/tap.dart:256:5)
E/flutter (11532): #3      BaseTapGestureRecognizer.didExceedDeadline (package:flutter/src/gestures/tap.dart:227:5)
E/flutter (11532): #4      PrimaryPointerGestureRecognizer.didExceedDeadlineWithEvent (package:flutter/src/gestures/recognizer.dart:493:5)
E/flutter (11532): #5      PrimaryPointerGestureRecognizer.addAllowedPointer.<anonymous closure> (package:flutter/src/gestures/recognizer.dart:446:40)
E/flutter (11532): #6      _rootRun (dart:async/zone.dart:1122:38)
E/flutter (11532): #7      _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (11532): #8      _CustomZone.runGuarded (dart:async/zone.dart:925:7)
E/flutter (11532): #9      _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23)
E/flutter (11532): #10     _rootRun (dart:async/zone.dart:1126:13)
E/flutter (11532): #11     _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (11532): #12     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:949:23)
E/flutter (11532): #13     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (11532): #14     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:384:19)
E/flutter (11532): #15     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
E/flutter (11532): #16     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
E/flutter (11532):

</code>```

I'm not sure why I get this error.

答:
So I've managed to solve the error by importing a few new packages and removing the old package.

Imported PositionTapDetector and replaced Gesturedetector with it.

Changed Audioplayer to Audio_Cache

But I think the main problem was the playLocal() method which plays audio from the devices location and not the asset folder.

So the final code is

```<code>child: PositionedTapDetector(
            onTap: (center) {
                  AudioCache player = AudioCache();
                  player.play('audio/movie_1.mp3');
              },
            child: Image(
              image: AssetImage('assets/images/PngItem_4931119.png'),
            ),
</code>```

Body:
I'm new to flutter and have recently started working on my first flutter project.

The idea is that when the user touches the button / image it should play a sound.

I'm using android studio to create the app.
I have imported a package called
Audioplayers to help play the audio.

When I run the code, the app is built and it displays the image, but when I tap on the image, it gives me an error that I'm unable to resolve:

Unhandled Exception: NoSuchMethodError: The getter 'position' was called on null

This is the code:

MaterialApp(
   home: Scaffold(
     backgroundColor: Colors.black,
     body: Center(
       child: GestureDetector(
         onTap: () {
           AudioPlayer audioPlayer = AudioPlayer();
           audioPlayer.setVolume(1.0);

           playLocal() async {
             int result = await audioPlayer.play(
                 'path/to/mp3',
                 isLocal: true);
           }
         },
         child: Image(
           image: AssetImage('assetsproj/images/PngItem_4931119.png'),
         ),
       ),
     ),
   ),
 ),

This is the error:

E/flutter (11532): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'position' was called on null.
E/flutter (11532): Receiver: null
E/flutter (11532): Tried calling: position
E/flutter (11532): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter (11532): #1      TapGestureRecognizer.handleTapDown (package:flutter/src/gestures/tap.dart:456:28)
E/flutter (11532): #2      BaseTapGestureRecognizer._checkDown (package:flutter/src/gestures/tap.dart:256:5)
E/flutter (11532): #3      BaseTapGestureRecognizer.didExceedDeadline (package:flutter/src/gestures/tap.dart:227:5)
E/flutter (11532): #4      PrimaryPointerGestureRecognizer.didExceedDeadlineWithEvent (package:flutter/src/gestures/recognizer.dart:493:5)
E/flutter (11532): #5      PrimaryPointerGestureRecognizer.addAllowedPointer.<anonymous closure> (package:flutter/src/gestures/recognizer.dart:446:40)
E/flutter (11532): #6      _rootRun (dart:async/zone.dart:1122:38)
E/flutter (11532): #7      _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (11532): #8      _CustomZone.runGuarded (dart:async/zone.dart:925:7)
E/flutter (11532): #9      _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23)
E/flutter (11532): #10     _rootRun (dart:async/zone.dart:1126:13)
E/flutter (11532): #11     _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (11532): #12     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:949:23)
E/flutter (11532): #13     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (11532): #14     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:384:19)
E/flutter (11532): #15     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
E/flutter (11532): #16     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
E/flutter (11532):

I'm not sure why I get this error.

Body:
So I've managed to solve the error by importing a few new packages and removing the old package.

Imported PositionTapDetector and replaced Gesturedetector with it.

Changed Audioplayer to Audio_Cache

But I think the main problem was the playLocal() method which plays audio from the devices location and not the asset folder.

So the final code is

child: PositionedTapDetector(
            onTap: (center) {
                  AudioCache player = AudioCache();
                  player.play('audio/movie_1.mp3');
              },
            child: Image(
              image: AssetImage('assets/images/PngItem_4931119.png'),
            ),


问:
Is it possible to connect to Spotify's MediaBrowserService?
I am writing a voice assistant and would like to be able to launch search results in Spotify. To understand how to connect to Spotify and other apps, I am playing with the Google's Media Controller Test app, which is described as doing the following:

Create a simple MediaController that connects to a MediaBrowserService
  in order to test inter-app media controls.

This app works with the Universal Android Music Player sample, or any
  other app that implements the media APIs.

When I run the app, it identifies Spotify as providing a MediaBrowserService, but I get an error when I try connecting to Spotify through the app:

Here's is the connection code:

mBrowser = new MediaBrowserCompat(this, mMediaAppDetails.componentName,
        new MediaBrowserCompat.ConnectionCallback() {
             @Override
             public void onConnected() {
                 setupMediaController();
                 mBrowseMediaItemsAdapter.setRoot(mBrowser.getRoot());
             }

             @Override
             public void onConnectionSuspended() {
                 //TODO(rasekh): shut down browser.
                 mBrowseMediaItemsAdapter.setRoot(null);
             }

             @Override
             public void onConnectionFailed() {
                 showToastAndFinish(getString(
                         R.string.connection_failed_msg, mMediaAppDetails.appName));
             }

         }, null);
mBrowser.connect();
```

Specifically, shortly after calling mBrowser.connect(), the callback's onConnectionFailed() method is called.

Does this imply that Spotify refuses MediaBrowserService requests from non-whitelisted apps (as described here) and that there's no way for an individual app writer to connect to Spotify's MediaBrowserService, or is there some other way to connect? FWIW, Google Play Music also rejects connections through the app.

I have also tried getting Spotify to search and play by launching an intent, but that was unsuccessful.

答:
Does this imply that Spotify refuses MediaBrowserService requests from non-whitelisted apps (as described here) and that there's no way for an individual app writer to connect to Spotify's MediaBrowserService, or is there some other way to connect?

Yes, that's exactly what onConnectionFailed means.

You can verify this by changing UAMP's onGetRoot to return null rather than BrowserRoot(UAMP_EMPTY_ROOT, rootExtras).

Generally, you'd need to reach out to each music player and ask them to whitelist your app (or switch to allowing all apps to control their playback) if you'd like to use the standard Android APIs and MediaBrowserCompat to connect to them.

Body:
I am writing a voice assistant and would like to be able to launch search results in Spotify. To understand how to connect to Spotify and other apps, I am playing with the Google's Media Controller Test app, which is described as doing the following:

Create a simple MediaController that connects to a MediaBrowserService
  in order to test inter-app media controls.

This app works with the Universal Android Music Player sample, or any
  other app that implements the media APIs.

When I run the app, it identifies Spotify as providing a MediaBrowserService, but I get an error when I try connecting to Spotify through the app:

Here's is the connection code:

mBrowser = new MediaBrowserCompat(this, mMediaAppDetails.componentName,
        new MediaBrowserCompat.ConnectionCallback() {
             @Override
             public void onConnected() {
                 setupMediaController();
                 mBrowseMediaItemsAdapter.setRoot(mBrowser.getRoot());
             }

             @Override
             public void onConnectionSuspended() {
                 //TODO(rasekh): shut down browser.
                 mBrowseMediaItemsAdapter.setRoot(null);
             }

             @Override
             public void onConnectionFailed() {
                 showToastAndFinish(getString(
                         R.string.connection_failed_msg, mMediaAppDetails.appName));
             }

         }, null);
mBrowser.connect();

Specifically, shortly after calling mBrowser.connect(), the callback's onConnectionFailed() method is called.

Does this imply that Spotify refuses MediaBrowserService requests from non-whitelisted apps (as described here) and that there's no way for an individual app writer to connect to Spotify's MediaBrowserService, or is there some other way to connect? FWIW, Google Play Music also rejects connections through the app.

I have also tried getting Spotify to search and play by launching an intent, but that was unsuccessful.


问:
In a horizontally scalable architecture, how to deal with database concurrency when multiple instances read/write to the same row simultaneously?
I know SQL Server is very robust in this sense (transactions and locking), but how would that work with NoSQL databases like AWS DocumentDB with Mongo API?</p>

答:
In Amazon DocumentDB, all CRUD statements (findAndModify, update, insert, delete) guarantee atomicity and consistency, even for operations that modify multiple documents. For more information, see Implicit Transactions.

Additionally, reads from an Amazon DocumentDB cluster’s primary instance are strongly consistent under normal operating conditions and have read-after-write consistency. For more information, see Read Preference Options.


问:
"The dll is not allowed to be included or could not be found" while building unity3d SignalR
I'm using unity 2017.2 and ran into this error while building for APK file

```<code>ArgumentException: The Assembly System.Reflection.Emit is referenced by
Microsoft.AspNetCore.SignalR.Core
('Assets/Plugins/Microsoft.AspNetCore.SignalR.Core.dll'). But the dll is not
allowed to be included or could not be found.
UnityEditor.AssemblyHelper.AddReferencedAssembliesRecurse (System.String
assemblyPath, System.Collections.Generic.List`1[T] alreadyFoundAssemblies,
System.String[] allAssemblyPaths, System.String[] foldersToSearch,
System.Collections.Generic.Dictionary`2[TKey,TValue] cache,
UnityEditor.BuildTarget target) (at
C:/buildslave/unity/build/Editor/Mono/AssemblyHelper.cs:152)
UnityEditor.AssemblyHelper.FindAssembliesReferencedBy (System.String[] paths,
System.String[] foldersToSearch, UnityEditor.BuildTarget target) (at
C:/buildslave/unity/build/Editor/Mono/AssemblyHelper.cs:192)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
</code>```

My project need to use .Net 4.6. So, I have changed it in player setting. I don't have any error when I click play in the editor but when I want to build it, this is where it fail.

Hopefully someone can help me on this. Thank you

答:
I have found the solution to this question in another thread.

You can find it in this link.

Hopefully someone can benefit from my answer.

Body:
I'm using unity 2017.2 and ran into this error while building for APK file

ArgumentException: The Assembly System.Reflection.Emit is referenced by
Microsoft.AspNetCore.SignalR.Core
('Assets/Plugins/Microsoft.AspNetCore.SignalR.Core.dll'). But the dll is not
allowed to be included or could not be found.
UnityEditor.AssemblyHelper.AddReferencedAssembliesRecurse (System.String
assemblyPath, System.Collections.Generic.List`1[T] alreadyFoundAssemblies,
System.String[] allAssemblyPaths, System.String[] foldersToSearch,
System.Collections.Generic.Dictionary`2[TKey,TValue] cache,
UnityEditor.BuildTarget target) (at
C:/buildslave/unity/build/Editor/Mono/AssemblyHelper.cs:152)
UnityEditor.AssemblyHelper.FindAssembliesReferencedBy (System.String[] paths,
System.String[] foldersToSearch, UnityEditor.BuildTarget target) (at
C:/buildslave/unity/build/Editor/Mono/AssemblyHelper.cs:192)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

My project need to use .Net 4.6. So, I have changed it in player setting. I don't have any error when I click play in the editor but when I want to build it, this is where it fail.

Hopefully someone can help me on this. Thank you


问:
'React Hook useEffect has a missing dependency' warning with function
So I have this React component which uses the useEffect() hook:

```<code>const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem]);

const myFunction = () => {
  return 'hello';
}
</code>```

React gives me a warning about 'myFunction' being a missing dependency. I (think I) understand why and I've read through many similar questions asking for more or less the same thing, but the answer is always 'move your function into the useEffect hook'. This would be fine if not for myFunction being called from different places, e.g.:

```<code>...
return (
  <Button onClick={() => myFunction()} />
);
</code>```

therefore I cannot put my function inside the useEffect hook.

One answer to a similar question was to put the function outside the component, but that would require me to pass a lot of data to my functions, e.g.
const myFunction(stateItem, setStateItem, someProp) => { stuff };

which gets extremely tedious when there are several functions with many props, state hooks etc. to pass.

Aside from putting a linter ignore comment above the useEffect hook, is there anything more practical to do about this? I'm finding these things to make using react hooks very impractical.

答:
So it seems like your aim is to keep your function inside your component and

You don't want to move it inside useEffect since you want to use it elsewhere

You don't want to move it outside your function since you want to avoid passing parameters from the component

In that case you i think the best solution is to use the useCallback hook as shown below

```<code>
function YourComponent(props){

  const [stateItem, setStateItem] = useState(0);

  //wrap your logic in useCallback hook
  const myFunction = React.useCallback(
    () => {

      //if you use any dependencies in this function add them to the deps array of useCallback
      //so if any of the dependencies change thats only when the function changes

      return 'hello'
    }, [deps])

    useEffect(() => {
       if(condition) {
          myFunction();
       }

    //add your function to the dependency array as well
    //the useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array, besides the #1 rule is NEVER LIE ABOUT YOUR DEPENDENCIES
    //the function only changes if the dependencies to useCallback hook change!!
    }, [stateItem, myFunction ])

   return (
     <Button onClick={() => myFunction()} />
   );
}

</code>```

The useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array. the function only changes if the dependencies to useCallback hook change. By doing this we keep the golden rule of hooks which is NEVER LIE ABOUT YOUR DEPENDENCIES. Hope that helps. You might want to read this Blog Post By Dan Abramov

Body:
So I have this React component which uses the useEffect() hook:

const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem]);

const myFunction = () => {
  return 'hello';
}

React gives me a warning about 'myFunction' being a missing dependency. I (think I) understand why and I've read through many similar questions asking for more or less the same thing, but the answer is always 'move your function into the useEffect hook'. This would be fine if not for myFunction being called from different places, e.g.:

...
return (
  <Button onClick={() => myFunction()} />
);

therefore I cannot put my function inside the useEffect hook.

One answer to a similar question was to put the function outside the component, but that would require me to pass a lot of data to my functions, e.g.
const myFunction(stateItem, setStateItem, someProp) => { stuff };

which gets extremely tedious when there are several functions with many props, state hooks etc. to pass.

Aside from putting a linter ignore comment above the useEffect hook, is there anything more practical to do about this? I'm finding these things to make using react hooks very impractical.

Body:
So it seems like your aim is to keep your function inside your component and

You don't want to move it inside useEffect since you want to use it elsewhere

You don't want to move it outside your function since you want to avoid passing parameters from the component

In that case you i think the best solution is to use the useCallback hook as shown below

function YourComponent(props){

  const [stateItem, setStateItem] = useState(0);

  //wrap your logic in useCallback hook
  const myFunction = React.useCallback(
    () => {

      //if you use any dependencies in this function add them to the deps array of useCallback
      //so if any of the dependencies change thats only when the function changes

      return 'hello'
    }, [deps])

    useEffect(() => {
       if(condition) {
          myFunction();
       }

    //add your function to the dependency array as well
    //the useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array, besides the #1 rule is NEVER LIE ABOUT YOUR DEPENDENCIES
    //the function only changes if the dependencies to useCallback hook change!!
    }, [stateItem, myFunction ])

   return (
     <Button onClick={() => myFunction()} />
   );
}

The useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array. the function only changes if the dependencies to useCallback hook change. By doing this we keep the golden rule of hooks which is NEVER LIE ABOUT YOUR DEPENDENCIES. Hope that helps. You might want to read this Blog Post By Dan Abramov


问:
If form validation failed then redirect back with input using custom request class (laravel 5.8)
The problem is i want to return back with the inputs when the validation is fails. Here I'm using a custom request class to validate user input.

Now my question is where i place this piece of code on Controller Or in Request class.

  or is there another way to do it?

Here is the code i want to use:
return redirect()->back()->withInput();

Here is the Controller:

```<code><?php

namespace App\Http\Controllers\Admin;

use App\Http\Requests\Admin\counter\CreateCounterRequest;
use App\Models\Admin\Counter;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CounterController extends Controller
{
    public function store(CreateCounterRequest $request)
    {
        Counter::create([
            'title' => $request->title,
            'ion_icon' => $request->ion_icon,
            'counter_value' => $request->counter_value,
        ]);
        session()->flash('success', 'Counters created successfully.');
        return redirect(route('counter.index'));
    }
}

</code>```

Here is the Request Class:

```<code><?php

namespace App\Http\Requests\Admin\counter;

use Illuminate\Foundation\Http\FormRequest;

class CreateCounterRequest extends FormRequest
{
    public function rules()
    {
        return [
            'ion_icon' => 'required',
            'title' => 'required',
            'counter_value' => 'required|numeric',
        ];
    }

}
</code>```

答:
you can use a method from FormRequest class, that is failedValidation() method.

and example code is like this:

```<code>protected function failedValidation(Validator $validator)
{
    return back()->withErrors($validator)->withInput();
}
</code>```

you must add a argument from Illuminate\Contracts\Validation\Validator class to your method failedValidation and add Illuminate\Http\RedirectResponse class for get redirect method.

add Illuminate\Validation\ValidationException class, if not your method cant be read.

Body:
The problem is i want to return back with the inputs when the validation is fails. Here I'm using a custom request class to validate user input.

Now my question is where i place this piece of code on Controller Or in Request class.

  or is there another way to do it?

Here is the code i want to use:
return redirect()->back()->withInput();

Here is the Controller:

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Requests\Admin\counter\CreateCounterRequest;
use App\Models\Admin\Counter;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class CounterController extends Controller
{
    public function store(CreateCounterRequest $request)
    {
        Counter::create([
            'title' => $request->title,
            'ion_icon' => $request->ion_icon,
            'counter_value' => $request->counter_value,
        ]);
        session()->flash('success', 'Counters created successfully.');
        return redirect(route('counter.index'));
    }
}

Here is the Request Class:

<?php

namespace App\Http\Requests\Admin\counter;

use Illuminate\Foundation\Http\FormRequest;

class CreateCounterRequest extends FormRequest
{
    public function rules()
    {
        return [
            'ion_icon' => 'required',
            'title' => 'required',
            'counter_value' => 'required|numeric',
        ];
    }

}

Body:
you can use a method from FormRequest class, that is failedValidation() method.

and example code is like this:

protected function failedValidation(Validator $validator)
{
    return back()->withErrors($validator)->withInput();
}

you must add a argument from Illuminate\Contracts\Validation\Validator class to your method failedValidation and add Illuminate\Http\RedirectResponse class for get redirect method.

add Illuminate\Validation\ValidationException class, if not your method cant be read.


问:
Ansible, how to check if a variable is not null?
I have this var I a role that I use to add authorized keys to a linux user, so foo can either be a string with a single ssh public key or a list of multiple public keys.

By default foo is defined but empty so it can be tested even if the user doesn't set it, that way no related tasks are done if it's empty.

I'd normaly use when: foo or when: not foo and it was working great, except that now ansible trow a depreciation warning saying :

[DEPRECATION WARNING]: evaluating None as a bare variable, this
  behaviour will go away and you might need to add |bool to the
  expression in the future. Also see CONDITIONAL_BARE_VARS configuration
  toggle.. This feature will be removed in version 2.12. Deprecation
  warnings can be disabled by setting deprecation_warnings=False in
  ansible.cfg.

I tried when: foo|bool as mentionned but it returns false every time the variable is filled with a string that's not yes, true, Yes...

foo is defined doesn't work since the var is defined

foo != "" doesn't work because the var is null not a empty string

foo | length > 0 doesn't work because null doesn't have a length

I'm honestly out of ideas here.

答:
I think the answer is right there in the error. "evaluating None as a bare variable" suggests that foo evaluated to None. So you need:

when: foo != None


问:
Convert .dbc files into .csv with python
I'm writing a python script to convert .DBC files (from Datasus) into .CSV.

I've searched a lot some libs to help me but didn't get success with any of them. Do someone know an option/package which could be useful in this conversion task?

答:
If you're using python on Linux, one of the alternatives is using the project located at this repository: https://github.com/greatjapa/dbc2csv

It works by creating a docker that runs the bash script followed by the python script (you can also run them separately, without using docker, and that will work just as well).

It's also worth noting that the .dbc extension used by Datasus is one that they created themselves (not related to the .dbc used by cantools and other such tools), which just helps it being a pain to work with.


问:
VS2010 "Add Item" directory change
Is there any way to change the default directory Visual Studio 2010 uses when you add a source file through Add -> New Item?</p>

答:
Add New Item simply adds the item based on which project directory you're currently in or have selected in your Solution Explorer. If you want to change where it gets added then select the target location in the Solution Explorer first.

This behavior is obvious when right-clicking in the Solution Explorer, but it's also the same when using Project -> Add New Item....

Title: VS2010 "Add Item" directory change


问:
Why can't I return a list of specific email addresses from a Calendar invite with App Script?
I'm trying to return a list of specific email addresses of all event attendees on a GSuite calendar with a script and I can only return either an ID number or a list that appears only as "EventGuest, EventGuest, EventGuest...."

Is it possible to return the email address itself?  Thanks in advance for any guidance here!

This is the basic script that I'm working with:

```<code>function listCalendarAttendees(){
var calendar =  CalendarApp.getCalendarById('AnyCalendarTEST@gmail.com');
var sheet = SpreadsheetApp.openById('TEST ID').getSheetByName('Bobs Calendar');
var startTime = new Date();
var endTime = new Date(startTime.getTime()+(1000*60*60*24*7));
var events = calendar.getEvents(startTime, endTime);
Logger.log('Number '+events.length);
for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames =event.getGuestList().toString();

sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}
}
</code>```

答:
You want to retrieve the emails of all guests in the event.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Modification points:

getGuestList() returns the object of EventGuest[]. In this case, the email can be retrieved by getEmail() from EventGuest.

When appendRow() is used in the for loop, the process cost will be high. So in this modification, setValues() is used instead.

Modified script:

When your script is modified, it becomes as follows.

From:

```<code>for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames =event.getGuestList().toString();

sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}
</code>```

To:

```<code>var values = [];  // Added
for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames = event.getGuestList().map(function(e) {return e.getEmail()}).join(",");  // Modified
  values.push([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);  // Modified
}
sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);  // Added
</code>```

In this modification, the emails are separated by , and it is put to a cell.

References:

getGuestList()

Class EventGuest

getEmail()

If I misunderstood your question and this was not the direction you want, I apologize.

Body:
I'm trying to return a list of specific email addresses of all event attendees on a GSuite calendar with a script and I can only return either an ID number or a list that appears only as "EventGuest, EventGuest, EventGuest...."

Is it possible to return the email address itself?  Thanks in advance for any guidance here!

This is the basic script that I'm working with:

function listCalendarAttendees(){
var calendar =  CalendarApp.getCalendarById('AnyCalendarTEST@gmail.com');
var sheet = SpreadsheetApp.openById('TEST ID').getSheetByName('Bobs Calendar');
var startTime = new Date();
var endTime = new Date(startTime.getTime()+(1000*60*60*24*7));
var events = calendar.getEvents(startTime, endTime);
Logger.log('Number '+events.length);
for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames =event.getGuestList().toString();

sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}
}

Body:
You want to retrieve the emails of all guests in the event.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Modification points:

getGuestList() returns the object of EventGuest[]. In this case, the email can be retrieved by getEmail() from EventGuest.

When appendRow() is used in the for loop, the process cost will be high. So in this modification, setValues() is used instead.

Modified script:

When your script is modified, it becomes as follows.

From:

for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames =event.getGuestList().toString();

sheet.appendRow([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);
}

To:

var values = [];  // Added
for(var x=0;x<events.length;x++){
  var event = events[x];
  var messages = event.getTitle();
  var eventStart = event.getStartTime();
  var emails = event.getCreators().toString();
  var descriptions = event.getDescription();
  var guestListLength = event.getGuestList().length;
  var guestListNames = event.getGuestList().map(function(e) {return e.getEmail()}).join(",");  // Modified
  values.push([messages,eventStart,emails,descriptions,guestListLength,guestListNames]);  // Modified
}
sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);  // Added

In this modification, the emails are separated by , and it is put to a cell.

References:

getGuestList()

Class EventGuest

getEmail()

If I misunderstood your question and this was not the direction you want, I apologize.


问:
resizing image in tkinter for my browsing file code

how can I resize my image? here is my code..

```<code>from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from PIL import Image, ImageTk

class Root(Tk):
    def __init__(self):
        super(Root, self).__init__()
        self.title("Python Tkinter Dialog Widget")
        self.minsize(640, 400)

        self.labelFrame = ttk.LabelFrame(self, text = "Open File")
        self.labelFrame.grid(column = 0, row = 1, padx = 20, pady = 20)

        self.button()

    def button(self):
        self.button = ttk.Button(self.labelFrame, text = "Browse A File",command = self.fileDialog)
        self.button.grid(column = 1, row = 1)

    def fileDialog(self):

        self.filename = filedialog.askopenfilename(initialdir =  "/", title = "Select A File", filetype =
        (("jpeg files","*.jpg"),("all files","*.*")) )
        self.label = ttk.Label(self.labelFrame, text = "")
        self.label.grid(column = 1, row = 2)
        self.label.configure(text = self.filename)

        img = Image.open(self.filename)
        photo = ImageTk.PhotoImage(img)

        self.label2 = Label(image=photo)
        self.label2.image = photo
        self.label2.grid(column=3, row=4)

root = Root()
root.mainloop()
</code>```

答:
You can either use Image.resize() which does not keep the image aspect ratio, or Image.thumbnail() which keeps the image aspect ratio:

```<code>img = Image.open(self.filename)
imgsize = (600, 400)  # change to whatever size you want
#img = img.resize(imgsize)
img.thumbnail(imgsize)
photo = ImageTk.PhotoImage(img)
</code>```

Body:
how can I resize my image? here is my code..

from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from PIL import Image, ImageTk

class Root(Tk):
    def __init__(self):
        super(Root, self).__init__()
        self.title("Python Tkinter Dialog Widget")
        self.minsize(640, 400)

        self.labelFrame = ttk.LabelFrame(self, text = "Open File")
        self.labelFrame.grid(column = 0, row = 1, padx = 20, pady = 20)

        self.button()

    def button(self):
        self.button = ttk.Button(self.labelFrame, text = "Browse A File",command = self.fileDialog)
        self.button.grid(column = 1, row = 1)

    def fileDialog(self):

        self.filename = filedialog.askopenfilename(initialdir =  "/", title = "Select A File", filetype =
        (("jpeg files","*.jpg"),("all files","*.*")) )
        self.label = ttk.Label(self.labelFrame, text = "")
        self.label.grid(column = 1, row = 2)
        self.label.configure(text = self.filename)

        img = Image.open(self.filename)
        photo = ImageTk.PhotoImage(img)

        self.label2 = Label(image=photo)
        self.label2.image = photo
        self.label2.grid(column=3, row=4)

root = Root()
root.mainloop()

Body:
You can either use Image.resize() which does not keep the image aspect ratio, or Image.thumbnail() which keeps the image aspect ratio:

img = Image.open(self.filename)
imgsize = (600, 400)  # change to whatever size you want
#img = img.resize(imgsize)
img.thumbnail(imgsize)
photo = ImageTk.PhotoImage(img)


答:
Event Guest is an object.  Here are it's methods:

getEmail()

getAdditionalGuests()

getGuestStatus()

getName()

Title: Why can't I return a list of specific email addresses from a Calendar invite with App Script?


问:
React form submission logic with lifted state and controlled dependence
I've dug myself into a deep rabbit hole with this component in an attempt to use React hooks.

The Parent component handles a dictionary state which is eventually distributed to multiple components.

My problem child component WordInput has a form with a single input. When submitting the form the component is fetching the word's definition from an API and passing on both the word and the definition to the parent which then sets the state in the form of dictionary. So far, so good IF it's the first word in dictionary. The part I'm having trouble with is to submit any subsequent words/definitions.

When the user submits a subsequent word, I want the component to check whether the word already exists in the dictionary that is passed to the child. If it doesn't exist, add it to the dictionary via the submit function.

I think the problem is that I'm trying to do too much with useEffect
I useEffect to:
  - set loading
  - check and process the dictionary for existing words
  - check that definition and word aren't empty and submit both to parent/dictionary
  - fetch a definition from an API

In the unprocessed code, I have multiple console.groups to help me keep track of what is happening. The more I add to the component, the more Subgroups and subgroups of subgroups accumulate. Clearly, the approach I'm taking isn't very dry and causes too many re-renders of the component/useEffect functions. For conciseness, I have taken out the console.log entries.

The imported fetchWordDefinition merely processes the fetched data and arranges it correctly into an array.

I don't know how to keep this dry and effective, and any help is appreciated with this rather simple task. My hunch is to keep all the logic to submit the word/definition in the submit handler, and only use useEffect to validate the data prior to that.

```<code>import React, { useState, useEffect } from "react";
import fetchWordDefinition from "./lib/utils";

const WordInput = ({ onSubmit, dictionary }) => {
    const [definition, setDefinition] = useState([]);
    const [cause, setCause] = useState({ function: "" });
    const [error, setError] = useState({});
    const [loading, setLoading] = useState(false);
    const [word, setWord] = useState("");
    const [wordExistsInDB, setWordExistsInDB] = useState(false);

    useEffect(() => {
        const dictionaryEmpty = dictionary.length === 0 ? true : false;

        if (dictionaryEmpty) {
            return;
        } else {
            for (let i = 0; i < dictionary.length; i += 1) {
                if (dictionary[i].word === word) {
                    setWordExistsInDB(true);
                    setError({ bool: true, msg: "Word already exists in DB" });
                    break;
                } else {
                    setWordExistsInDB(false);
                    setError({ bool: false, msg: "" });
                }
            }
        }
    }, [dictionary, word]);

    useEffect(() => {
        const definitionNotEmpty = definition.length !== 0 ? true : false;
        const wordNotEmpty = word !== "" ? true : false;

        if (wordNotEmpty && definitionNotEmpty && !wordExistsInDB) {
            onSubmit(word, definition);
            setWord("");
            setDefinition([]);
        }
    }, [definition, word, onSubmit, wordExistsInDB]);

    useEffect(() => {
        if (cause.function === "fetch") {
            async function fetchFunction() {
                const fetch = await fetchWordDefinition(word);
                return fetch;
            }

            fetchFunction().then(definitionArray => {
                setDefinition(definitionArray);
                setCause({ function: "" });
            });
        }
    }, [cause, word]);

    const handleSubmit = async e => {
        e.preventDefault();

        setLoading(true);
        setCause({ function: "fetch" });
    };

    return (
        <form onSubmit={handleSubmit}>
            {error.bool ? <span>{error.msg}</span> : null}
            <input
                name='word'
                placeholder='Enter Word'
                type='text'
                value={word}
                onChange={({ target: { value } }) => setWord(value)}
            />
            <input type='submit' />
        </form>
    );
};

export default WordInput;
</code>```

答:
Your component only needs to keep track of the word and the loading flag.

When the user changes the word input it updates the word state.

When the user submits the form the loading state changes. This triggers a useEffect that will first check if the word already exists. If not it proceeds to fetch it and add both the word and its definition to the dictionary.

```<code>const WordInput = ({ onSubmit, dictionary }) => {
    const [loading, setLoading] = useState(false);
    const [word, setWord] = useState("");

    useEffect(() => {
        if (!loading) return;

        const existing_word = dictionary.find(item => item.word === word);

        if (existing_word) return;

        const fetchFunction = async () => {
            const definition = await fetchWordDefinition(word);

            // Update the dictionary
            onSubmit(word, definition);

            // Reset the component state
            setWord("");
            setLoading(false);
        };

        fetchFunction();
    }, [loading]);

    return (
        <form
            onSubmit={e => {
                e.preventDefault();

                if (word.length) {
                    setLoading(true);
                }
            }}
        >
            <input
                name="word"
                placeholder="Enter Word"
                type="text"
                value={word}
                onChange={({ target: { value } }) => setWord(value)}
            />
            <input type="submit" />
        </form>
    );
};
</code>```

Please let me know if something is not clear or I missed something.

Body:
I've dug myself into a deep rabbit hole with this component in an attempt to use React hooks.

The Parent component handles a dictionary state which is eventually distributed to multiple components.

My problem child component WordInput has a form with a single input. When submitting the form the component is fetching the word's definition from an API and passing on both the word and the definition to the parent which then sets the state in the form of dictionary. So far, so good IF it's the first word in dictionary. The part I'm having trouble with is to submit any subsequent words/definitions.

When the user submits a subsequent word, I want the component to check whether the word already exists in the dictionary that is passed to the child. If it doesn't exist, add it to the dictionary via the submit function.

I think the problem is that I'm trying to do too much with useEffect
I useEffect to:
  - set loading
  - check and process the dictionary for existing words
  - check that definition and word aren't empty and submit both to parent/dictionary
  - fetch a definition from an API

In the unprocessed code, I have multiple console.groups to help me keep track of what is happening. The more I add to the component, the more Subgroups and subgroups of subgroups accumulate. Clearly, the approach I'm taking isn't very dry and causes too many re-renders of the component/useEffect functions. For conciseness, I have taken out the console.log entries.

The imported fetchWordDefinition merely processes the fetched data and arranges it correctly into an array.

I don't know how to keep this dry and effective, and any help is appreciated with this rather simple task. My hunch is to keep all the logic to submit the word/definition in the submit handler, and only use useEffect to validate the data prior to that.

import React, { useState, useEffect } from "react";
import fetchWordDefinition from "./lib/utils";

const WordInput = ({ onSubmit, dictionary }) => {
    const [definition, setDefinition] = useState([]);
    const [cause, setCause] = useState({ function: "" });
    const [error, setError] = useState({});
    const [loading, setLoading] = useState(false);
    const [word, setWord] = useState("");
    const [wordExistsInDB, setWordExistsInDB] = useState(false);

    useEffect(() => {
        const dictionaryEmpty = dictionary.length === 0 ? true : false;

        if (dictionaryEmpty) {
            return;
        } else {
            for (let i = 0; i < dictionary.length; i += 1) {
                if (dictionary[i].word === word) {
                    setWordExistsInDB(true);
                    setError({ bool: true, msg: "Word already exists in DB" });
                    break;
                } else {
                    setWordExistsInDB(false);
                    setError({ bool: false, msg: "" });
                }
            }
        }
    }, [dictionary, word]);

    useEffect(() => {
        const definitionNotEmpty = definition.length !== 0 ? true : false;
        const wordNotEmpty = word !== "" ? true : false;

        if (wordNotEmpty && definitionNotEmpty && !wordExistsInDB) {
            onSubmit(word, definition);
            setWord("");
            setDefinition([]);
        }
    }, [definition, word, onSubmit, wordExistsInDB]);

    useEffect(() => {
        if (cause.function === "fetch") {
            async function fetchFunction() {
                const fetch = await fetchWordDefinition(word);
                return fetch;
            }

            fetchFunction().then(definitionArray => {
                setDefinition(definitionArray);
                setCause({ function: "" });
            });
        }
    }, [cause, word]);

    const handleSubmit = async e => {
        e.preventDefault();

        setLoading(true);
        setCause({ function: "fetch" });
    };

    return (
        <form onSubmit={handleSubmit}>
            {error.bool ? {error.msg} : null}
            <input
                name='word'
                placeholder='Enter Word'
                type='text'
                value={word}
                onChange={({ target: { value } }) => setWord(value)}
            />
            <input type='submit' />
        </form>
    );
};

export default WordInput;

Body:
Your component only needs to keep track of the word and the loading flag.

When the user changes the word input it updates the word state.

When the user submits the form the loading state changes. This triggers a useEffect that will first check if the word already exists. If not it proceeds to fetch it and add both the word and its definition to the dictionary.

const WordInput = ({ onSubmit, dictionary }) => {
    const [loading, setLoading] = useState(false);
    const [word, setWord] = useState("");

    useEffect(() => {
        if (!loading) return;

        const existing_word = dictionary.find(item => item.word === word);

        if (existing_word) return;

        const fetchFunction = async () => {
            const definition = await fetchWordDefinition(word);

            // Update the dictionary
            onSubmit(word, definition);

            // Reset the component state
            setWord("");
            setLoading(false);
        };

        fetchFunction();
    }, [loading]);

    return (
        <form
            onSubmit={e => {
                e.preventDefault();

                if (word.length) {
                    setLoading(true);
                }
            }}
        >
            <input
                name="word"
                placeholder="Enter Word"
                type="text"
                value={word}
                onChange={({ target: { value } }) => setWord(value)}
            />
            <input type="submit" />
        </form>
    );
};

Please let me know if something is not clear or I missed something.


问:
Python calling one function form another
I have written a little python script to get files in a directory, get a hash and then write them to a table.

The first part, getting the files and calculating the hash was easy. But now I added the function (write_record) to store the filename, log date and hash to a database. But I am struggling how to call it form the get_files function an write a record for each file in the directory

```<code>from datetime import datetime
from os import scandir
import os
import hashlib
import psycopg2
BLOCKSIZE = 65536
hasher = hashlib.sha256()
basepath = '.'

def convert_date(timestamp):
     d = datetime.utcfromtimestamp(timestamp)
     formated_date = d.strftime('%d%m%Y%H%M%S')
     return formated_date

def get_hash(entry):
    with open(entry, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while len(buf) > 0:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)
                               # print(hasher.hexdigest())

def get_files():
    dir_entries = scandir('.')
    for entry in dir_entries:
        if entry.is_file():
             info = entry.stat()
        print(' %s %s %s' % (entry.name, convert_date(info.st_mtime),hasher.hexdigest()))
        log_filename = entry.name
        log_hashvalue = hasher.hexdigest()
        log_date = convert_date(info.st_mtime)
        return log_filename,log_hashvalue,log_date
       # write_record()

def write_record():
    log_filename,log_hashvalue,log_date = get_files()
    try:
        print(log_filename,log_hashvalue,log_date)
        connection = psycopg2.connect(user="postgres",password="xxxxxxxx",host="xxx.xxx.xxx.xxx",port="5432",database="evidence_logging")
        cursor = connection.cursor()
        postgres_insert_query = """ INSERT INTO logfiles (log_name,log_date,log_hashvalue) VALUES (%s,%s,%s)"""
        record_to_insert = (log_filename,log_date,log_hashvalue)
        print(postgres_insert_query, record_to_insert)
        cursor.execute(postgres_insert_query, record_to_insert)
        connection.commit()
        count = cursor.rowcount
        print (count, "Record inserted successfully into logfiles table")

    except (Exception, psycopg2.Error) as error :
        if(connection):
            print("Failed to insert record into logfiles table", error)

    finally:
    #closing database connection.
        if(connection):
            cursor.close()
            connection.close()
            print("PostgreSQL connection is closed")

write_record()
</code>```

Thanks in advance
Regards
Georg

答:
In your code you are calling write_record() method this will insert only one file beacause get_files() method will return the first file not all the files.

first you need to call get_files() method instead of returning in this method you should call write_record() method with the values you are returning from get_files().

And do not close the connection after insertion of every record close the connection after insertion of all the records.

try this

```<code>from datetime import datetime
from os import scandir
import os
import hashlib
import psycopg2
BLOCKSIZE = 65536
hasher = hashlib.sha256()
basepath = '.'
connection = None

def convert_date(timestamp):
    d = datetime.utcfromtimestamp(timestamp)
    formated_date = d.strftime('%d%m%Y%H%M%S')
    return formated_date

def get_hash(entry):
    with open(entry, 'rb') as afile:
    buf = afile.read(BLOCKSIZE)
    while len(buf) > 0:
        hasher.update(buf)
        buf = afile.read(BLOCKSIZE)
        # print(hasher.hexdigest())

def get_files():
    dir_entries = scandir('.')
    for entry in dir_entries:
        if entry.is_file():
          info = entry.stat()
        print(' %s %s %s' % (entry.name, convert_date(info.st_mtime),hasher.hexdigest()))
        log_filename = entry.name
        log_hashvalue = hasher.hexdigest()
        log_date = convert_date(info.st_mtime)
        write_record(log_filename,log_hashvalue,log_date)
    #close the connection after writing all records
    close_connection()

def write_record(log_filename,log_hashvalue,log_date):
    try:
        print(log_filename,log_hashvalue,log_date)
        connection = psycopg2.connect(user="postgres",password="xxxxxxxx",host="xxx.xxx.xxx.xxx",port="5432",database="evidence_logging")
        cursor = connection.cursor()
        postgres_insert_query = """ INSERT INTO logfiles (log_name,log_date,log_hashvalue) VALUES (%s,%s,%s)"""
        record_to_insert = (log_filename,log_date,log_hashvalue)
        print(postgres_insert_query, record_to_insert)
        cursor.execute(postgres_insert_query, record_to_insert)
        connection.commit()
        count = cursor.rowcount
        print (count, "Record inserted successfully into logfiles table")

    except (Exception, psycopg2.Error) as error :
        if(connection):
            print("Failed to insert record into logfiles table", error)

    finally:
        cursor.close()

def close_connection():
    if(connection):
        connection.close()
        print("PostgreSQL connection is closed")

get_files()
</code>```

Body:
I have written a little python script to get files in a directory, get a hash and then write them to a table.

The first part, getting the files and calculating the hash was easy. But now I added the function (write_record) to store the filename, log date and hash to a database. But I am struggling how to call it form the get_files function an write a record for each file in the directory

from datetime import datetime
from os import scandir
import os
import hashlib
import psycopg2
BLOCKSIZE = 65536
hasher = hashlib.sha256()
basepath = '.'

def convert_date(timestamp):
     d = datetime.utcfromtimestamp(timestamp)
     formated_date = d.strftime('%d%m%Y%H%M%S')
     return formated_date

def get_hash(entry):
    with open(entry, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while len(buf) > 0:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)
                               # print(hasher.hexdigest())

def get_files():
    dir_entries = scandir('.')
    for entry in dir_entries:
        if entry.is_file():
             info = entry.stat()
        print(' %s %s %s' % (entry.name, convert_date(info.st_mtime),hasher.hexdigest()))
        log_filename = entry.name
        log_hashvalue = hasher.hexdigest()
        log_date = convert_date(info.st_mtime)
        return log_filename,log_hashvalue,log_date
       # write_record()

def write_record():
    log_filename,log_hashvalue,log_date = get_files()
    try:
        print(log_filename,log_hashvalue,log_date)
        connection = psycopg2.connect(user="postgres",password="xxxxxxxx",host="xxx.xxx.xxx.xxx",port="5432",database="evidence_logging")
        cursor = connection.cursor()
        postgres_insert_query = """ INSERT INTO logfiles (log_name,log_date,log_hashvalue) VALUES (%s,%s,%s)"""
        record_to_insert = (log_filename,log_date,log_hashvalue)
        print(postgres_insert_query, record_to_insert)
        cursor.execute(postgres_insert_query, record_to_insert)
        connection.commit()
        count = cursor.rowcount
        print (count, "Record inserted successfully into logfiles table")

    except (Exception, psycopg2.Error) as error :
        if(connection):
            print("Failed to insert record into logfiles table", error)

    finally:
    #closing database connection.
        if(connection):
            cursor.close()
            connection.close()
            print("PostgreSQL connection is closed")

write_record()

Thanks in advance
Regards
Georg

Body:
In your code you are calling write_record() method this will insert only one file beacause get_files() method will return the first file not all the files.

first you need to call get_files() method instead of returning in this method you should call write_record() method with the values you are returning from get_files().

And do not close the connection after insertion of every record close the connection after insertion of all the records.

try this

from datetime import datetime
from os import scandir
import os
import hashlib
import psycopg2
BLOCKSIZE = 65536
hasher = hashlib.sha256()
basepath = '.'
connection = None

def convert_date(timestamp):
    d = datetime.utcfromtimestamp(timestamp)
    formated_date = d.strftime('%d%m%Y%H%M%S')
    return formated_date

def get_hash(entry):
    with open(entry, 'rb') as afile:
    buf = afile.read(BLOCKSIZE)
    while len(buf) > 0:
        hasher.update(buf)
        buf = afile.read(BLOCKSIZE)
        # print(hasher.hexdigest())

def get_files():
    dir_entries = scandir('.')
    for entry in dir_entries:
        if entry.is_file():
          info = entry.stat()
        print(' %s %s %s' % (entry.name, convert_date(info.st_mtime),hasher.hexdigest()))
        log_filename = entry.name
        log_hashvalue = hasher.hexdigest()
        log_date = convert_date(info.st_mtime)
        write_record(log_filename,log_hashvalue,log_date)
    #close the connection after writing all records
    close_connection()

def write_record(log_filename,log_hashvalue,log_date):
    try:
        print(log_filename,log_hashvalue,log_date)
        connection = psycopg2.connect(user="postgres",password="xxxxxxxx",host="xxx.xxx.xxx.xxx",port="5432",database="evidence_logging")
        cursor = connection.cursor()
        postgres_insert_query = """ INSERT INTO logfiles (log_name,log_date,log_hashvalue) VALUES (%s,%s,%s)"""
        record_to_insert = (log_filename,log_date,log_hashvalue)
        print(postgres_insert_query, record_to_insert)
        cursor.execute(postgres_insert_query, record_to_insert)
        connection.commit()
        count = cursor.rowcount
        print (count, "Record inserted successfully into logfiles table")

    except (Exception, psycopg2.Error) as error :
        if(connection):
            print("Failed to insert record into logfiles table", error)

    finally:
        cursor.close()

def close_connection():
    if(connection):
        connection.close()
        print("PostgreSQL connection is closed")

get_files()


问:
How do I determine which render pipeline I'm using in an existing Unity project?
I have an existing project and just found out there are multiple render pipelines available. I don't remember which I chose (if I chose) back when creating the project. How do I determine which render pipeline I'm using in an existing Unity project?

https://docs.unity3d.com/2019.3/Documentation/Manual/render-pipelines.html

答:
Go to Edit -> Project Settings -> Graphics

If you chose the Built-in Render Pipeline (default) the Scriptable Render Pipeline Settings field will say None.


问:
Output sum, avg, and standard deviation from imported text file arrays
my text file, garbageData contains these numbers:

40 50 43 98 20

10 67 84 25 71

37 54 32 90 62

76 49 69 95 44

11 22 33 44 55

I'm trying to read garbageData and store the numbers in an array. Then I need to get a sum, average, and standard deviation of those numbers that are stored.

Then for each number in the array, I need to add a random number ranging from 1 to 10 to that number and store the new number in a different array.

This is what I have so far, but I can't manipulate it. What am I doing wrong?

```<code>    with open('garbageData.txt','r') as myArray:
       for x in myArray:
       sum = sum(myArray)
       print(sum)
</code>```

答:
Reading a file returns strings, it doesn't parse the numbers. You need to split the file and convert them to numbers.

```<code>with open('garbageData.txt', 'r') as f:
    nums = [int(x) for x in f.read().split()]
mysum = sum(nums)
print(mysum)
</code>```

You shouldn't use sum as your variable name, since it will replace the built-in function sum().

Body:
my text file, garbageData contains these numbers:

40 50 43 98 20

10 67 84 25 71

37 54 32 90 62

76 49 69 95 44

11 22 33 44 55

I'm trying to read garbageData and store the numbers in an array. Then I need to get a sum, average, and standard deviation of those numbers that are stored.

Then for each number in the array, I need to add a random number ranging from 1 to 10 to that number and store the new number in a different array.

This is what I have so far, but I can't manipulate it. What am I doing wrong?

    with open('garbageData.txt','r') as myArray:
       for x in myArray:
       sum = sum(myArray)
       print(sum)

Body:
Reading a file returns strings, it doesn't parse the numbers. You need to split the file and convert them to numbers.

with open('garbageData.txt', 'r') as f:
    nums = [int(x) for x in f.read().split()]
mysum = sum(nums)
print(mysum)

You shouldn't use sum as your variable name, since it will replace the built-in function sum().


问:
Can we access azure web app by private link
My on premises network is connected to azure over expressroute. Now with the new private link for azure app service, can the on-prem users connect to azure app service with private ip, without going over the internet

答:
No, Azure Private Link is in Preview and currently supports Azure Storage and SQL Database, not Azure app service.

Note that several Azure PaaS services such as Azure Storage, Azure
  Data Lake Storage Gen 2, Azure SQL Database, Azure SQL Data Warehouse,
  Key Vault, Azure Database for MySQL, Azure Database for PostgreSQL,
  and Azure Database for MariaDB still offer consumption over Private
  Link in preview. Azure PaaS will soon offer support for consumption
  over Private Link in general availability.

Read https://azure.microsoft.com/en-us/updates/private-link-now-available-in-ga/


问:
iOS 13.0 - Best approach for supporting Dark Mode and also support iOS 11 & 12
So I've posted on Apple Developer Forums, but haven't gotten a reply yet.

Background:

iOS 13 has introduced Dark Mode and a number of System Colors with predefined Light and Dark variants: (https://developer.apple.com/videos/play/wwdc2019/214/)

These colors can be used in the storyboard directly as named colors. They've also been added as static colors to the UIColor class: (https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors)

However, static colors added to UIColor are not available in code in iOS 11 and 12. This makes its tricky to use them as all references to the new System Colors must be wrapped in an availability check:

It also raises the question: on iOS 11 and 12, what will the System colors resolve to when used directly in the Storyboard? In our testing they seem to resolve to the Light variant, though we haven't tested all of them.

Current approach:

This is the approach we are leaning towards. We will add all colors to our Colors.xcassets file for older iOS version support, and through our CustomColors Enum perform a single version check and mapping so the correct UIColor system colors is returned depending on the iOS version. Once we drop support for iOS 11 and 12 we will remove the respective colors from Colors.xcassets as we will only be using the System Colors instead.
We will also refactor all our storyboards to use the new System Colors.

The drawbacks of this approach are:

If we want to use system colors directly in our code after we drop support for iOS 11 and 12 (UIColor.label, UIColor.systemBackground, etc), it could be quite a large refactor to get rid of all the enum references

Because we will be using System Colors in our storyboard, we must ensure that our Colors.xcassets equivalents use the same color code

This bug: (UIColor(named:) always returns nil on iOS 11.0-11.2) - if its not fixed then this approach is unusable (EDIT: This bug is fixed in XCode 11 GM seed 2 11A420a)

As with all Asset Catalogs, using magic strings to access items in the catalog makes it easy for developers to make a mistake and get nil instead of the asset (the color in this case). This could result in difficult-to-pick-up bugs if we don't test every single screen, forcing us to write the crashIfAllColorsNotDefined() method. using an enum does mitigate this risk as the magic strings are only stored/used in one place.

Other approaches: (How do I easily support light and dark mode with a custom color used in my app?)

Question:

What are some other approaches one could use to support Dark Mode with iOS 13 by using the new System colors, while still supporting iOS 11 and 12?
And is it safe to use the new System Colors in Storyboards on older iOS versions?

答:
A combination of Enum and UIColor Extension was the way to go in the end.
There are two 'parts' to the custom colors - your app's special colors and duplicate apple colors.

Some of the new colors Apple released are only available in iOS13 or later (systemBackground, opaqueSeparator, secondaryLabel, etc). If you want to use these right away then you'll have to create them as custom colors. This is a concern because it increases future technical debt, as these colors would have to be refactored once iOS13 becomes your minimum supported version. This is especially difficult to refactor in Storyboards.

The way this solution is set up, the UIColors extension can be easily modified to return the official apple colors at a later stage. You should only set duplicate apple colors programmatically - don't use them directly in Storyboards.

In code:

```<code>self.backgroundColor = .red1
self.layer.borderColor = UIColor.successGreen1.cgColor
</code>```

Colors Enum:

```<code>// Enum for all custom colors
private enum CustomColors : String, CaseIterable {
    case red1 = "red1"
    case red2 = "red2"
    case blue1 = "blue1"
    case blue2 = "blue2"
    case successGreen1 = "successGreen1"
    case warningOrange1 = "warningOrange1"

    //----------------------------------------------------------------------
    // MARK: - Apple colors
    //----------------------------------------------------------------------

    // Duplicates for new apple colors only available in iOS 13
    case opaqueSeparator = "customOpaqueSeparator"
    case systemBackground = "customSystemBackground"
    case systemGroupedBackground = "customSystemGroupedBackground"
    case secondarySystemGroupedBackground = "customSecondarySystemGroupedBackground"
    case secondaryLabel = "customSecondaryLabel"
    case systemGray2 = "customSystemGray2"
}
</code>```

UIColor extension:

```<code>// Extension on UIColor for all custom (and unsupported) colors available
extension UIColor {

    //----------------------------------------------------------------------
    // MARK: - Apple colors with #available(iOS 13.0, *) check
    //----------------------------------------------------------------------

    // These can all be removed when iOS13 becomes your minimum supported platform.
    // Or just return the correct apple-defined color instead.

    /// Opaque Seperator color
    static var customOpaqueSeparator: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.opaqueSeparator
        } else {
            return UIColor(named: CustomColors.opaqueSeparator.rawValue)!
        }
    }

    /// System Background color
    static var customSystemBackground: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.systemBackground
        } else {
            return UIColor(named: CustomColors.systemBackground.rawValue)!
        }
    }

    /// System Grouped Background color
    static var customSystemGroupedBackground: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.systemGroupedBackground
        } else {
            return UIColor(named: CustomColors.systemGroupedBackground.rawValue)!
        }
    }

    // more

    //----------------------------------------------------------------------
    // MARK: - My App Custom Colors
    //----------------------------------------------------------------------

    /// Red 1 color
    static var red1: UIColor {
        return UIColor(named: CustomColors.red1.rawValue)!
    }

    /// Red 2 color
    static var red2: UIColor {
        return UIColor(named: CustomColors.red2.rawValue)!
    }

    /// Success Green 1 color
    static var successGreen1: UIColor {
        return UIColor(named: CustomColors.successGreen1.rawValue)!
    }

    // more

    //----------------------------------------------------------------------
    // MARK: - Crash If Not Defined check
    //----------------------------------------------------------------------

    // Call UIColor.crashIfCustomColorsNotDefined() in AppDelegate.didFinishLaunchingWithOptions. If your application
    // has unit tests, perhaps ensure that all colors exist via unit tests instead.

    /// Iterates through CustomColors enum and check that each color exists as a named color.
    /// Crashes if any don't exist.
    /// This is done because UIColor(named:) returns an optionl. This is bad -
    /// it means that our code could crash on a particular screen, but only at runtime. If we don't coincidently test that screen
    /// during testing phase, then customers could suffer unexpected behavior.
    static func crashIfCustomColorsNotDefined() {
        CustomColors.allCases.forEach {
           guard UIColor(named: $0.rawValue) != nil else {
            Logger.log("Custom Colors - Color not defined: " + $0.rawValue)
            fatalError()
           }
       }
    }
}
</code>```

In Storyboards:

Pick custom colors directly, except for the duplicate apple colors.

Colors.xcassets:

Body:
A combination of Enum and UIColor Extension was the way to go in the end.
There are two 'parts' to the custom colors - your app's special colors and duplicate apple colors.

Some of the new colors Apple released are only available in iOS13 or later (systemBackground, opaqueSeparator, secondaryLabel, etc). If you want to use these right away then you'll have to create them as custom colors. This is a concern because it increases future technical debt, as these colors would have to be refactored once iOS13 becomes your minimum supported version. This is especially difficult to refactor in Storyboards.

The way this solution is set up, the UIColors extension can be easily modified to return the official apple colors at a later stage. You should only set duplicate apple colors programmatically - don't use them directly in Storyboards.

In code:

self.backgroundColor = .red1
self.layer.borderColor = UIColor.successGreen1.cgColor

Colors Enum:

// Enum for all custom colors
private enum CustomColors : String, CaseIterable {
    case red1 = "red1"
    case red2 = "red2"
    case blue1 = "blue1"
    case blue2 = "blue2"
    case successGreen1 = "successGreen1"
    case warningOrange1 = "warningOrange1"

    //----------------------------------------------------------------------
    // MARK: - Apple colors
    //----------------------------------------------------------------------

    // Duplicates for new apple colors only available in iOS 13
    case opaqueSeparator = "customOpaqueSeparator"
    case systemBackground = "customSystemBackground"
    case systemGroupedBackground = "customSystemGroupedBackground"
    case secondarySystemGroupedBackground = "customSecondarySystemGroupedBackground"
    case secondaryLabel = "customSecondaryLabel"
    case systemGray2 = "customSystemGray2"
}

UIColor extension:

// Extension on UIColor for all custom (and unsupported) colors available
extension UIColor {

    //----------------------------------------------------------------------
    // MARK: - Apple colors with #available(iOS 13.0, *) check
    //----------------------------------------------------------------------

    // These can all be removed when iOS13 becomes your minimum supported platform.
    // Or just return the correct apple-defined color instead.

    /// Opaque Seperator color
    static var customOpaqueSeparator: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.opaqueSeparator
        } else {
            return UIColor(named: CustomColors.opaqueSeparator.rawValue)!
        }
    }

    /// System Background color
    static var customSystemBackground: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.systemBackground
        } else {
            return UIColor(named: CustomColors.systemBackground.rawValue)!
        }
    }

    /// System Grouped Background color
    static var customSystemGroupedBackground: UIColor {
        if #available(iOS 13.0, *) {
            return UIColor.systemGroupedBackground
        } else {
            return UIColor(named: CustomColors.systemGroupedBackground.rawValue)!
        }
    }

    // more

    //----------------------------------------------------------------------
    // MARK: - My App Custom Colors
    //----------------------------------------------------------------------

    /// Red 1 color
    static var red1: UIColor {
        return UIColor(named: CustomColors.red1.rawValue)!
    }

    /// Red 2 color
    static var red2: UIColor {
        return UIColor(named: CustomColors.red2.rawValue)!
    }

    /// Success Green 1 color
    static var successGreen1: UIColor {
        return UIColor(named: CustomColors.successGreen1.rawValue)!
    }

    // more

    //----------------------------------------------------------------------
    // MARK: - Crash If Not Defined check
    //----------------------------------------------------------------------

    // Call UIColor.crashIfCustomColorsNotDefined() in AppDelegate.didFinishLaunchingWithOptions. If your application
    // has unit tests, perhaps ensure that all colors exist via unit tests instead.

    /// Iterates through CustomColors enum and check that each color exists as a named color.
    /// Crashes if any don't exist.
    /// This is done because UIColor(named:) returns an optionl. This is bad -
    /// it means that our code could crash on a particular screen, but only at runtime. If we don't coincidently test that screen
    /// during testing phase, then customers could suffer unexpected behavior.
    static func crashIfCustomColorsNotDefined() {
        CustomColors.allCases.forEach {
           guard UIColor(named: $0.rawValue) != nil else {
            Logger.log("Custom Colors - Color not defined: " + $0.rawValue)
            fatalError()
           }
       }
    }
}

In Storyboards:

Pick custom colors directly, except for the duplicate apple colors.

Colors.xcassets: