WebSession.Quit

For years we’ve been doing some basic checking in the WebSession.Open event of our Xojo web apps. First, we check to see how many open sessions we have and if it’s over a preset number.  The second check we do is to see how many open sessions we have for the current IP address. We set it to something low like 10 because when some joker decided a few years ago to prove that Xojo web apps suck. He opened up our training app, and then hit refresh 150 times and then complained about how unresponsive the app was (thus proving his point that Xojo web apps suck, I guess).

In our apps, if either of those conditions is met we use a ShowURL to redirect to one of the webpages on our regular website to show the user that the app is either too busy or something bad happened. It’s worked decent enough that I’ve never revisited it until this past weekend when several users alerted me to the redirect never clearing. Since I couldn’t login to my own app I restarted the server and everything was fine again.

I tend to use a log file on my web apps to track certain conditions and this morning I added more information so I could track this more. I just happened to be monitoring the app (in my browser) when my session count spiked to around 50 in just a few seconds. Looking at the new information in the log file the IP addresses were all over the place.  An attack?  I dunno but it sure seemed like it.

Unfortunately, the session count didn’t go down immediately like I expected it too and, in fact, it didn’t go down even up to an hour later. I had over a hundred open sessions before it stopped (did Xojo Cloud security close the port?).

When that happened I started looking at code. Some of this code I hadn’t looked at in a year or more. Basically the code did the two checks in the WebSession.Open even and if the function returned true I immediately tried to call WebSession.Quit.

Guess what happens when you do that? If you guessed nothing you’d be wrong. It generates a Nil Object Exception first with the following stack trace:

Function WebSession._WaitingForSync() as boolean
Sub

WebPushHandler.CheckForChanges()

Sub _SessionShutdownThread.Event_Run()

And after that then it does nothing. The WebSession never quits – ever – until something kills the app.

My solution was to put a timer property into the Session and if I meets my quit conditions start the timer and in the action event (using AddHandler) quit the Session. Seems to work as expected now.

This is filed in Feedback <feedback://showreport?report_id=35794> and it appears that it’s been verified. There are some additional details on their response. They know why it’s happening at least. Let’s hope this one gets fixed sooner rather than later.

I’ve seen various people have issues with WebSession.Quit over the years. This might be the root cause of some of those.

Subclassing vs Extends vs Containers

Xojo is really powerful because it gives you multiple ways to create really powerful controls.  Today I’ll discuss subclassing, extends, and containers.

Subclassing

First, subclassing a control is really easy to do.  Create a new class and set the super to the control you are extending.  A great example of this is the Xojo ListBox.  In its raw form it’s powerful, but limited, in its functionality.  To have those awesome alternating row colors we subclass the ListBox and put our code in the CellBackgroundPaint event.

One of the things that people forget to do when subclassing the control is to repeat the events that that they are using.  Because I’ve used the CellBackgroundPaint event it’s not available to any instances of the class.  Sometimes this is desirable, but sometimes you want the control to still have those events.

The solution is simple.  Define a new event named CellBackgroundPaint and use the same properties and return value.  This means that you, the developer, can have the alternating colors in your listbox but also still have the opportunity to override those colors if you need them.

The other powerful thing about subclassing is that you can continue to subclass them all you want.  In one of our projects we have the following Listbox hierarchy:  ListBox -> AlternatingRowListbox -> CustomCellListbox -> RecordsetListbox.  Each one is still a Listbox, but each gets all of the events and properties of its supers so this means that the RecordsetListbox automatically gets the alternating rows even though it specializes in loading the listbox by using a Recordset.

Extends

Sometimes, though, you only want to add a single method to a class.  Creating a subclass to do this might be overkill, especially if you have to go back and and retrofit this change in a lot of places.  A good example of this the PopupMenu where you often have to set the text of the PopupMenu to some value.  The code is often like this:

for i as integer = 0 to pm.ListCount-1
   
   if pm.list(i) = sSomeValue then
      
      pm.ListIndex = i
      
      exit
      
   end
   
next

It’s not hard but after you’ve done this several dozen times you come to the realization that this should be automated somehow because it’s a lot copying and pasting and if you find a better way in the future you’ll hate yourself (trust me, I’ve done this).  You could easily subclass the PopupMenu and go through and change the Super of all existing popupmenu’s, but there is an even simpler way of doing this:  Extends

Extends lets you create your own method that acts like it’s part of the class.  If we were to take our code above for the PopupMenu and put it into a module (it won’t work in class objects like Windows) our code would look like this:

Sub SetText(extends pm as PopupMenu, assigns s as String)
   
   for i as integer = 0 to pm.ListCount-1
      
      if pm.list(i) = s then
         
         pm.ListIndex = i
         
         exit
         
      end
      
   next
   
End Sub

Same code, just using the extends.  What’s great about this is that using it super easy.  It becomes part of the AutoComplete list and is a ‘dot’ extension (just as if it was a subclassed item).  So calling it is like this:

pmFont.setText = sTheFont

I don’t remember when the Extends method was introduced but since it was introduced the number of Subclassed items in our projects has dropped dramatically.  Using Extends fails in one area and that’s Properties.  If you need a property for the additional functionality, you’ll still need to subclass the control and add the property to the subclass.

Containers

This final method may confuse some people.  Using a container control isn’t a subclass nor using the extends.  Containers are incredibly powerful controls in Xojo, though, because they allow you to create combinations of controls (and their subclasses) in unique and reusable ways.  A great example of this is a typical Save/Cancel pair of pushbuttons on a dialog or window.  On Macintosh OS X the Save button is on the right and the Cancel on the left.  On Windows it’s opposite.  In Linux, it’s the same order as Windows but the buttons have a different height.

There’s nothing stopping you from adding code to every window that has this Save/Cancel combination so that they’re in the proper location and height.  But why?  This is Xojo, a modern object oriented language!  Plus, I hope you’re as lazy of a programmer as I am because that’s a lot of work.  Use a container!

Create the container, add the pushbuttons.  I named my buttons Left and Right because their function is determined at runtime depending on the platform.  I add an Open event and in that event I add code like this:

#if TargetMacOS then
   
   btnRight.caption = kSave
   
   btnRight.Default = true
   
   btnRight.cancel = false
   
    
   
   btnLeft.caption = kCancel
   
   btnRight.Default = false
   
   btnLeft.Cancel = true
   
#else
   
   btnRight.caption = kCancel
   
   btnRight.Default = false
   
   btnRight.cancel = true
   
    
   
   btnLeft.caption = kSave
   
   btnRight.Default = true
   
   btnLeft.Cancel = false
   
#Endif

The kCancel and kSave are dynamic constants holding the proper strings.  In the ActionEvent of the buttons I have code like this to raise an event to tell the parent container (a window or another container) what happened:

Sub Action()
   
   //btnLeft
   
   #if TargetMacOS then
      
      //Cancel
      
      RaiseEvent Action false
      
   #else
      
      //Save
      
      RaiseEvent Action True
      
   #Endif
   
End Sub

Sub Action()
   
   //btnRight
   
   #if TargetMacOS then
      
      //Save
      
      RaiseEvent Action true
      
   #else
      
      //Cancel
      
      RaiseEvent Action False
      
   #Endif
   
End Sub

And finally the Action event which I’ve defined is:

Event Action(bSave as boolean)

It’s really as simple as that!  No matter which platform I’m on the Action event from this container tells me if the user pressed save or cancel.

Why did I include Containers in this article?  Good question!  It’s because you can think of Container Controls as a way to subclass Windows or WebPages without it being a window/page.  You can reuse Containers as many places as you want and when you change the original it changes the children (be aware though that there are some caveats with this statement – especially with WebContainers).  And even better is that you can dynamically add and remove containers at runtime.  Adding them is simple by using the EmbedWithin commands and to remove them use the Close method (I always set their visibility to false first).

We use a LOT of containers in our consulting work.  We find that it tends to simplify the code (remember being a lazy programmer isn’t a bad thing).  We’ve had windows/pages that have thousands of control and hundreds of controls visible at any given time but with a UI that complex we like to break them out into Containers.  So rather than having a Navigator with a listing of thousands of controls (and their labels!) we break it out logically into containers and the Navigator has maybe a dozen containers instead.

Each container has Save, Load, Validate set of methods (sometimes this is using an Interface) and whatever other methods are required but the point is that the overall window/page doesn’t need to know, or care, what the individual controls are and how to load, save, and validate their data – it only has to know enough to call the Load, Save and validate methods in each container.

With Xojo for Web, containers are even more important because you can create ‘repeating rows of controls’ that are very complex.  We wrote an entire accounting application for a client in using Xojo for Web and as you can imagine creating an Invoice Line Item row that needs Qty, Price, Amount, Sales tax and the necessary UI to add and delete the row, void a row, make it non-taxable can be complex.  Sure, we could have come up with a UI that doesn’t have that in a list, but frankly, it’s not that hard using WebContainers.

Containers are very powerful things and a great way to combine controls into one unit.  It’s also a way to create a dynamic control that can easily be added a runtime.  Rather than using a ControlSet (i.e. control array) and cloning an existing control (and having to keep track of the index) you can dynamically place your container that holds your one control.  We don’t use this technique very often but it does come up every now and then.

Conclusions

Subclassing a control in Xojo is pretty easy but sometimes overkill.  Using the extends method works great if you’re adding methods to a class/control and don’t need to add any properties.  Containers are powerful constructs that let you combine controls into a reusable object that have their own events and that can be added dynamically.  As a Xojo programmer you should be familiar with all three methods.

Did I forget anything?

New Video: ServerSockets

As a companion piece to the video from earlier in the week we added a new 38 minute video today on using a ServerSocket that allows your Xojo application to communication with multiple client apps that are using TCPSockets.  It turns out that it’s incredibly easy to use if you understand TCPSockets (which hopefully you know better now with that video).

I was chatting with an old developer friend this morning that I wish I had made this video a number of years ago when I was beating my head up against the wall on a big project that was using TCPSockets and ServerSockets.  Hopefully this gets you over the hump and you get some use out of it.  My pain is your gain in this case.

In this video we create a TCPSocket subclass on the ‘server’ that handles all of the communication details with the client apps.  The ServerSocket is a pretty dumb object (since it knows nothing about about our communications protocol with the client apps) but it is a pretty powerful class since you don’t have to do much to communicate to the clients other than provide a socket.

Our client apps can send a command, a single file, or a folder full of files.  Each client could potentially send a file with the same name and it would keep track of it properly.  We wrap up the video with having the server app send a message to all of the connected clients.

Direct link for subscribers:  http://www.bkeeney.com/XojoTraining/xojotraining.cgi?video=340

New Video: TCPSockets

Today, I added a new video to our Xojo training area. This new video guides you through the steps to using TCPSockets in your Xojo applications. In this nearly 90 minute video we create a sender application and a receiver application and by sending some simple data (a command and data) to the receiver to make sure we’re processing everything properly.

Then, we send a file (of any size) from the Mac sender app to the Windows receiver app. We do some basic file metrics to make sure the file we receive is the same as we sent. In the video I forget to unpack part of the data properly and it’s this file checking step that finds the problem (sometimes doing something wrong is instructive in these videos)!

Screen Shot 2014-10-08 at 10.16.38 AM

After that, sending a folder full of files is no big deal and in the video we clearly see that the sender has a queue of files that it’s going to send in multiple data segments, and the receiver only has a few of the segments yet.

Finally, we create an acknowledge message that gets sent back to the Sender application proving that we can have two way communication between the applications.

http://www.bkeeney.com/XojoTraining/xojotraining.cgi?video=339

We now have over 55 hours of training video of Real Studio and Xojo.  Since we rewrote the training area using Xojo for Web we’ve served up over 8,700 hours of streaming video to thousands of developers around the world.

Data Paging Control

A lot of Xojo developers don’t give too much thought to how much data they’re loading into a listbox. For many desktop apps a couple of thousand rows is not uncommon and, frankly, not a big deal. Push that to ten thousand rows and things start to get dicey and when you get to a million rows you’re talking some serious wait time for all million rows to get added to a list box.

For web apps it’s even worse. When the server gets the request to load a WebListbox with a million rows it has to build all of the HTML, first, on the server, push it down the internet connection to your browser, and THEN the browser has to reconstruct those million rows of HTML into a display. Any time you deal with strings there is a performance penalty and needless to say a million rows of data is huge hit to performance.

Trying to show the user a million rows is bad on multiple levels. First, your application is slammed with unnecessary string handling and second, the user can’t possibly handle a million rows of data. The listbox scrolling alone would be a nightmare! Just don’t do this!

Web apps have been using paging controls for years to limit the amount of data the user sees. I’ve seen some web sites limit this data to 100 rows and some to even less unless the user specifies more. That way the onus is on the user for the webpage being slow.  And more recently I’ve seen more desktop apps limiting the amount of data too.

Data Page Control

Today we released a new 48 minute training video showing you how to build your own paging control in Xojo desktop and web apps. We build the Paging Control using a Container Control and standard controls and then use it control a listbox. Then it’s a matter of using the SQL keywords LIMIT and OFFSET to control which records are returned. Of course the video comes with a desktop and web project file with source code you can use in your own projects.

The running example of the web app is at http://xojo.bkeeney.com/BKSWebExamples/#datapaging

This video is available to subscribers at http://xojo.bkeeney.com/XojoTraining/xojotraining.cgi?video=338

If you’ve not looked at our training videos you might find some interesting things. I invite you to take a look!

Computed Properties

Computed Properties have come up several times in the past week and in both cases, the person I was talking with was having a hard time understanding them.  They are a useful tool in Xojo in the right circumstances.  So let’s dig in.

First, let’s get this out of the way.  You don’t need to use Computed Properties.  Ever.  If you don’t want to.  They are an automation feature of the Xojo IDE.  Simply, they are a lazy way to create getter and setter methods for a private property in your class.

There are times when you want to expose your private property to the outside world but not give it unrestricted access.  Usually you’d want to do this because you need to validate the input, or perhaps something needs to be done before it can be read.

Creating your private property is no problem.  In this case we’re creating moSecurity that is a reference to our clsSecurity class.

Private moSecurity As clsSecurity

You create a Getter method that checks to see if we’ve already created an instance of it.  If not, then you load it and then simply return it.  Simple enough.

Function Security() As clsSecurity
   
   if moSecurity = nil then
      
      moSecurity = me.LoadSecurity
      
   end
   
   return moSecurity
   
End Function

If you want to change the Security object, you create a Setter method and use the Assigns keyword like this:

Function Security(assigns oSecurity as clsSecurity) As boolean
   
   if oSecurity <> nil then
      
      if me.CanChange(oSecurity) = false then
         
         return false
         
      end
      
   end
   
   moSecurity = oSecurity
   
End Function

Again, not terribly difficult to do.  It’s one property and two methods.  Notice that I didn’t name them GetSecurity and SetSecurity because I want these methods to act like a property to the outside world.

Return valuesThe Xojo IDE tries to be helpful by making a hierarchy of the methods that have the duplicate name.  You may (or may not) find this to be terribly useful.  I happen to dislike it because I can’t tell at a glance what the return value is, if anything, on either method without hovering my mouse over it or clicking on it and looking at the Inspector.  But then this is true of ALL functions – not just these types. Just one of the things that I miss from the Real Studio IDE.

SetterGetterMethods

Now repeat this sequence for every private property that you need to have exposed with Setter and Getter methods.  It’s not that it’s hard, it’s just tedious.  And if you have a particularly large class (think Formatted Text Control) that has hundreds of properties, the Method list gets HUGE.  The other drawback is that I often forget to use the Assigns keyword so I get compile errors if I attempt to use the Method as a property.

Computed Properties is a way to help make this a bit easier  We can accomplish the same thing by creating a public property called oSecurity in clsUser.

oSecurity As clsSecurity

ConvertToComputedPropertyPopupRight click on it in the Navigator and choose Convert to Computed.  You’ll see that the IDE makes a Private property called moSecurity as clsSecurity AND creates a hierarchical group for oSecurity containing a public Get and public Set method.  The default code that is in these computed properties is:

 

 

 

Get
   
     return moSecurity
   
End Get

Set
   
   moSecurity = value
   
End Set

At this point, we can modify these Get and Set methods to almost what we had before.

Get
   
     if moSecurity = nil then
   
   moSecurity = me.LoadSecurity
   
end

return moSecurity

End Get

Set

if oSecurity <> nil then
   
   if me.CanChange(oSecurity) = false then
      
      return
      
   end
   
end

moSecurity = oSecurity

End Set

ComputedPropertiesNotice that in the Computed Property version of the set we can’t return a value.  This is probably the biggest drawback, in my opinion, to using Computed Properties.  It’s almost the same amount of work but we have potentially saved some typing and we no longer have to worry about the assigns keyword because the IDE is automagically adding it for us behind the scenes (remember, we all want to be lazy programmers, right).  Thus our property is still treated as a property to the outside world.

One of the things that annoys me about Computed Properties is that now you have double the amount of Properties.  In the old fashioned (setter, getter) way you get a bunch of methods and in this second way double the number of properties.  Both, however, do mostly the same thing.

In my own fantasy world (believe me, it’s scary sometimes) I’d love to have the IDE group Public, Protected, and Private constants, methods, properties, etc so that I can expand only those that I want.  In this case I’d prefer to see only the Public ones.  The drawback is that you would have an additional hierarchy layer that causes clutter and may cause some confusion.  Would having the ability to hide certain scope types help?  I don’t know.

Do I have a conclusion?  Setter and Getter methods for your properties is easy enough.  It takes a little bit more work to set up and a bit more typing.  Each method, however, makes the Navigator a bit harder to read because of the added hierarchy but then so does the Computed Property.

Should you switch to using Computed Properties?  Only you can answer that.  I guess the only thing I’d recommend is be consistent throughout your project.  Consistency makes programs easier to read.

What say you, Xojo programmers?  Do you like using Computed Properties?  Why or why not?

ARGen 1.6.3

ARGen64BKeeney Software released a new version of ARGen today.  ARGen is an ActiveRecord class generator for Xojo and Real Studio.  It allows you to generate all of the classes required to use ActiveRecord in your projects.

Version 1.6.3 Fixes a CubeSQL bug that kept the Load function from working properly.  You could get around this by using the FindByID shared method but some people prefer the Load method.

This version also modifies the ActiveRecord classes a bit so it uses the prefix/suffix preferences used in ARGen to make sure your classes have the required property to match the field in the table.  For example, if you had a field PlaywrightID and were using a prefix of ‘i’ it will now flag the developer if there isn’t a property named iPlaywriteID.  In previous versions it didn’t really matter what you used.  This is just one more developer aid.

It is recommended that all Windows users update manually since a bug was discovered in earlier versions of the auto updater.

Recordset’s are Funny Things

We have a new developer working at BKeeney Software and he’s in the learning phase of Xojo. Not only is he new to Xojo but he doesn’t have a ton of experience doing software development in general. As someone who’s been using Xojo for a long time it is interesting to see how people struggle with the language and the IDE.

Today we had one of those “teaching moments” as he was beating his head up against the wall with this bit of code in a save method. This is a simple Invoice application saving the invoice line item to an SQLite database that’s on the local machine. See if you can spot the mistake.

dim rs as recordset =db.sqlselect( "Select * From tinvoicelineitem where invoicelineitem_ID = " + str(iInvoiceLineItem_ID) )
if db.error then
   msgbox CurrentMethodName + " db error: " + db.ErrorMessage
   break
   return false
end
rs.Field("InvoiceID").IntegerValue = iInvoiceID
rs.Field("salesTax_Flag").BooleanValue = bSalesTax_Flag
rs.Update

if db.error then
   msgbox CurrentMethodName + " db error: " + db.ErrorMessage
   break
   return false
end


Have you spotted the error yet? I don’t blame you. It’s easy to miss and it took me a few minutes of staring at it to find it. The code runs with zero code errors and zero database errors. The only thing that’s wrong is that it doesn’t save any line item data.

Okay, I’ll tell you. I forgot to add the rs.edit command at the top of the method. Without telling the recordset that you’re editing it, it will never generate the SQL to update the RecordSet.


dim rs as recordset =db.sqlselect( "Select * From tinvoicelineitem where invoicelineitem_ID = " + str(iInvoiceLineItem_ID) )
if db.error then
   msgbox CurrentMethodName + " db error: " + db.ErrorMessage
   break
   return false
end
rs.Edit // IMPORTANT!
rs.Field("InvoiceID").IntegerValue = iInvoiceID
rs.Field("salesTax_Flag").BooleanValue = bSalesTax_Flag
rs.Update

if db.error then
   msgbox CurrentMethodName + " db error: " + db.ErrorMessage
   break
   return false
end


I can argue that the lack of an error is bad. Sure, I didn’t code it right, but you’d think there would be some sort of error if an update was called without a starting edit. I’ve added <feedback://showreport?report_id=35134> to the Feedback system.

To be honest, we don’t do straight Xojo database calls much any more simply because we’re using ActiveRecord for most projects. AR eliminates most of the tedious database coding and let’s you deal with the data and the UI. When you call the Save in ActiveRecord you don’t need to care if it’s a new record or not. AR handles all the gory (and boring) details for you.

What say you my Xojo friends? Do you get bit by this type of thing when doing database coding?

Naming Conventions

If you don’t have standard naming conventions in your Xojo (or any other language for that matter) project you need to start NOW.  I mean it.  Open your IDE of choice and start looking at your variable names.  Can you tell at a glance what type of variable it is?  Better yet, can you tell what it does?  Or do you have a bunch of x, i, y, and z’s floating around in your code?

What about your TextFields?  Do you name them so you can tell their function or do you simply use the default name that the IDE gives you?  How do you tell the difference between TextField1 and TextField2?

Literally, the first thing I do when handed an OPC (Other Peoples Code) project is to look at the control names.  If I see TextField1 and TextFieldX I will almost always turn the project down.  But if I see txtName and txtAddress I know that I can figure out the code without constantly having to look at the Layout Editor.  The point is that controls are referenced in Xojo code all the time so if you’re naming your controls so that their function is obvious, the code will be obvious too.

The same goes with variable names.  I will prepend arrays with ar so that an array of MyClass will always look like aroMyClass.  My dictionaries always have dict in the front.  Colors always have c prefixes and so on (see chart below).

Do I use the occasional i, x, y and so on?  Absolutely, but they are throw away variables that are inevitably part of a loop of some sort.  If I’m using that variable for any other reason I will always name it something useful.

Variable names are important.  Rarely will you see me using iTemp as integer.  Instead, I’ll use iTempIndex which will at least tell me something about the variable.

I dare you to look at a project you did a year ago and open up any random method in it.  Can you read the code without referring to the Layout Editor?  I know that I’ve refined my own coding standards because of this.  If you’re not learning from your past mistakes why keep doing what you’ve always done?

I can hear some of you now.  Standards…Pft!  I don’t need no stinkin’ standards.  Think again.  I’m not here to tell you what those standards are just that you have them and that you are consistent about them.

Do what makes sense to you.  I looked at hungarian notation (http://en.wikipedia.org/wiki/Hungarian_notation) and I can see why people call it a different language.  While I’m sure it has many fine qualities it seems to make more work for me in figuring out what the variables are doing.  It’s way too complicated for Xojo.  For me, at least, simpler is better.  Plus, I’m not sure that a strongly-typed language like Xojo is in need of such strong naming conventions.

Using naming conventions for your controls and variables is an easy way to simplify your life and your clients’ life (if you’re handing code over).  Remember, you’re not just coding for the here and now, you’re coding for someone that will look at the code 6 to 12 months from now.  That someone might just be you!

Below is values right out of our new developer introduction document:

Variable Prefixes
Datatype Prefix Example
string s sName as string
integer i iCnt as integer
double d dAverage as double
dictionary dict dictNames as Dictionary
date dtm dtmModified as New Date Assumes I care about the time
date dt dtToday as new Date assumes I do NOT care about the time
class reference o oMyClass as new clsMyClass
color c cHighlight as color
folderitem f fPic as FolderItem
private property m miCnt as integer
boolean b bVisible as boolean
memory block mb mbBuffer as MemoryBlock
window win winMain
class name cls clsMyClass
array ar arsNames() as string ardAverages() as double aroMyClass() as clsMyClass
Control Prefixes
Control Prefix Example
Pushbutton btn btnSave
Label lbl lblCaption
Listbox lb or lst lbPeople or lstPeople
StyleGrid sg sgPeople
TreeView tv tvSections
TextField/TextArea txt txtPassword
CheckBox cb or chk chkEnabled
BevelButton bb bbSelect
ComboBox cbo or cmb cmbUserType
PopupMenu pm pmState
ProgressBar prog progUpload
Scrollbars see example common practice to use vScroll and hScroll
Radio Buttons rb rbOption1
Canvas cvs cvsGraph
TabPanel tab tabMain
Toolbar tb tbMain
PagePanel pp or page ppSection
Menu menu menuPopup
Container Control cc ccDetails

Xojo 2014 Release 2.1

Xojo 2014 Release 2.1 was released this week. This maintenance release is huge in several important ways.

This is the last version of Xojo that will build Mac Carbon apps. The upcoming changes to the framework for iOS and 64bit (and who knows what else) have made it impossible (or at least unfeasible) for the engineering team to keep supporting the Carbon framework. So long Carbon, we have to split up. It’s you, really, not me.

Since this will be the last version to support Carbon some nagging bugs were fixed in the Carbon framework. The hard crash that occurred when creating a new instance of the XMLDocument has been fixed. In addition a bunch of plugin issues for Carbon were fixed.

Cocoa apps that use RegEx will now pass submission to the Mac App Store.

For web app developers a big change was made to HandleSpecialURL that breaks everything that depended upon how the old, incorrect way, WebRequests were handled. I know this affects Web Custom Controls and it may also affect Studio Stable Web Essentials (unconfirmed). More info in a Xojo blog post at http://www.xojo.com/blog/en/2014/08/handlespecialurl-changes-in-2014r21.php

A few other web bugs were fixed. WebSession.Quit now properly clean and close the Session. A bug with WebContainer.EmbedWithin used in a open event (never a recommended way, if you ask me) that would cause WebLabels and WebLinks to offset was fixed.

There were several of database class changes too. SQLite now uses FTS4 with unicode61 tokenizer on Mac OS X. MySQLCommunityServer SQLExecute and Prepared statements no longer assume the statement is UTF8 encoded. The ODBCDatabase DatabaseRecord.Insert no longer inserts the wrong value.

As always, read the release notes for additional information and Feedback ID’s.

This dot release is critical for those developers still building for Carbon. iOS will (presumably) be out in Release 3 in at least beta form and the new framework is causing changes in a big way. I’m sure some of those changes will be subtle but some will be a smack to our collective faces.

To paraphrase Game of Thrones, “iOS is coming.” Sorry, couldn’t resist. :)