![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/images/you_are_here_red.gif)
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/default/files/beta-site.gif)
Newton Q & A: Ask the Llama
Q I was wondering why my autopart is taking up so much heap space after it's installed. The InstallScript and RemoveScript are quite small:
constant kGlobalDataSym := '|Globals:MYSIG|; InstallScript := func(partFrame, removeFrame) begin if NOT GetGlobals().(kGlobalDataSym) exists then GetGlobals().(EnsureInternal(kGlobalDataSym)) := {}; GetGlobals().(kGlobalDataSym).(EnsureInternal(kAppSymbol)) := GetLayout("MyTool.t"); end; RemoveScript := func(removeFrame) begin local NGP := GetGlobals().(kGlobalDataSym); if hasSlot(NGP, kAppSymbol) then RemoveSlot(NGP, kAppSymbol); end;The template in MyTool.t is only a simple proto with a few slots in the base view: a symbol, viewBounds, viewFlags, viewJustify, viewFormat, viewClickScript, and three methods. When installed, the autopart takes up about 640 bytes of heap space. Is this because of the physical representation in the extras drawer?
A A minimal autopart with no RemoveScript will take up about 240 bytes. One with a RemoveScript will take 350 bytes or more, depending on the size of the RemoveScript. The 240 bytes are used by the system to keep track of the package. This includes the name, the extras drawer entry, and any symbols that you passed to EnsureInternal.
Trying your code showed that it used 444 bytes. Of course, we don't have the MyTool.t layout in the package, but that doesn't matter since you don't call EnsureInternal on the layout. Using 444 bytes isn't out of line considering the minimum size of an autopart.
Of course, you could make your code a little smaller. For example, in your RemoveScript you check that kGlobalDataSym is a known global variable. This isn't required, since RemoveSlot will do the right thing if kAppSymbol isn't in your global data frame. Note that you may want to make sure your global data frame exists:
RemoveScript := func(removeFrame) RemoveSlot(GetGlobalVar(kGlobalDataSym), kAppSymbol);Also, you use GetGlobals, which is a deprecated function for Newton OS 2.0. You should be using GetGlobalVar, DefGlobalVar, and UnDefGlobalVar.
Q I'm using a protoPeoplePicker in Newton OS 2.0 and it keeps showing an "Untitled Person." Is this an opportunity to create someone or is there really a gremlin inside the machine?
A There are only two reasons for the appearance of the "Untitled Person" entry. One is that you mistakenly entered that person in your card file, which can happen if you edit an entry and accidentally erase the name. The more likely reason is that this is your hacking Newton device. If so, you probably didn't go through the Setup application and set an owner. "Untitled Person" is the default owner of the machine. We recommend that you set up a default hacking MessagePad, back it up using NBU (Newton Backup Utility), and then use that backup to create development units.
Q I've read the article in Newton Technology Journal on package freezing and I'm still a bit confused. Can you confirm that the following questions and answers are right?
- Does my form part still have a slot in the root after being frozen? No.
- Is the RemoveScript called when it's frozen? Yes.
- Is the InstallScript called when it's unfrozen? Yes.
- Can I prevent freezing/unfreezing? No.
- Can I get a message indicating freezing vs. pulling the card? No.
- What happens when the user tries to put away an item routed to a frozen application? A "can't find application" error.
Q There are times in my application when I want to perform the same operation on a whole bunch of soup entries. Right now the Xmit form of the calls takes quite a while and results in a lot of messages flying around. Is there a better way to do this?
A Yes. You can use nil for the argument that tells the system which application is performing the change. This tells the system not to transmit the change notification. Then you can use XmitSoupChange to send a whatThe notification. This will inform other applications that something changed, but not give specifics of the change. As an example, here's a code snippet to remove all entries in a given cursor:
// create a function we can map over local myRemoveFunction := func(entry) EntryRemoveFromSoupXmit(entry, nil); // remove the entries MapCursor(removeCursor, myRemoveFunction); // now inform registered soups that something has changed XmitSoupChange(kSoupName, kAppSymbol, 'whatThe, nil);Q We're having a problem with compiled NewtonScript code. We have a function that takes an int as a parameter. We use the int type indicator in the function definition. However, it's possible for the parameter to be nil. For compiled code this results in a type mismatch error. Is there a workaround for this?
A There is a way to work around this problem; however, you'll pay a performance penalty. It's much better to redesign your API to accept only integers. If you do want a workaround, you can use the type-checking functions to make sure the parameter is an integer before you use it like one. Here's some code that will work:
func native(x) begin local int intx; if IsInteger(x) then begin // now you can use intx and it'll be faster than using x intx := x; end else begin // do whatever else is appropriate; it isn't an integer ... end; end;Q In our application we sometimes have to show the user a big error message, which unfortunately is too large for the Notify mechanism. Is there a way we can add a button to the Notify slip? If not, is there some other mechanism we can use?
A The answer is simple: just don't let your user generate such a large error. But seriously, there is no way to modify the slip that comes up from Notify. Here are two ways to solve your problem:
- Have the Notify message tell the user to click on some user interface element in your application for more information. This is the recommended solution.
- Instead of Notify, use a dialog to inform the user of the error. Since you control the dialog, you control which buttons are in it. You could set up such a dialog with AsyncConfirm.
aView := {_proto: anotherView, // more slots...} anotherView := {_proto: protoFloater, // more slots...}Is there a function I could call that would take aView and return true if it's an instance of protoFloater?
A There is no built-in function that will do this, but it's relatively simple to write:
func(frame, prot) begin while (frame AND (frame <> prot)) frame := frame._proto; return (frame <> nil) end;Q How do I define a pickerDef column to be "lastname, firstname" in a single column?
A You can specify a Get method in your pickerDef and modify your columns appropriately. As an example, take a look at the protoListPicker sample on the Newton Developer CD. One of the subsamples is called ListPickerSoup. The default is to display the first item in the first column and the second item in the second column. The original pickerDef is defined as follows (from pickerDef.f):
DefConst('kMyBasicSoupDataDef, { _proto: protoNameRefDataDef, // required validationFrame: nil, // used if editing is supported name: "Random Data ", // name at top left of picker if // foldersTabs are present HitItem: func(tapInfo, context) begin context:ThingChosen(tapInfo); end, });Then in myListPicker in the listPickerSoup.t layout file, the pickerDef slot is:
{_proto: kMyBasicSoupDataDef, // defined in the pickerDef.f file class: 'nameRef, // always include columns: [ // Column 1 { fieldPath: 'first, // field to display in column tapWidth: 100, // width for checkbox & name combined, // offset from the right margin doRowHilite: true, }, // Column 2 { fieldPath: 'second, // field to display in column tapWidth: 0, // width from preceding column to // right bounds doRowHilite: true, }, ], }To modify this sample to show one column in the format "second, first", you would add the following Get method to kMyBasicSoupDataDef:
Get: func(object, fieldPath, format) begin if fieldPath = 'second AND (format = 'text OR format = 'sortText) then begin local realData := EntryFromObj(object); if realData then // format is "second, first" return (realData.second & ", " & realData.first); else return "- -"; end else inherited:?Get(object, fieldPath, format); endThis Get method will return the correct string for a column that displays the slot 'second. It will also sort on a string that's in the format "second, first".
The other thing you need to do is modify the columns definition. Simply remove the first column, so that the pickerDef in myListPicker looks like this:
{_proto: kMyBasicSoupDataDef, // defined in the pickerDef.f file class: 'nameRef, // always include columns: [ // Column 2 { fieldPath: 'second, // slot to display in column tapWidth: 0, // width from preceding column to // right bounds doRowHilite: true, }, ], }Q I have a pick list that takes quite a while to create. I'd like to use a weak array so that I don't have to keep creating the list. That way I get garbage collection for free. But I don't want to make the array "weak" until after the pick list has been opened by the picker so that items don't accidentally get garbage collected. How do I turn a regular array into a weak array? Or will this work at all?
A You can't turn a regular array into a weak array; an array is one or the other. But using a weak array should work, with these minor modifications to your code: Create a slot in your picker (say myWeakArray) and initialize it to a weak array. Create your regular array of pick items as usual. Let the user pop up the picker; then in either the pickCancelledScript or the pickActionScript, set the first element of myWeakArray to the array of list items. Next time you want to construct the pick list, check for the first element of myWeakArray. If it exists, you have your pick list; if not, create a new one.
Q I'm using one of the newt name views to select a name. Whenever the people picker comes up, it's viewing "All Names." How can I programmatically change the default folder used by the picker?
A You need to change the Picker method of the newt name flavor as follows:
Picker: func() protoPeoplePopup:New('|nameRef.people|, nil, self, {labelsFilter: <symbol-for-desired-folder>});The final argument to the New method is a frame of options. Each slot/value pair is used to set up a slot/value pair in the protoPeoplePicker. So grab the symbol for the default folder that you want and set the labelsFilter of the protoPeoplePopup.
Q What is the path to true enlightenment and wisdom?
A Simple: Buy and read all the books that claim to show you such a path. As you read, make a list of the major points. Take that list, cross off the contradictions, take the inverse of what's left, and then get a life. Alternatively, go and code another thousand lines of NewtonScript.
The llama is the unofficial mascot of the Developer Technical Support group in Apple's Newton Systems Group. Send your Newton-related questions to dr.llama@newton.apple.com. The first time we use a question from you, we'll send you a T-shirt.*
Thanks to jXopher Bell, Henry Cate, Bob Ebert, David Fedor, Ryan Robertson, Jim Schram, Maurice Sharp, Bruce Thompson, and Scott Wright for these answers.*
If you need more answers, take a look at the Newton developer Web page, at http://www.devworld.apple.com/dev/newtondev.shtml.*
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/img/search_text.gif)
- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine