Can an If Statement tell if an assignment was valid? - objective-c

I have an object that returns a value if successful and false (or nil) if it failed.
i want to assign that value to a variable
if(var1 = [object foo])
{
//if the [object foo] returned a variable, goes here
}
else
{
//[object foo] returned FALSE (or nil), go here
}
can an If statement detected if an assignment was valid?

This is all right but will generate a warning, since this is a common typo (= instead of ==). To silence that warning add another set of parentheses like this:
if ((var = [object foo])) ...
Since this easily can lead to misunderstandings a lot of people will advise against doing this. For a simple if statement this is much clearer to do the assignment first:
var = [object for];
if (var) ...
In while loops this is more useful, but also considered harmful by many people.

Not sure I understand your question, but let me try and explain a few situations you can check
1) Property contains value
if ([object foo])
{
// If foo has a value associated to it that is not nil/false/zero
}
else
{
// If foo equals nil, false or zero
}
2) Assignment to a variable was successful
if ((bar = [object myMethod]))
{
// If myMethod returns any non-nil value
}
else
{
// If myMethod returns nil
}
3) Previous assignment of a variable was successful
bar = [object myMethod];
if (bar)
{
// If bar has a value associated to it that is not nil/false/zero
}
else
{
// If bar equals nil, false or zero
}

use == instead of = in the if statement.
before the if statement, you may have var1 = [object foo]
see comparison operators

If you mean by valid that the variable contains an expected result, you can just perform another if on the variable against the expected result, or null to check it.

Related

Gorm - how to access nullable fields when using pointers?

I'm new to Go and still learning about optional struct fields.
I'm looking at the Gorm manual page where it gives an example of using pointers to indicate nullable fields (here)
If I strip down the example given so that it contains only a mandatory field and an optional field I'm left with something like this:
https://play.golang.com/p/lOLGWNVvq1l :
package main
import "fmt"
type User struct {
Name string
Email *string
}
func main() {
user := User{Name: "Example"}
// cannot use "example#example.com" (untyped string constant) as *string value in assignment
user.Email = "example#example.com"
// invalid operation: user.Email == "example#example.com" (mismatched types *string and untyped string)
if user.Email == "example#example.com" {
fmt.Println("foo")
}
}
How would I perform operations on a record that I've just retrieved from the database?
I need to be able to check if a nullable field is set to some value. I also can't assign a value to it.
One approach that I've thought of is to use some sort of wrapping function to try and make things safer, like at https://play.golang.com/p/4YlpPwaXMkm where I have:
func UnwrapString(x *string) string {
if x != nil {
return *x
}
return ""
}
func WrapString(x string) *string {
return &x
}
func main() {
user := User{Name: "Example"}
// can safely set an optional value that is currently null
if UnwrapString(user.Email) == "example#example.com" {
fmt.Println("hello world")
}
// can safely set a value if the existing Email is null
user.Email = WrapString("example#example.com")
// only safe because the value is set
if *user.Email == "example#example.com" {
fmt.Println("hello world")
}
}
Working with nullable fields in Gorm seems like such a basic and common thing that I don't expect to have to DIY. What's the idiomatic Gorm way to do this?
An idiomatic way to check if a field is non-nil, and if so, compare the value:
if user.Email != nil && *user.Email == "example#example.com" {
fmt.Println("foo")
}
The reason this works, even if user.Email is nil (and you get no nil-pointer dereference panic), is because Go has short circuit evaluation, meaning if the first comparison falls through in this AND statement, the second won't be evaluated, because there is no way this AND statement will ever be true if the first value is already false.
To do inline pointer assignments, the function you wrote is what I would do as well:
func StrPtr(s string) *string {
return &s
}
And you could then do:
user.Email = StrPtr("example#example.com")

Unable to understand the certain operator in Swift

