martin clayton's helpful answer provides a good explanation of the problem[1], but his solution - as he states - has a potentially unwanted side effect.
Here are side-effect-free solutions:
Caveat: Solving the -i syntax problem alone, as below, may not be enough, because there are many other differences between GNU sed and BSD/macOS sed (for a comprehensive discussion, see this answer of mine).
Workaround with -i: Create a backup file temporarily, then clean it up:
With a non-empty suffix (backup-file filename extension) option-argument (a value that is not the empty string), you can use -i in a way that works with both BSD/macOS sed and GNU sed, by directly appending the suffix to the -i option.
This can be utilized to create a backup file temporarily that you can clean up right away:
sed -i.bak 's/foo/bar/' file && rm file.bak
Obviously, if you do want to keep the backup, simply omit the && rm file.bak part.
Workaround that is POSIX-compliant, using a temporary file and mv:
If only a single file is to be edited in-place, the -i option can be bypassed to avoid the incompatibility.
If you restrict your sed script and other options to POSIX-compliant features, the following is a fully portable solution (note that -i is not POSIX-compliant).
sed 's/foo/bar' file > /tmp/file.$$ && mv /tmp/file.$$ file
- This command simply writes the modifications to a temporary file and, if the - sedcommand succeeds (- &&), replaces the original file with the temporary one.
 - 
- If you do want to keep the original file as a backup, add another mvcommand that renames the original first.
 
- Caveat: Fundamentally, this is what - -idoes too, except that it tries to preserve permissions and extended attributes (macOS) of the original file; however, if the original file is a symlink, both this solution and- -iwill replace the symlink with a regular file.
 See the bottom half of this answer of mine for details on how- -iworks.
 
[1] For a more in-depth explanation, see this answer of mine.