I'm going to developer two very similar apps, the logic is absolutely the same, but api calls base URLs, texts and UI graphics( such as backgrounds etc) will be different, but the all views will be the same (buttons, labels in the same places). It's quizes apps.
How to do it in the smart way? To not duplicate code etc.
I thought about to setup workspace, add bundles with UI, plists with texts and URL's, and than based on project name or identifier use one of the bundles, etc.
Maybe somebody can share smth else? More efficient way.
Thx.
I thought about [...] adding bundles with UI, plists texts and URL's
You wrote your own answer. Additionally you setup two targets. One for each project. Within the target you define an envorinment variable, which you can use in your code to switch between the bundles / URLs.
You should write a Helper Class to get the Ressources. That helper class checks the environment variable and gives back the correct ressource.
(You may want to write categories for UIImage and NSURL and write your own NSLocalizedString version. With that you don't need to check any conditions/settings anywhere else in your code.)
Related
or "How to decouple UI from business logic in Delphi?"
Each target platform has its own set of native firemonkey controls (Windows=VCL, MacOS=TMS mCL, Android=D.P.F, iOS=TMS iCL and D.P.F). The new FireUI (multi-device form designer) is a great solution for styled components, but not for native components because it still requires the same component on the master pane to support all platforms. As you cannot mix them on the same form, it completely breaks the whole idea with Delphi.
A lot of developers would say that Delphi is the broken approach, see "Why FireMonkey is so fundamentally wrong in every aspect". However, the premise for this question is NOT to argue against Delphi, but to get the best results out of what it does offer.
The conclusion is then that for each form in your application you have to make a separate form for each target platform. This leads to these questions:
Challenge 1: How to include different form files in your project depending on your target platform?
Solution 1: include all of them, i.e. MainForm_IOS.pas, MainForm_Android.pas, MainForm_Win, MainForm_OSX.pas, and then use compiler directives inside the files, so only the content of one of the files is active. Disadvantage: a large application can have many forms (we have around 40), so we are talking about a large number of included files.
Solution 2: Do not include them in the project, but instead just place them in seperate folders. Then you can add the matching folder to the search path for each target platform. Disadvantage: They will not show up in the Project Manager, so it will slow down the workflow every time you need to find a file.
Solution 3: Create a project for each target platform. Disadvantage: Every time you add new units or change common project settings you have to (remember to) apply it to all projects.
Update: As suggested in the Malcom Groves video, placing all the business logic in a package will remove the disadvantage from Solution 3. So I consider solution 3 as the best approach.
Challenge 2: How to connect the different device forms to the (same) business logic?
Possible solution: Create a "Helper" class that contains all the code you would normally have in the form unit.
Update: This "Helper class" is actually what the MVVM calls a ViewModel. What I need seem to be a MVVM framework that can support the databinding. I have made another question about that.
Any input and suggestions about best practice are welcome.
For challenge 1:
You can conditionally link in your FireMonkey form resources depending on the compile target:
{$R *.Windows.fmx MSWINDOWS}
{$R *.Macintosh.fmx _MACOS}
etc.
This is excatly what the XE7 Multiview designer does, but I see nothing against using this mechanism to link whole form files conditionally in to your executable. Of course you might also want to ifdef the corresponding units in your project file.
For challenge 2: Just use some form of Model View Controler logic. So your platform dependant forms will talk to a platform independant controler.
I have been fighting a losing battle against loading fonts from an embedded file for use with DirectWrite. I am writing a simple puzzle game that has a C#/XAML interface but also uses SurfaceImageSource to add some DirectX content.
I have written a WinRT component that handles all of the DirectX code, and it works quite nicely. Some of my DirectX content is text drawn using the DirectWrite API. I can draw all the text I like so long as I'm loading an installed font from the system using IDWriteFactory::GetSystemFontCollection(), etc. But, I cannot seem to find a way to load a custom font from an embedded file.
From what I can tell Metro apps are not allowed to load files from the filesystem in the same way as a traditional app. So, the IDWriteFactory::CreateFontFileReference() method that takes a normal file path is worthless to me, right? I need to load my file from an ms-appx URL.
So, I wrote a custom font loader in my WinRT component that implements the IDWriteFontCollectionLoader interface (which is a ton of work if you've never done it before btw) that loads the font from an ms-appx URL using the new StorageFile API. Now, I can load my IDWriteFontFile and I can get a IDWriteFontFace, but if I try to call any of the truly useful methods on the font face it returns E_UNEXPECTED. I can get the number of glyphs and the glyph indices, but if I try to call something like GetGlyphRunOutline() or GetDesignGlyphMetrics(), it fails with E_UNEXPECTED. Using the same drawing code that generates an ID2D1PathGeometry using GetGlyphRunOutline() works great as long as I install the font file and get the IDWriteFontFace through the series of calls starting with IDWriteFactory::GetSystemFontCollection(). I am working with a normal true type font.
So, how do I load a custom font from an embedded file into DirectWrite in a Metro app? I'm probably just missing something easy, because I am certain that other people will want to be able to load custom fonts in this way.
I have a sample project (or could prepare one easily) for anyone who can help me identify my problem.
I have loaded the two IDWriteFontFace objects side by side, and I tried to figure out what is different between the one that works and the one that breaks. What I need to see in order to find out why it is failing is opaque to me hidden behind inside the IDWriteFontFace interface. HELP PLEASE!
Question also posted here: Building Metro style games with DirectX Forum
Well, the answer is... don't write a IDWriteFontCollectionLoader! You can use IDWriteFactory::CreateFontFileReference() with the StorageFile API. I was under the impression from all of the Microsoft Conference talks I had attended that in Metro you would be unable to access the native file system directly; the way forward would be to use the StorageFile API which references resources, etc. using ms-appx URLs. I understood that this was done for concurrency and to allow the OS to insulate itself from Metro apps that would be downloaded from the store by creating a file system sandbox. I think that is accurate. But, I feel like I was led to believe that we would never be able to get native file system paths. That is NOT true. IStorageFile provides a way. Just use IStorageFile.Path. I never looked at it because I just assumed the Path property would hold the ms-appx URL that I used to create the object. Microsoft probably provided this for exactly the purpose in my problem above: calling legacy COM interfaces that require a native path.
I haven't done any testing to determine whether the WinRT framework actually sandboxes you if you try to access a native file system path outside your own app package. I'm betting that it does...
What are good ways of building groups/folders?
I've tried by feature (UI for a feature plus model etc) with a common group. I've also tried by UI, model, etc.
The former keeps like things together which fits the iPhone paradigm nicely. The latter means I jump around a bit more.
What do you think?
The standard Xcode MVC folder structure is as follows.
CoreData : Contains DataModel and Entity Classes.
Extension : Contain One class(default apple class extensions+project class extensions.)
Helper: Contain Third Party classes/Frameworks (eg. SWRevealController) + Bridging classes (eg. Obj C class in Swift based project)
Model : Make a singleton class (eg.AppModel - NSArray,NSDictionary, String etc.) for saving data. The Web Service Response parsing and storing data is also done here.
Services : Contain Web Service processes (eg. Login Verification, HTTP Request/Response)
View : Contain storyboard, LaunchScreen.XIB and View Classes. Make a sub folder Cells - contain UITableViewCell, UICollectionViewCell etc.
Controller: Contain Logic or Code related to UIElements (eg. UIButton’s reference+ clicked action)
It's going to be very project dependent. In my last project I had mostly views, and so I organized the views by view-type.
Organizing code by type
Organizing code by type is ok for small projects but it's not a good practice for big ones.
Just imagine you have tons of files and folders organized by type, and when you work on a single feature, you have to open all of the folders. Which can confuse you and you can get lost many times while you scroll through files.
It looks something like on A.G's & Julian B.'s answers.
Organizing code by feature (intent)
Organizing code by feature (intent) is the best practice for big projects and big teams.
Cause usually teams work on a single feature, and they focus only on a single folder or group of files. They don't necessarily have to know about other features and files.
It looks something like this:
AppDelegate
Features
Feature 1
View Controllers
Models
Views
Logic
Feature 2
View Controllers
Models
Views
Logic
Networking
Models
Logic
Extensions
Resources
Also, to mention, this practice and technique (organizing project by feature) are implemented by the greatest companies around the world.
Is there some tool in Xcode that allows me to store snippets of code I often reuse in various applications so I do not have to retype it each time? I am talking about things like all the code that goes into defining Table Delegate Methods and Table Source Methods, UIAlertViews code and such. I just would like to have my own private repository where I can put snippets of code I think I may need in the future in other apps. Is there anything like that? Thanks for any help.
I guess the answer to your need is discussed in this page http://www.turkeysheartrhinos.com/?p=8. Look at the "Custom TextMate – Like Macros" section.
In Interface Builder you can drag and drop components you've built into the library under the Custom Objects list. These can be reused in other XIBs you build later.
I'm not sure about code snippets in Xcode itself, I would find that useful too. If you are talking reuse though, can you put alot of your generic stuff in superclasses that you can inherit from when appropriate?
Try "Edit User Scripts..." under the script menu in Xcode. Look at the scripts under the "HeaderDoc" header to see some examples of inserting templates into code. You'll have to reformat your snippets into blocks of Perl like these, but this approach also gives you those neat tab-through-able input areas like you see when you autocomplete method calls.
How about using the tool "sinppets" ?
I'm writing code that will allow my iphone-app to have a "configuration page".
A grouped, scrolling, UITableView... with cells that contain the needed textFields, switches, sliders, etc.
It is an ENOURMOUS amount of code. Is there an easier way?
Is there a way I could create a simple text-file, contain all my desired design choices and have my (reusable) code build the TableView for me?
Or... can I just do the whole thing quicker/easier in Interface Builder instead of code?
Basically there are two approaches here :
you rely on what Apple gives you and implement a Bundle Settings (basically a dictionary that describes how the settings screen should look like), and then , your settings will be in the "Settings" application of the iPhone.
The drawback here is that what apple provides is quite limited and you won't be able to implement some of the most complicated settings you can see in "standard" (pre-installed) apple application settings.
That's why many developers are switching to "inapp" settings thanks to open source FWK or they reimplement everythingh from scratch but it can be a lot of code as you said.
You reimplement your own UIViewController for settings or you rely on some framework that will provide you the UIViewController to extend from and ease your implementation.
There are 2 good frameworks for that (Jesse cited one of them, but there's another one )
InAppSettings ( http://inscopeapps.com/blog/inappsettings-10/ )
InAppSettingsKit ( http://inappsettingskit.com/ )
A comparison of the two framework can be found here : http://inscopeapps.com/blog/inappsettings-vs-inappsettingskit/
(ok that's from one of the two authors but at least this gives an idea ;)
If you can live with the limitations of the standard application preferences in iPhone, you can actually create this using a settings bundle which only needs a plist and optionally a localized strings file.
You can check out Apple documentations for this:
http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ApplicationSettings/ApplicationSettings.html
Claus
If you're looking for a ready made and reusable solution, you can check
http://www.inappsettingskit.com/
It's open source too, so it's useful as a base.
I never found an easy and efficient way to build complicated table view by using Interface Builder, so I think programming the settings view is more preferable.
If you're talking about using a text file or plist, you may want to mimic the Settings Bundle design of Settings app.
Load the plist data upon the app launch.
I've built something like what you're looking for. Going off Claus's answer as well, it basically just duplicates the interface of the Settings application using the same settings.plist file as the settings app. The only difference is that it's a view controller that you can put inside the app. There's a surprisingly small amount of coding involved, it was just a lot of looking at the settings app to see exactly how things were laid out.