I have been changing some SWIFT code into OBJECTIVE-C, and I am stuck at certain part of the code, where I am unable to understand if it is a condition or something else.
Following is the code and I am stuck on 9th line stating :
if let channel1Buffer = buffer.floatChannelData?[0]
What I do not understand here is the above if condition is checking if "buffer.floatChannelData" is null, and then proceeding to get the first index, or is it something else.
input.installTap(onBus: 0, bufferSize:4096, format:format, block: { [weak self] buffer, when in
guard let this = self else {
return
}
print("Buffer Float Channel Data: ", buffer.floatChannelData as Any);
**if let channel1Buffer = buffer.floatChannelData?[0]** {
print("channel1Buffer: ", channel1Buffer);
/// encode PCM to mp3
let frameLength = Int32(buffer.frameLength) / 2;
print("frameLength: ", frameLength);
let bytesWritten = lame_encode_buffer_interleaved_ieee_float(this.lame, channel1Buffer, frameLength, this.mp3buf, 4096);
// `bytesWritten` bytes stored in this.mp3buf now mp3-encoded
print("\(bytesWritten) encoded");
this.file.append(this.mp3buf, length: Int(bytesWritten));
// #TODO: send data, better to pass into separate queue for processing
}
})
Let's take it part by part - buffer.floatChannelData?[0]
buffer has property named floatChannelData which is optional so it has ? at the end. then it takes that optional which accepts subscription [0] which also returns optional value. So it continues inside {} only if floatChannelData is not nil AND it's first value is not nil
Your Objc should look like
float *const *channelData = [buffer floatChannelData];
if (channelData) {
float *channel1Buffer = channelData[0]; //this might crash if channelData is empty
...
The line tries to assign the variable channel1Buffer the value of buffer.floatChannelData[0], and the code within {} is only executed if that assignment is successful. It may for instance fail if buffer.floatChannelData is nil or buffer.floatChannelData[0] is nil.

Why use double parentheses in init methods, or is 1 == (1)?

What do parentheses do when evaluating some meaning?
I have faced this in code, when something is checked and they use
if ( (some condition that returns 1) )
{
code
}
So my question is, does this evaluate to true? I would think that it is always false since (1) does not return anything?
Edit: clarification, question is why double parenthesis in if? I know that 1 is true.
The additional parentheses are used when an assignment is used for its truth value. They allow the compiler to distinguish between
if ((var = expr))
which signals intentional combination of assignment and truth value test, and
if (var = expr)
as an unintentional misspelling of if (var == expr).
The convention, carried over from C and C++, is for the compilers to warn on if (var = expr) as a possible misspelling of if (var == expr). They don't warn on if ((var = expr)), because the extra set of parentheses signals to the compiler that the assignment was intended. As rob mayoff explains, clang has a special case not to warn for certain assignments to self, but for many coders the habit remained.
As others said, the generated code is exactly the same with and without the extra parens.
If you write,
if (self = [super init]) { // Warning
// ...
}
The compiler will give you a warning, because it thinks you might have mistyped = as ==. If you add a second set of parentheses, the warning goes away.
if ((self = [super init])) { // No warning
// ...
}
So the extra parentheses are there to make typos less likely. The parentheses do not change the value of the expression.
In general 0 equates to false, NOT 0 to true.
This link explains bool in objective-c: http://www.mindsizzlers.com/2010/04/objective-c-and-the-properties-of-bool/
true and false value of bool and int
boolean value of false is equivalent to the int value of 0.
boolean value of true is equivalent to the int value of non-zero (e.g. 1, 10, 3000, etc)
For example, consider an example of C code below:
bool bValue;
int nValue;
bValue = true;
nValue = 1;
if (bValue == nValue) {
printf("bValue and nValue are the same!\n");
}
// output: bValue and nValue are the same!
Wrapped with multiple parenthesis:
The following two snippets returns exactly the same results.
if ((((((((((((((((((((1)))))))))))))))))))) {
printf("Hello World!\n");
}
returns the same result as:
if (1) {
printf("Hello World!\n");
}
Expression in if statement
Within your given if statement, you must have an expression that resolves to either true or false value. Please refer to this page for example of expression.

Expected expression before 'unsigned' ->Objective C

m_cAppIdMap is an object of a dictionary.
I want to iterate through the dictionary and to ind and remove the value pEvent.wTimerId is an unsigned short integer that is stored as key in the dictionary.
if(unsigned short* key in m_cAppIdMap) //error:Expected expression before 'unsigned'
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
I am getting an error when i try to iterate through the loop.
EDITED
-(BOOL)KillTimer:(unsigned short)wTimerId
{
stRs232Timer* pEvent;
BOOL bReturn=FALSE;
theLock = [[NSLock alloc]init];
if ([theLock tryLock]) {
// if ( m_cAppIdMap.Lookup(wTimerId,pEvent) )
// {
// (void)findAndRemoveEvent(pEvent); // remove from event queue
// (void)m_cAppIdMap.RemoveKey(wTimerId); // remove from app map
for(wTimerId in m_cAppIdMap)
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
[theLock unlock];
}
return bReturn;
}
I am getting error in this code 'selector element does not have a valid object type' . I need to search for wTimerId(key) in the m_cAppIdMap. Is it what i'm doing is correct.The commented lines above the for loop is the implementation of the same code in cpp. I coud not make the same logic over here in Objective C.
I think you meant to use for rather than if. Additionally, the fast enumeration syntax
for (x in y) can only be used on objects that implement the NSFastEnumeration protocol—typically NSArray. It looks like you're using C arrays, so this syntax won't work anyway.
you meant to write for (VARIABLE in CONTAINER) {...} -- but your sample uses if, not for.
side note: it is an error to mutate the collections you iterate over during the iteration.

NSArray in if statement strange behaviour

i have the following two pieces of code which i think should be identical
int temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state];
if (temp > 0)
{
NSLog(#"TEST: %d",temp);
}
if ([[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state] > 0)
{
NSLog(#"TEST: %d",temp);
}
state is just an int in the objects in the array with accessor like:
#property (assign)int state;
but when state is negative, the first version works (no output), but the second version outputs (for example) "TEST: -4" (?!)
is there any obvious reason why they might be different?
Since -objectAtIndex: returns an id, the compiler will not be able to know what -state should return. If you did not import the header that declares state first, or if the property state has ambiguous declaration (e.g. another class has declared #property(retain) id state before your class is imported), then the compiler may infer a wrong type for -state.
If it infers id, for instance, as all pointers are nonnegative, -4 will be implicitly viewed as 0xFFFFFFFC, thus the > 0 condition passes.
But for code 1, you have specified that temp is an int, so even if the return value of the call is 0xFFFFFFFC, it will be cast back to a signed value (-4), hence the condition fails.
The safest approach is to specify the type of -objectAtIndex:, i.e.
Foo* obj = [[myArray objectAtIndex:iIndex] objectAtIndex:jIndex];
if (obj.state > 0) {
...
I I understand it right, and the two if's are NOT in the same method, then the second one prints an unassigned variable. the fix should go like this:
if ((temp = [[[myArray objectAtIndex:iIndex] objectAtIndex:jIndex] state]) > 0)
{
NSLog(#"TEST: %d",temp);
}