That’s a big stack

I’ve been plowing through all kinds of tutorials and books so that I can build a working stack of tools and libraries for doing javascript development. Boy, is that extensive and complicated. This is how far I’ve gotten until now.

I have learned most of the technologies in the graph, at least superficially, and it looks like you need most of them for a fully rounded application. The world has certainly changed from back when you could learn one language, one IDE, and one platform.

Javascript development mindmap
The interrelated tools and libraries I need (click for large version)

Update: do read this satirical post about how it feels to learn Javascript. It’s absolutely perfect.

Autoresizing text view in table cells

Continuing from the previous version, I upgraded to Swift 3 and Xcode 8 (beta 4). Most of the glitches are gone, but every now and then one shows up. So I’m not entirely sold on the whole thing yet. I’m still having doubts if it wouldn’t be simpler to just have the user enter text in a separate popup of some kind, and only display read-only views in the actual table. The problem with that is that it is a lot less intuitive and user-friendly. OTOH, it would work… I get a feeling Apple really doesn’t want us to do editing in text views in table cells. I don’t think any of Apple’s own apps do that.

Continue reading “Autoresizing text view in table cells”

Medical IT crap, the why

(Continuing from my previous post.)

I think the major problem is that buyers specify domain functionality, but not the huge list of “non-functional requirements”. So anyone fulfilling the functional requirements can sell their piece of crap as lowest bidder.

Looking at a modern application, non-functional requirements are stuff like resilience, redundancy, load management, the whole security thing, but also cut-and-paste in a myriad of formats, a number of import and export data formats, ability to quick switch between users, ability to save state and transfer user state from machine to machine, undo/redo, accessibility, error logging and fault management, adaptive user interface layouts, and on and on.

I’d estimate that all these non-functional requirements can easily be the largest part of the design and development of a modern application, but since medical apps are, apparantly, never specified with any of that, they’re artificially cheap, and, not to mince words, a huge pile of stinking crap.

It’s really easy to write an app that does one thing, but it’s much harder and more expensive to write an app that actually works in real environments and in conjunction with other applications. So, this is on the purchasers’ heads. Mainly.

Another creator pattern for clusters

This is about Cocoa, and in particular about class clusters. The problem I wanted to solve was having a class cluster with easily extendable hierarchy without too much interdependency. In my case, I want to create a number of different UITableViewCell descendants, depending on the particular data element the cell should handle. If the data element has a field “string value”, then a UITableViewCell with a text field for such a string value should be created. If the data element has a field “check” representing a yes/no answer, then a UITableViewCell with a yes/no functionality widget should be created instead, and so on. In total, I have less than ten different kinds of UITableViewCell derived classes, but they could become more at any time.

Continue reading “Another creator pattern for clusters”

Don’t do parts.parts

I just found another weirdness in Apple’s Objective C. If you have the same name for several components of an object path, the runtime starts stuttering and behaving very badly. Intermittently, you can’t scroll, or only extremely slowly, everything turns into molasses. No errors, mind, just mindbogglingly slow.

This stuttering and slowness seems to affect the simulator, mainly, not so much if you run code on your device (in my case the iPad). Also, if you run under instruments, things work better (Murphy strikes again), except I had it stutter under “Allocations” but not under other instruments.

I had these repeat names in two places in my code and resolving those two seems to have fixed the stuttering entirely. To illustrate what I mean, see this code snippet:

for (IDRBase *idr in self.parts.parts) {
   if ([idr isSuperCell]) break;
   CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
   UIView *view = [idr getAsView:newFrame];
   if (view) {
      [returnView addSubview:view];
      verticalOffset += view.frame.size.height;
   }
}

(Yes, it’s the same snippet as in the previous example with nil or not nil. Coincidence. My code does indeed consist of more than just this.)

In the very first line you see a property referred to as “self.parts.parts”. That is what screws things up. Even though the two names “parts” refer to entirely different things, and even though the code actually delivers the values it should, this repetition of identical literal names confuses the crap out of the runtime, it seems. The solution is to not name these two things the same, of course. In this case, I changed the innermost “parts” to “aParts”, resulting in “self.parts.aParts”, and hey presto, no stuttering no more.

Is it nil or isn’t it?

A bit of Objective-C weirdness I don’t quite get. The weirdness occurs if “view” in the code below is nil, that is if [idr getAsView:newFrame] returns nil. You’d expect the verticalOffset not to be incremented, but it is. Even though view is nil, view.frame.size.height still evaluates to “21” (in this case) and verticalOffset gets incremented. (The first returned view was 21 high, the second returned view was nil in the debug run I’m referring to.)

- (UIView *)getAsView:(CGRect)theFrame {
	CGFloat verticalOffset = 0.0;
	CGRect hugeFrame = myCGRectHuge(theFrame);
	IDVBase *returnView = [[IDVBase alloc] initWithFrame:hugeFrame];
	hugeFrame = myCGRectResetToZero(hugeFrame);
	
	for (IDRBase *idr in self.parts.parts) {
		CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
		UIView *view = [idr getAsView:newFrame];
		[returnView addSubview:view];
		verticalOffset += view.frame.size.height;
	}
	[returnView sizeToFit];
	return [returnView autorelease];
}

To avoid the unintended increment, I have to add the conditional if (view) {…} (which is a pretty good idea anyway, since it’s rather pointless, or maybe even bad, to add a nil as a subView):

- (UIView *)getAsView:(CGRect)theFrame {
	CGFloat verticalOffset = 0.0;
	CGRect hugeFrame = myCGRectHuge(theFrame);
	IDVBase *returnView = [[IDVBase alloc] initWithFrame:hugeFrame];
	hugeFrame = myCGRectResetToZero(hugeFrame);
	
	for (IDRBase *idr in self.parts.parts) {
		CGRect newFrame = myCGRectDown(hugeFrame, verticalOffset);
		UIView *view = [idr getAsView:newFrame];
		if (view) {
			[returnView addSubview:view];
			verticalOffset += view.frame.size.height;
		}
		[returnView addSubview:view];
		verticalOffset += view.frame.size.height;
	}
	[returnView sizeToFit];
	return [returnView autorelease];
}

I don’t know what the moral of this story is. I assume that if I should delve into the language reference, this will turn out to be undefined behaviour. Trying to figure out what could have been defined behaviour, I can’t come up with a reasonable answer, so I guess it’s just one of those things you should avoid doing. Maybe a compiler warning would have been nice, though.

Method forwarding in Objective-C

I scraped together the following from a number of sources and got it to work fine and without compiler warnings. Interesting links are, among others:

http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html
http://macdevelopertips.com/objective-c/objective-c-categories.html

But, I get ahead of myself. The idea here is to have one object forward method invocations to another. Typically, you have a class responding to method A, then you decide to make an instance of that class a member of an outer class and any messages for the methods sent to the outer class should be forwarded to the inner class if that’s where they are to be handled. And, of course, you don’t want to sit and write all these methods again in the outer class just so the inner class gets called. An example:

I have a class I call IotaDOM2TableProxy which has a method “rowsInSection:”. The class IssueWorksheet holds an instance of IotaDOM2TableProxy as a property. I now want any “rowsInSection” messages sent to the outer IssueWorksheet to be forwarded to the inner IotaDOM2TableProxy object without having to declare any “rowsInSection” method for the IssueWorksheet class. This is how you do it.

Firstly: the target, the IotaDOM2TableProxy class, needs no modification at all. It never knows what hit it, or rather, where the invocations come from. So we’ll not say anything more about it than that it contains the declaration of the “rowsInSection:” method (among a load of other stuff):

@interface IotaDOM2TableProxy : NSObject {
...
}
- (NSUInteger)rowsInSection:(NSUInteger)section;
@end

The IssueWorksheet class holds an instance of the IotaDOM2TableProxy, and does not declare any method called “rowsInSection”:

@interface IssueWorksheet : NSObject {
    IotaDOM2TableProxy *dom2tableProxy;
}
@property (nonatomic, retain) IotaDOM2TableProxy *dom2tableProxy;
@end

To make IssueWorksheet forward any calls it doesn’t know about to IotaDOM2TableProxy, we have to override three methods in IssueWorksheet:

- (BOOL)respondsToSelector:(SEL)aSelector {
    return [super respondsToSelector:aSelector] || 
           [self.dom2tableProxy respondsToSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *sig;
    sig = [super methodSignatureForSelector:aSelector];
    if (sig == nil)
        sig = [self.dom2tableProxy methodSignatureForSelector:aSelector];
    return sig;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    SEL aSelector = [invocation selector];
    if ([self.dom2tableProxy respondsToSelector:aSelector])
        [invocation invokeWithTarget:self.dom2tableProxy];
    else
        [self doesNotRecognizeSelector:aSelector];
}

And this works beautifully for one, two, or any number of methods to forward. There’s just one problem: the compiler complains that IssueWorksheet “may not respond to method…” and we should always eliminate warnings. The easiest way is to declare the forwarded methods in a category, which only mildly defeats the purpose of the exercise. But it works and is safe. You do that by adding the category after the interface declaration of IssueWorksheet, so the header file will now look as follows in its entirety:

//
//  IssueWorksheet.h
//  iotaPad1
//
//  Created by Martin on 2010-06-08.
//

#import 
#import "IotaDOM2TableProxy.h"

@interface IssueWorksheet : NSObject {
    IotaDOM2TableProxy *dom2tableProxy;
}

@property (nonatomic, retain) IotaDOM2TableProxy *dom2tableProxy;

- (id)initFromFile:(NSString *)name ofType:(NSString *)type;


@end

@interface IssueWorksheet (ForwardedMethods) 
- (NSUInteger)rowsInSection:(NSUInteger)section;
@end

In the above, I call the category “ForwardedMethods”, but you can call it anything you like. The name doesn’t matter and isn’t referenced anywhere else, but the category must have a unique name of some sort.

Please note: there is no implementation in the .m file for “rowsInSection”. The category definition suffices to shut the compiler up.