PDA

View Full Version : NSTextField to display NSMutableString




larswik
Jul 4, 2011, 05:24 PM
Hello, This code works when I test it.

NSString *tempString;
NSMutableString *valueAppender;

- (IBAction)ONE:(id)sender {
tempString = @"1";
[mathField setStringValue: tempString];

I then tried to swap out to an NSMutableString 'valueAppender' for this next code I get a warning "Incompatible pointer types assigning to 'NSMutableString *' from 'NSString *'"


- (IBAction)ONE:(id)sender {
valueAppender = @"1";
[mathField setStringValue: valueAppender];
}

I understand the error message and I am looking through the Apple documentation in the methods to find a method for a NSMutableString. I thought about trying to assign the NSMutableString to a NSString and have the text field then display the string?

Thanks,

-Lars



mfram
Jul 4, 2011, 05:59 PM
MutableString is a subclass of String though. You might be trying to set the wrong item.

jiminaus
Jul 4, 2011, 06:24 PM
"Incompatible pointer types assigning to 'NSMutableString *' from 'NSString *'"


Read the error message carefully.

larswik
Jul 4, 2011, 10:22 PM
Incompatible pointer types would lead me to believe that the pointer to the NSMutableString object. Is different then a standard pointer to a NSString object. I tried code like this but I also get an error at runtime.

- (IBAction)ONE:(id)sender {
[valueAppender setString: @"1"];
[mathField setStringValue: valueAppender];

mathField is just an NSTextField. SetSrtingValue is a valid method in that is listed for NSTextField class. But valueAppender is a NSMutableString and not just an NSString. That is the only thing that I see that can cause the problem. Is my thinking wrong?

Here is the error message that pops up with the degugger

"*** Assertion failure in -[NSTextFieldCell _objectValue:forString:errorDescription:], /SourceCache/AppKit/AppKit-1038.35/AppKit.subproj/NSCell.m:1531
2011-07-04 20:15:32.028 Xp Calc2[1715:903] Invalid parameter not satisfying: aString != nil"

jiminaus
Jul 4, 2011, 10:43 PM
You're reading the error message around the wrong way. The error is about assigning from NSString* to NSMutableString*, not the other way around.

You've got an NSString* that you're trying to assign to an NSMutableString*. This cannot be done safely, so the compiler is flagging in the error.

The problem was with this line:

valueAppender = @"1";


As you know @"1" results in an NSString*. But valueAppender is an NSMutableString* variable. Now do you see the error?


Your last post is more on track. It's okay, assuming you've alloc'ed and init'ed valueAppender. If you haven't, you're sending setString: to nil, which isn't going to do anything. And on second reading of your reply, you indeed haven't because NSTextField is complaining about it being null.

The general way to alloc and init an NSMutableString from another string is to use either [[NSMutableString alloc] initWithString:@"abc"] or [@"abc" mutableCopy].

However, you could just alloc and init an NSMutableString object in this classes' init, and then your code would work as posted.


BTW It is perfectly fine to use an object of a subclass instead of a class, thanks to the Liskov substitution principle (http://en.wikipedia.org/wiki/Liskov_substitution_principle). But you cannot go the other way and substitute an object of a superclass for a class.

larswik
Jul 5, 2011, 02:42 AM
Thanks Jim, I see what is happening now. I have not alloc and init the NSMutableString. I was watching the Lynda.com video on learning objective-C the video said to the effect that if I did not write the class then I should not release it. I think he used NARC as long as I have not used New, Alloc, Retain or Copy the system would handle the memory management.

So for NSString *tempString; I did not alloc or init (instantiate) it. But for NSMutableString I should?

I was getting a nil response and now I know why, thanks.

Is there a way I can know if I am supposed to instantiate a system class, or if it handles it's self? I looked in the reference and could not see examples.

Thanks again Jim, I would have been staring at that one the whole night.

-Lars

balamw
Jul 5, 2011, 05:45 AM
Just my $0.02, IMHO this is part of the unlearning of what you have learned in procedural code that makes me lean towards folks learning Objective-C first.

You should always lean towards using alloc init (or equivalent) for objects, but your procedural instincts say assign with =.

B

jiminaus
Jul 5, 2011, 06:44 AM
... said to the effect that if I did not write the class then I should not release it.

This is wrong. The rules of memory management apply regardless of whether you've written the class or not.

I think he used NARC as long as I have not used New, Alloc, Retain or Copy the system would handle the memory management.

This is right. I've never seen the NARC acronym, but it works. You are responsible for sending a release message to an object returned by any of these methods. Sending an autorelease message counts as sending a release message.

You must not send a release message to an object returned by any other methods.

Print out the Basic Memory Management Rules (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH), read them, re-read them often, keep them close by, and refer to them often; until they become instinct.

So for NSString *tempString; I did not alloc or init (instantiate) it. But for NSMutableString I should?

I was getting a nil response and now I know why, thanks.

Is there a way I can know if I am supposed to instantiate a system class, or if it handles it's self? I looked in the reference and could not see examples.

You don't have an object unless you obtain one by either alloc'ing and init'ing one, or by getting a pointer to one from another variable or the result of a method.

When you're considering instance variables, sometimes you'll need to think about the greater lifetime of an object because an instance variable might be assigned in one method and then later used in another.

NSString is slightly special in that there's special syntax them. @"abc" is pretty much equivalent to [NSString stringWithUTF8String:"abc"]. Notice it's not of the NARC methods, so you're not responsible for releasing the object obtained using the @"abc" syntax. But it does result in a pointer to an NSString object.


(An aside: Technically the memory managent rules say you're required to retain the object obtained using the @"abc" syntax if you want to keep around an pointer to it, in for example an instance variable. But most people don't do that, and so far the runtime has supported that, and probably always will.)

PatrickCocoa
Jul 5, 2011, 09:26 AM
This is wrong. The rules of memory management apply regardless of whether you've written the class or not.

[snip]

Print out the Basic Memory Management Rules (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH), read them, re-read them often, keep them close by, and refer to them often; until they become instinct.


The Basic Memory Management rules are well-defined. It seems that that would be a topic amenable to computer solution at the compiler level. What would your reaction be to a compiler that automatically counted memory references and did the retain/release for you?

This would be at the compiler level, not garbage collection done at run time.

Catfish_Man
Jul 5, 2011, 11:53 AM
The Basic Memory Management rules are well-defined. It seems that that would be a topic amenable to computer solution at the compiler level. What would your reaction be to a compiler that automatically counted memory references and did the retain/release for you?

This would be at the compiler level, not garbage collection done at run time.

What a coincidence... http://clang.llvm.org/docs/AutomaticReferenceCounting.html

larswik
Jul 5, 2011, 04:31 PM
There is SOOOO much to learn in Objc-C and remember. I am amazed people can pick up books and try to learn it at home in their spar time. If I don't do little fun experiments as I learn to help me retain what I learn I would forget.

balamw- I am happy I went with C and then back to Object-C. I don't have to worry about learning an If statement while learning what objects are as so on. The last day of my Pascal class the instructor said he hoped people would take his Java class next semester. He said that even though Object oriented programming is a different way of thinking, Object's are still filled with procedural code.

Jim - I will read Memory reference. My brain is on overload reading and watching videos and then having what I thought I just learned corrected on this forum :) You wrote this line of code
@"abc" is pretty much equivalent to [NSString stringWithUTF8String:"abc"].

This will create an object with a pointer? Is it some default pointer that gets created. I thought you had to define the variable pointer like NSString *ptr ?


If I ever figure this out Objective - C I am going to make a program to teach Objective - C Programming. Have it be a hands on with graphical representations of '-(void)', 'NSString' and so on located in different bins. Then a question saying " Create an object that places the string "Hello World" in memory". I would then open my class bin and drag out the graphical representation of an NSString class. Then in my variable bin pull out a pointer and rename it. Then from the memory bin I pull out an Alloc. Then from a method bin I would pull out a graphical representation of a Method that works with that class like initWithString. Then type in Hello World and press the execute button to see if it works, or give a clue as to why it did not.

Then as you keep learning you can download more moduals online to build up the library (bins) as you grow.

Not the program Alice, but where you look at code and not dance astronauts.

Someone should make an app for this :)

-Lars

balamw
Jul 5, 2011, 05:52 PM
There is SOOOO much to learn in Objc-C and remember.

There's an anecdote at the beginning of Cocoa in a Nutshell (http://oreilly.com/catalog/9780596004620) that bears repeating.

It's practically impossible to know Cocoa inside and out. There was once a discussion between two programmers about Cocoa's large APIs: one was a veteran Perl programmer, the other a Cocoa programmer. The Perl programmer grumbled about the intimidating and verbose Cocoa APIs, saying there was simply too much to remember. Bemused, the Cocoa programmer retorted: “You don't remember Cocoa; you look it up!”


balamw- I am happy I went with C and then back to Object-C. I don't have to worry about learning an If statement while learning what objects are as so on. The last day of my Pascal class the instructor said he hoped people would take his Java class next semester. He said that even though Object oriented programming is a different way of thinking, Object's are still filled with procedural code.

Clearly everyone learns and retains things differently.

I first learned BASIC, Pascal and some C back in the 8-bit days, so I can't know for sure how things would be if I hadn't learned procedural, linear code first.

However, I can say that I've gone through the unlearning (a.k.a. retraining) process twice. First with Agilent VEE (a visual programming language (http://en.wikipedia.org/wiki/Visual_programming_language) that was my first introduction to multi-threaded programming, where code can exectute in highly non-linear paths, and then again with Objective-C. All my previous OOP-y work in C++ and Java was informal didn't really test my perception of objects as fundamentally different than fancy structures.

In both cases VEE and Objective-C (and to some extent MATLAB) I often see folks getting in deep trouble because they insist on trying to make it fit their existing mindset instead of letting go and learning how to use it for what it is.

Since learning some Objective-C I've also gone back to some C++ with STL and find that my code is much more "objectified" now.

B

jiminaus
Jul 5, 2011, 10:17 PM
This will create an object with a pointer? Is it some default pointer that gets created. I thought you had to define the variable pointer like NSString *ptr ?


A variable is just a box to put values into. A pointer to an object exists, remember a pointer is just a memory address, regardless of it being stored in a variable.

Take the example of integers and consider the following snippet of code.
int x = 10;
int y = 5;
int a = 2 * (x + y);

When the expression on the last line is being executed, after x is added to y, the resulting 15 exists. It's not stored in any variable, but it exists (likely in a CPU register). Only after 15 is multiplied by 2, is the resulting 30 stored in the variable a.

Similarly with @"abc". The result of executing @"abc" is a pointer to an NSString object containing the text "abc". What you do with that pointer is up to you. You can store in a variable, you can pass it as an argument to a function or a message, you can even sent it a message like so.

[@"abc"
writeToFile:[@"~/Desktop/abc" stringByExpandingTildeInPath]
atomically:NO
encoding:NSUTF8StringEncoding
error:NULL]; // It's actually bad to pass NULL here, don't copy this

Sydde
Jul 6, 2011, 09:51 AM
When the compiler sees something like

x = "abc";

it sees a constant value that it cannot easily embed into a code stream, so it puts it into a specific area reserved for constants, globals and statics and generates code that accesses that location (on some platforms, like PPC, this is even true for a value like 2.5 which cannot be embedded into the code stream). When you change the constant to @"abc", exactly the same thing happens, except some additional stuff is added so that the constant value will serve as an instance of a NSString. Because the reserved location is not in the dynamic heap area, retain and release messages will have no effect.

And yes, "abc" constitutes 4 bytes (with \0) so it could in fact easily be embedded into to code stream, but I think most compilers will not attempt an optimization at that level, and rightly so.

larswik
Jul 6, 2011, 01:19 PM
balamw - Lots of learned and unlearned languages. I think I am safe to start to unlearning Pascal :)


