Jump to content

Dalija Prasnikar

Members
  • Content Count

    1111
  • Joined

  • Last visited

  • Days Won

    96

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Delphi for Mobile Applications

    When it comes to mobile development you cannot count on that kind of stability. Not because of Delphi, but because of platforms. android and iOS get new OS version every year, often with drastic changes in some workflows and features. They also expect that you frequently update your application and make it compatible with new OS versions (old applications still run, but if you don't make an update in two years period applications will not be available to users with new OS versions - this is just example, there are variants of what exactly happens in each particular case). Those OS changes also require changes in Delphi toolset and sometimes additions in code. How drastic depends on the each particular change. This is valid for all mobile development toolsets, and is nothing Delphi specific. But, this also means that you will have to keep current with new Delphi releases and you cannot stick using some old Delphi version for too long after new one gets out.
  2. Dalija Prasnikar

    Delphi for Mobile Applications

    Yes, things have changed significantly for the better. However, there are still some pain points (more specifically debugging, especially on iOS as Apple keeps throwing curved balls) Main difference is that ARC was being source of significant performance issues on mobile platforms. I have done extensive investigations at the time, and by doing slight modifications in FMX code I was able to significantly improve performance. Used optimizations were covered in my blog posts: https://dalijap.blogspot.com/2018/01/optimizing-arc-with-unsafe-references.html https://dalijap.blogspot.com/2018/01/optimizing-arc-hard-way.html https://dalijap.blogspot.com/2018/03/optimizing-arc-weakness-of-weak.html Even though there is no ARC compiler, above articles are still valid when dealing with interfaces in Delphi. Removing ARC compiler was not the only performance improvement. Next one was introduction of Skia library in Delphi 12, which gives better performance on mobile platforms. It is not perfect and depending on the project it is not necessarily working better on the desktop FMX applications, but it is easily configurable, so different rendering methods can be used depending on the platform. Another pain point was using 3rd party frameworks on both Android and iOS, and this has also been significantly improved in the meantime. Overall, plenty of bugs have been fixed in the meantime (of course, that does not mean there are no new bugs), but things are way better than they were at the early beginnings. Most importantly people are successfully using Delphi for writing Android and iOS applications. You can find one such example here: Whether Delphi is the best option for some project that is another question and it can really depend on the project. The best option would be putting down all the tech your app needs to interact with and what are basic features you need to support. After you have tall that listed you can make a demo app to see whether you can easily incorporate all that you need across various tools and platforms. Only after doing that you will be able to tell which one will be the best for the project. And at the end, the grass is not greener on the other side. For development Delphi is much more stable platform than some others. It does not have some fancy features language wise, but its UI frameworks are very stable. Over the years, both Google and Apple made significant shifts in their native frameworks that required extensive code refactoring (yes, you can still use the old ways, but it still requires a lot of work to keep up with changes). If you are looking for cross-platform tool, then situation is not too much different.
  3. Dalija Prasnikar

    Google Signin Firebase for Store doesn't work

    If you are using App Bundles and Play Store Signing, then you need to add SHA-1 fingerprint from the Google Play Console as Google will use different certificate for signing from the ones in your keystores. See: https://developers.google.com/android/guides/client-auth
  4. Dalija Prasnikar

    tParallelArray and interfaces

    It compiles for me... but after adding missing quotes in interface GUID declaration. TParallelArray is not the problem here.
  5. Dalija Prasnikar

    Do you need an ARM64 compiler for Windows?

    Just the fact that the code has been working for over 25 years means that it will have very little issues when it comes to exception handling. Only hardware exceptions are the problem, which for VCL means mostly dereferencing nil and dangling pointers and floating point exceptions (which are now masked by default). I doubt that there are many places in VCL that would need code changes for exception handling.
  6. Dalija Prasnikar

    Do you need an ARM64 compiler for Windows?

    Since there is already plenty of low level RTL code that runs with LLVM based compilers, the only part where those exceptions could cause issues is VCL. I would say that this is probably less of a problem than it may look like on the first sight. Developing Windows ARM compiler is much simpler than 64-bit IDE
  7. Dalija Prasnikar

    String memory usage

    AI can't even count properly. Why would it be able to know whether number is prime or not?
  8. Dalija Prasnikar

    Simulate blocking mode to send Email

    CheckSynchronize must be called from main thread, just like Application.ProcessMessages. If the issue is that background thread is calling TThread.Synchronize or Tthread.Queue, then CheckSynchronize must work. If it doesn't work then the problem is in something else. I don't use FNC components so I cannot say what the actual issue is.
  9. Dalija Prasnikar

    SplashForm freeze

    I misinterpreted your post. However, if you do that, then you must not call Free on SplashForm, but FreeAndNil and then check whether it is nil before calling Close. You could also just call FreeandNil in the MainForm.Show event as releasing the form would also free it. OnShow event can be triggered more than once and freeing the form without niling the reference would mean that you are accessing dangling pointer which can crash your application. FreeAndNil can be safely called on nil reference so you wouldn't have issues with that.
  10. Dalija Prasnikar

    SplashForm freeze

    Creating forms and running animation are all tasks that need to run in the main thread. Adding background threads would not help here.
  11. Dalija Prasnikar

    SplashForm freeze

    If the form is not completely painted, then you should call Application.ProcessMessages. The need to have that can depend on the controls and code you have on the splash form. Animation will depend on message processing, so using animation in splash form is not advisable. (I missed that part in your initial post). If you insist on having animation, then you would have to call Application.ProcessMessages more frequently, like @DJSox proposed, but the animation might not be smooth depending on how much time is needed for constructing each form. Calling MainForm.Free (or Close depending on the code) will destroy the main form. Not to mention that even closing in OnShow would prevent main form from becoming visible, so this is not something you should be doing at all. It does not serve any purpose.
  12. Dalija Prasnikar

    SplashForm freeze

    Your problems is that you are trying to show splash form after all other forms are created. You should show it immediately upon construction. BEGIN Application.Initialize; Application.Title:= 'My Slow App'; FormSplash:= TFormSplash.Create(Application); FormSplash.Show; Application.CreateForm(TFormMain, FormMain); Application.CreateForm(TForm2, Form2); Application.CreateForm(TForm3, Form3); Application.CreateForm(TForm4, Form4); Application.CreateForm(TForm5, Form5); FormSplash.Free; // FormSplash is no longer needed Application.Run; END. There is also no point in having empty try...finally block, it serves no purpose. If construction of any of the forms fails, the application will just terminate. You could add some error handling in such case, but that is another story. You should not use FormSplash variable anywhere else after you call Free on it as it will be a dangling pointer. That should not be too much of an issue since it is only a splash form and it is not supposed to be used anywhere else. Otherwise you would have to use FreeAndNil(FormSplash) to be sure that reference is niled when object is gone and the variable is still accessible to other code.
  13. Dalija Prasnikar

    "Divided by zero" exception

    C++, Swift to name some. Interoperability with code written in other languages (although this is not a language issue per-se) was one of the main reasons why exceptions are masked now, as such code would commonly expect masked exceptions. So you had to do mask/unmask at every call to such code which then caused issues in threading as Delphi FPCR functions were not thread-safe at all. For instance: https://stackoverflow.com/q/9472265/
  14. Thanks, that helps and your issue is accessible now.
  15. I don't know if you can change that now, but when posting issue you need to use Share with Embarcadero customers to make it visible to others. See https://dalijap.blogspot.com/2024/04/delphi-121-new-quality-portal-released.html
  16. No. Please don't post existing bug reports to the new tracker as they already exist in the internal tracking system and doing so duplicates the issues and only creates more unnecessary work. Also ne tracking system does not support voting. There are zero benefits for anyone involved.
  17. The problem is that Embarcadero provides base framework classes that satisfy very narrow usage and are not properly open for extension. Sometimes you need to change literally one line, to get the needed behavior, but there is no way to do that properly. So you need to resort to hacking into those classes. Protected opens up the class for needed extensions and still protects casual users from using implementation details and does not break encapsulation. Yes, if the implementation changes, you may need to update your code to match the changes, but you would need to do that regardless. Private is major PITA.
  18. Yes, sorry. I missed the context you are replying to. We agree on the rest, and that was the point of my example. To show that custom managed are initialized/finalized even if not used and that there is extra initialization for Default call on implicit temporary variable. And compiler should be smart enough not to require any temporary variable at all. In any way thing is broken.
  19. Because whole point of custom managed records is automatic initialization/finalization. So if you merely declare such record as local variable and you don't ever use it, its initialization and finalization routines will run. Running following code makes the issue more obvious. type TMyRec = record x: Integer; class operator Initialize(out rec: TMyRec); class operator Finalize(var Dest: TMyRec); class operator Assign(var left, right: TMyRec); end; class operator TMyRec.Initialize(out rec: TMyRec); begin Writeln('init'); end; class operator TMyRec.Finalize(var Dest: TMyRec); begin Writeln('finalize'); end; class operator TMyRec.Assign(var left, right: TMyRec); begin Writeln('assign'); end; procedure Main; var r: TMyRec; begin r := Default(TMyRec); end; begin Main; end. If assignment is commented out then result will be init finalize But running code as-is will result with: init init init assign finalize finalize
  20. One thing you would want to do is use single form as a container and organize all other forms as frames. Working with multiple forms on mobile is major PITA and docking frames in that main form container is much simpler for switching between views. You can still have multiple forms and dialogs on Windows if needed where you will dock the same frame used in mobile, on the separate container form.
  21. Dalija Prasnikar

    ifthen strange return value !

    Er... no. It does not matter how correct is the input, the output can still be outmost garbage when it comes to the correctness, it will just sound nice. Also, if you don't know whether some statement is correct or not how can you verify the output. For instance AI can say "Local variables are automatically initialized" and "Local variables are not automatically initialized" If you don't know which of those statements is true, you will not be in position to verify. You cannot even check with code, because local variable can accidentally occupy memory that was zero at the time, so it may seem like the first statement is true, while it is not. It does not matter how often it is correct (the best AI will be wrong in over 20% of responses, which is far from insignificant), it is about inability of a person who does not know something to determine whether response is correct or not. Even merely translating and rewording of correct content can result with incorrect output. Some examples how AI can lie to you: https://github.com/mdn/yari/issues/9208 and MS copilot demonstration video around 38 minutes.
  22. Dalija Prasnikar

    ifthen strange return value !

    I would suggest that you don't use ChatGPT or any other AI for writing or explaining the code. While it may give you correct results at times, quite often it will be completely wrong and you will have no idea whether what it said is correct or not.
  23. Dalija Prasnikar

    ifthen strange return value !

    It doesn't work like that. LObj is reference type. That means it consists of two parts. LObj variable itself is merely a pointer (address) that will point to the object instance when it is allocated on a heap. All local variables are allocated on stack, not heap. So when you declare local variable the memory for the pointer is automatically allocated on stack when FormCreate is called. Stack memory is not automatically cleared, so whatever values were there, they will remain. Only managed types local variables will be automatically initialized. When you create object and assign it to that variable then created instance will be allocated on a heap and address of that memory location will be stored in LObj variable. This behavior is same on all platforms. However, until Delphi 10.4 Delphi mobile platforms had ARC compiler where objects were automatically managed and local object variables were automatically initialized on those platforms.
  24. Dalija Prasnikar

    ifthen strange return value !

    LObj is local variable and it is not initialized. That means it will hold some random value (garbage). This is why it can show that object is allocated when it is actually not. You need to initialize it (to nil, or assign some object instance to it) before you can call your function.
  25. Dalija Prasnikar

    Dynamic array used as a queue. Memory fragmentation?

    If you are frequently adding/removing items from array and the maximal occupied memory is not an issue, I would use TList<T> instead of dynamic array which supports Capacity. Set the Capacity to the maximum number of elements you are expecting (if there are more underlying dynamic array will automatically grow). That will prevent frequent allocations/deallocations and improve performance. You may also use TQueue<T> which might be fit for your needs. Whole array needs to be allocated in one place so there will be no memory fragmentation just because of that array reallocations.
×