Rollo62 536 Posted October 28, 2019 (edited) Hi there, usually I don't care much about iOS versions, I would expect that those customers have the latest stuff always. But I was facing the issue that an older iPHone 5S (iOS 10.3.4) cannot tested via TestFlight. I see a message, similar to this https://stackoverflow.com/questions/33900295/app-not-compatible-on-iphone-4s-and-5-in-testflight Of coarse I may use features that are probably not available in older IOS, but I'm asking myself in general what strategy would fit best, to keep most apps as compatible as possible. I don't really know if iOS 10 is still supported, but the platform status says so, that is will be down to iOS 10.3 (never tested this). Its not easy to find out which features are depreceated or changed in each version, or is there maybe a good history of versions in the web ? I have never seen any for iOS. Currently I'm trying to encapsule simple features, as best as possible, so that I can test and enable/disable them separately (like notification, tts, sensors, location, etc..). What I did not incuded yet is a kind of "version control" for each feature, I think about e.g. certain features may have varying permisson models and behaviours, but that could be still acceptable for basic functionality of the app. Each feature could behave slightly different within different versions, but the app wouldn't crash right away, instead notifies gracefully. Probably this would be a little too difficult for abstraction, but I hope that breaking changes doesn't occur too often. I think XCode does a very good job in helping the developer in these cases, and to fix issues automatically, would like to have such XCode knowledgebase in my code too . If there are some interesting links about such abstraction, I would be happy to get some feedback. Edited October 28, 2019 by Rollo62 Share this post Link to post
Rollo62 536 Posted October 29, 2019 (edited) No ideas I could think of an interface system like FMX.Platform, to separate all features well. So that I could have multiple implementations, could override to fix something on the fly, and my features could be created by requesting the availability first. var LScreenService: IFMXScreenService; LScreenSize: TPoint; LMyService: IFMXMyService; begin if TPlatformServices.Current.SupportsPlatformService( IFMXScreenService, IInterface(LScreenService)) then begin LScreenSize := LScreenService.GetScreenSize.Round; ... if TPlatformServices.Current.SupportsPlatformService( IFMXMyService, IInterface(LMyService)) then //<= This checks if a feature is generally available (also kinda OS dependent) begin if LMyService.CanUseMyFull then // <= This could check if to what degree the feature is available at current OS-version begin LMyService.UseMyFull; // <== and use it fully if available end else if LMyService.CanUseMyPartly then // <= This could check if to what degree the feature is available at current OS-version begin LMyService.UseMyPartly; // <== and use it partly if available end; end; Would that be the perfect pattern to abstract such complex features also on different platforms and versions ? Mainly beauty may arise from a perfect naming system. Ideally I don't want to deal with version changes any longer, but simply want to use what is possily, to avoid crashes. The version requests are nicely hidden inside the services. But is this the best approach, is this really efficient and fits all needs ? Embarcadero decided for this to use it at the core, so it shouldn't be too bad, I'M not sure if there are better patterns available. I could also think about a messaging system, where all components communicate via publish/subscribe, which would ensure a very good separation, but that is not as easy to use as the FMX.Platform style. Another way could be simply by deriving features from a base class, to make use of normal class inheritence. Probably all different ways tend up to get messy soon, do I oversee someting ? Edited October 29, 2019 by Rollo62 Share this post Link to post
Dave Nottage 557 Posted October 30, 2019 There's no "easy" way to cater for older versions, whether it's iOS, macOS or Android. The best you can do is check the API documentation for which version the methods were introduced (or removed) and use TOSVersion.Check to determine whether the code is relevant and can be called, and branch to another part of the code if you need to cater for lower versions. There's a bunch of examples of TOSVersion.Check being used in the FMX code, so you could refer to them. Share this post Link to post
Rollo62 536 Posted October 30, 2019 (edited) I wanted to build a "system" or "pattern" that better could encapsulate such changes from the interface side. Of coarse the internal implementations may look totally different, and TOSVersion would help much. My goal is that from the interface side all this complexity is hidden. Not sure howto hide such complexits best. Personally I like the CanUse, DoUse, TryUse patterns, but they also need some kind of conditions when not necessary. Probably there are better concepts out there. I'm also not sure if enhancing the FMX.Platform system is a good idea, since this is the domain of Embarcadero, but I think doing so would keep the same pattern also for my own interfaces. Another possibility is simply "fixing" broken classes, to get the desired behaviour, e.g. by interposer classes. There are also people who like to completely replace the existing interfaces, by some own, well controlled interfaces, like maybe the TMS FNC did (I don'T really know this, but I think that will replace all existing TButton, TEdit, etc.). Maybe ways, but what will be the "golden way" (if there is any) ? Edited October 30, 2019 by Rollo62 Share this post Link to post