Yup, cost of movement onto a tile needs to be considered. Probably the easiest solution would be to edit tile properties and assign a "pathingCost" value (defaults to 0 if omitted). But in some maps the ground tiles may be on a different layer than the "detail" tiles (such as trees, oil puddle, building and what not) so I guess the better solution would be to assign a cost to a grid coordinate regardless of layers. That means the costs of both ground tile and detail tile could be added together to generate the total cost. And then you'd need a new set of cost values for different "units". That could become a memory issue (ex: 50 units * total tiles in map * sizeof(int32_t)).
In that case the callbacks would be less memory intensive but in turn would increase the runtime cost, highly depending on what code the delegate method runs. Classic memory vs CPU optimization tradeoff.
I'm sure there's a clever solution hidden somewhere, a combination of the two approaches perhaps. I remember in a PC game I worked on we had separate data maps for every usage (pathfinding for ground units, pathfinding for flying units, AI avoidance heatmap, tile texture map, ...) but that was on PC where 4 MB additional memory usage per map didn't hurt much.
Or maybe leave it to the user what the datatype of maps should be, ie most maps could do with byte maps (values -127 to 128) and 16-bit (word) maps would suffice for almost every pathfinding/AI usage. Even using bit-maps wouldn't be much of a problem, ie 2 bits per entry (4 blocking states) with 4 entries packed in a single byte if memory is really precious and you can trade it for about 10% or so runtime performance.