Jim - So funny you should mention this.
When the expression on the last line is being executed, after x is added to y, the resulting 15 exists. It's not stored in any variable, but it exists (likely in a CPU register). Only after 15 is multiplied by 2, is the resulting 30 stored in the variable a.

In my Pascal I got into it with my teacher and he thought I was nuts or did not get it. I had a local variable integer in a function like int a;. When the function returned control back to Main it the said something like total = a; I argued that when the function ended it destroyed that local int a variable so the the code snippet total = a; would not work. because 'a' no longer existed. He did not get what I was saying. Your 'Computer Register' answered that question.

I understand that all variables have an address and storage space. In C '&' accessed the address and '*' accessed the contents of that address. I used this a lot with functions to swap out values in memory locations.


Sydde - Thanks for the detailed explanation.

-Lars

balamw
Jul 6, 2011, 04:35 PM
balamw - Lots of learned and unlearned languages. I think I am safe to start to unlearning Pascal :)

:)

The danger for me is actually the closer languages.

Perhaps it's just me, but when I first learned C all my C code looked like Pascal, and similarly for C++ all my C++ looked like C. :p

Learning to let go and use higher level Objective-C/Cocoa instead of rolling your own and relying on your fundamental C concepts is the hard part.

At least it was for me, YMMV.

