objective-c compile error: Initializing NSString with an expression of incompatible..

Discussion in 'Mac Programming' started by johnmerlino, Oct 22, 2011.

  1. johnmerlino macrumors member

    Joined:
    Oct 22, 2011
    #1
    Hey all,

    I get following error:

    objective-c compile error: Initializing NSString with an expression of incompatible type void.

    Basically my speak instance method should return a string and then I want to output that string as part of a message:

    Code:
        Animal *animal = [[Animal alloc] init];
        NSString *speak = [animal speak];
        NSLog(@"The animal says %@", speak);
    
    Code:
    @implementation Animal
    
    - (id)init
    {
        self = [super init];
        if (self) {
            // Initialization code here.
        }
        
        return self;
    }
    
    - (void)dealloc
    {
        [super dealloc];
    }
    
    - (void)speak{
        NSLog(@"Hi there");
    }
    
    @end
    
    Here's basically my problem. Since objective-c uses the NNString class as its string implementation, I am not sure how to return it as the value of speak.

    thanks for response
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
  3. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    Well, you declared a "speak" method returning void, and the implementation of that void method returns nothing. You'd need to declare it as returning an NSString*, and change the implementation to return an NSString*, for example @"Hi there"
     
  4. johnmerlino thread starter macrumors member

    Joined:
    Oct 22, 2011
    #4
    I already tried that. It says NSString cannot be returned by value.
     
  5. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #5
    NSString *, not bare NSString. You only deal with objects via pointers in Objective-C. Where are you learning from, and what have you read so far?

    -Lee
     
  6. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #6
    It is essential for any programming effort to read and write very precisely. I never said you should write a method that returns an NSString. I said you should write a method that returns an NSString*.

    You never, ever, ever have any variables, parameters, return values, or expressions of type NSObject or any subclass of NSObject, like NSString. You _always_ use pointers, like NSObject* or NSString*.
     
  7. johnmerlino thread starter macrumors member

    Joined:
    Oct 22, 2011
    #7
    Got it working:

    Code:
        Animal *animal = [[Animal alloc] init];
        [animal setName:(NSString*) @"Dog"];
        NSLog(@"The name of the animal is %@", [animal name]);
    
    @interface Animal : NSObject {
    @private
        NSString *name;
        NSString *diet;
        NSString *habitat;
        NSDate *originDate;
    }
    
    - (NSString*) name;
    - (void) setName:(NSString*) name;
    
    @end
    
    
    @implementation Animal
    - (void)setName:(NSString*) animalName{
        name = animalName;
    }
    
    - (NSString*)name{ 
        return name;
    }
    
     
  8. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    Careful with casts. Most casts are either unnecessary, or wrong. In (NSString*) @"Dog", the cast is unnecessary, because @"Dog" is a special syntax for an NSString* with the contents "Dog".
     
  9. johnmerlino thread starter macrumors member

    Joined:
    Oct 22, 2011
    #9

    thanks for response, to make it easier I tried using the accessor method creation:
    Code:
    @interface Animal : NSObject { 
    @private
        NSString *diet;
    }
    @property NSString* diet;
    
    
    @implementation Animal
    @synthesize diet;
    
    But this line gives a warning:
    Code:
    @property NSString* diet;
    
    "default property attribute assign not appropriate for non-gc object"

    That said, it does compile. Im just wondering why it's giving me that warning.
     
  10. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #10
    Whenever you get a warning, you better find out why. A "warning" is the compiler telling you that you are doing something that is legal according to the rules of the language, but likely to get you into trouble.

    You'll have to read up on memory management first. Your setName method didn't take ownership of the object, which means if the caller releases the object, you will get a crash. Since that is done in code you explicitely wrote, the compiler gives you what you want. With the @property syntax, the default is exactly the same, "assign". But since you didn't write anything, the compiler tells you that this is most likely wrong, and "retain" is probably what you want.
     
  11. johnmerlino thread starter macrumors member

    Joined:
    Oct 22, 2011
    #11
    What you are saying is that using @property to declare setter/getter methods will default the method body to an assign. In essence, the setter method will just do a simple assignment of the instance variable to the new value. The problem is then that since Objective-C objects use reference counting, and therefore by not retaining the object, there is a chance that the string could be deallocated while it is still in use. Then the solution would be to retain the new value in the setter method:

    Code:
    @synthesize diet;
    - (void)setDiet:(NSString*) d{
        [d retain];
        [d release];
        diet = d;
    }
    
    Then this raises a new warning:
    "writable atomic property 'diet' cannot pair a synthesized setter/getter with a user defined setter/getter. But then again if I don't explicitly state that I want to maintain a reference of the object, and that I must release it before it will be deallocated, I will get that warning ""default property attribute assign not appropriate for non-gc object".

    So I see a catch-22 here. @synthesize cannot be used with objects, it appears.
     
  12. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #12
    You need to look more carefully at the syntax for declaring properties. There are attribute names you should use, such as copy, retain, nonatomic. These attributes go on the @property declaration, not the @synthesize. Read the Declared Properties section of the language reference guide.


    What book or tutorial are you learning Objective-C from? Please be specific. Whatever it is, you should probably read through the Objective-C Primer, too.
     
  13. johnmerlino thread starter macrumors member

    Joined:
    Oct 22, 2011
    #13
    thanks for all responses, I will look into all recommendations.
     

Share This Page