B

jiminaus
Jul 7, 2011, 01:10 AM
In my Pascal I got into it with my teacher and he thought I was nuts or did not get it. I had a local variable integer in a function like int a;. When the function returned control back to Main it the said something like total = a; I argued that when the function ended it destroyed that local int a variable so the the code snippet total = a; would not work. because 'a' no longer existed. He did not get what I was saying. Your 'Computer Register' answered that question.

If you can get your hands on one of the many Computer Architecture and Organization type books, it will fill in much of the picture for you.

larswik
Jul 7, 2011, 03:14 AM
balamw - The reason I got into programming last year was because I wanted to build a motion control rig for my camera. I shoot a lot of TV commercials and lots of restaurants. I wanted a small motion control rig that I could fly a camera over the food to get different looking shots. My friend Mike is an electronics engineer and designs custom circuit boards for printers to drive stepper motors and so on. He said if I learn programming he would build me the hardware. C seemed to be the main language people used to program for this type of stuff. I would think you could use Objective - C to build a GUI interface that would work to pull this off?

Anyways, that is years off still and many smaller projects to do on the way.

Jim - Those books might still be beyond my understanding but I will look into it.

-Lars

PatrickCocoa
Jul 7, 2011, 07:37 AM
balamw - The reason I got into programming last year was because I wanted to build a motion control rig for my camera. I shoot a lot of TV commercials and lots of restaurants. I wanted a small motion control rig that I could fly a camera over the food to get different looking shots. My friend Mike is an electronics engineer and designs custom circuit boards for printers to drive stepper motors and so on. He said if I learn programming he would build me the hardware.
-Lars

That sounds pretty cool. Keep plugging away at the programming!