I wonder if there is any frameworks I'm not aware that I can use to achieve the concept of databinding, bind a NSObject derived class (the model) to a UIControl/NSControl derived component properties.
For example I have a class with a property name and I need to bind it to a UITextView text property so that when the model's name property changes the UITextView text property updates.
I guess that there would be something built on the Key-Value Observing concept.
I would like something that is working in both OSX and iOS or any other related frameworks for the platforms.
Thank you.
You're looking for ReactiveCocoa - super awesome framework that does exactly what you asked for and more. Also a good way to implement MVVM - they have cool extensions that enable that ReactiveViewModel as well as extensions for AFNetworking
Take a look at AKA Beacon (https://github.com/mutech/aka-ios-beacon). It's a binding framework that allows you to bind views to properties right from interface builder. The view controller (by default) serves as view model for bindings. You just have to add one line of code to the view controller to activate binding support and the framework takes care for all the rest.
Beacon supports most standard views (Label, TextField/View, Image, Slider, Stepper, Switch, TableView, etc.). It's relatively easy to write extension bindings for custom views.
Related
I have just recently decided to transition from building UI elements using the storyboard to building them programmatically.
While looking up tutorials online, I saw some people liked to create their UIs using closures.
For example: let label: UILabel = { // they would customize their UI elements between the brackets }
I was wondering if this was some sort of conventional way used to build UI Elements ?
So far I've been sticking up with declaring my variables(including UI elements declaration) before the viewDidLoad method and declaring functions to configure them below it before calling them in the same 'viewDidLoad' method.
Is it wrong to do it this way?
There is nothing wrong in the way which you do, but using closures, is a common practice in iOS programming. Closures have multiple benefits such as all the view related configuration code is placed in a single place, the code is readable, and it becomes straightforward to make changes to the code and debug if there are any bugs present.
It’s about preference. But, in the way you described with closures, you won’t be able to access other properties even if you declare them before the property inside which you need them.
I'm a bit of a newbie programmer, so I'm asking for people's opinions/advice on what they would do in the situation I'm in.
Background
Due to constraints of the library I'm using to achieve a "pop up" like window, I'm currently working on a UIView class (let's call it Menu) which creates UIImagePickers and various other View Controllers (VCs). However, since the UIView itself persists on top of any VCs it spawns itself, I'm forced to delegate any VC creation methods to the parentVC of Menu, so that I can dismiss the Menu view, create any VCs necessary, and then (sometimes) additionally restore the Menu view.
Issue
I'm currently copy and pasting hundreds of lines of delegate methods for any UIViewController that has a Menu view. These delegate methods are the same for every one of those view controllers, and exist there because the methods have UIViewController specific functions such as presentViewController. I'm tempted to pass the parentVC as a parameter to Menu in order to cut down on the amount of duplicate code, but this seems MVC-unkosher. What would be a good approach to this problem?
If I understood right, you can Just create an extension, like this
extension SomeClass: ClassesDelegates {
//some specific code that all Views will use
}
I'm tempted to pass the parentVC as a parameter to Menu in order to cut down on the amount of duplicate code, but this seems MVC-unkosher.
That's because MVC is a dated architectural choice, leading to exactly this kind of situation. That's where the "Massive View Controller" snark that you may have noticed here and there around the web comes from.
Your Menu depends on parentVC. Thus, we call parentVC a dependency. A fundamental precept of modern architectures is dependency injection, which allows you to eliminate the duplicate code you refer to and test Menu in isolation from its dependencies. Check out
Dependency Injection Demystified
Dependency Injection
Dependency Injection, iOS and You
Dependency Injection in Swift
So, fear not the use of parameters, your instincts are sound. Embrace the use of parameters, and preen that you are adopting the "25-dollar term for a 5-cent concept" (see first link), the Agile design pattern referred to as Dependency Injection. For bonus cool points, do not make that parameter a UIViewController. Define a protocol with just the access that Menu requires, and make that parameter anything that conforms to said protocol, and add an extension to UIViewController conforming to that protocol. That makes testing and reuse elsewhere easier; and more importantly, then you will be engaging in Protocol-Oriented Programming, which puts you right out on the cutting edge of trendy Swift design patterns. Nobody will call you a newbie then.
I am fairly new at creating iOS apps and I have a question about a common practice regarding central Text & Color styling in a project.
What I want to do is to define a custom "Header" style, custom "ToolBar" style, custom "Body" style etc. and use them in different UIControlViews in my project.
I want to be able to change one of these styles so that every object using that style adjusts accordingly.
As much as I understand there are no CSS-like styling files when designing an iOS app.
What I was thinking to do is to create a Swift file where my styles are defined as constants in some way and add code blocks in all viewDidLoad methods of UIViewControllers that sets related objects' styles by using these constants.
Is there a better way, or what is the common practice for doing that kind of thing?
Many classes has the protocol UIAppearance which sets their default properties such as font, textColor, backgroundColor etc.
Ex:
UIButton.appearance().backgroundColor = UIColor.redColor()
List of all classes using UIAppearance
As you said create a configuration.swift file that contains your configuration and returns a view based on configuration and then use this configuration to create a custom view. This is the way I did in my last app. Also, check this snippet to get an actual understanding of what I said http://www.objc.io/snippets/20.html
Read about view controller polymorphism and view controller hierarchy.
Base a "parent" view controller on UITableViewController, and include your common properties and methods.
Then base all the "child" view controllers on that "parent".
For example in Objective C:
"Parent" view controller header file...
#import <UIKit/UIKit.h>
#interface MyParentTableViewController : UITableViewController
#end
"Child" view controller header file...
#import <UIKit/UIKit.h>
#interface MyChildTableViewController : MyParentTableViewController
#end
So in this manner all public properties and methods of the parent become available to the child, and only need be written once, in the parent implementation file.
I have been using the pod NUI for styling the complete iphone Application. There are couple of other options like UISS.
There are few other commercial options also, but the above two do a fantastic job of externalizing the styling of the application.
I've used NUI and it enables me to provide multiple themes and even allow the end user to switch themes.
I'm learning iOS development stuff and what I have found in tutorials and books is that controller layer usually has access to the View's controls directly (textfields, labels etc.). Let's consider such an example:
Assume, that View has a label called lblResult and a textfield called txtDataToAnalyze. Than in controler interface we've got something like this:
#property (nonatomic, retain) IBOutlet UILabel* lblResult;
#property (nonatomic, retain) IBOutlet UITextField* txtDataToAnalyze;
and some #synthesize statements in the implementation file.
I have some experience with JavaSwing development, where most of thinks I'm writing manually without any GUI Builders, and what I usually do in MVC is to access the View's controls via getters/setter. For example: void setResult(String resString); or String getDataToAnalyze();. In that way, controller knows only what pieces of information are displayed in the view, and not how are they displayed. I think it is more flexible (it is easier to change the view layer later).
I know that iOS has some specific rules, has introduced XIB/NIB files etc so maybe my doubts are completely useless in case of iPhone/iPad development. But I am going to write some more serious application for iOS (actually "rewrite" it from Java Swing) and that's why I would like to ask you:
Do you think, I should change the way I am thinking and get accustomed to that new (for me) approach (xib files, creating GUI using drag&drop and providing controler with information about how data should be displayed in view) ?? Did you have similar doubts when starting with iOS?
Short answer:
Yes, I think you should definitely spend a little time getting accustomed to working with Interface Builder (IB) to make NIBs and storyboards and let IB create the IBOutlet and IBAction references for you for those controls with which you need to interact. Once you're proficient at it, you'll be impressed by your productivity in generating easily maintained code. Don't dismiss IB too quickly.
In terms of letting the controller interact directly with the IBOutlet and IBAction references, this is common practice for simple user interfaces. If you have some real world examples, post a new question with a screen snapshot and we can offer more practical guidance.
Long answer:
Part of your question seems to be driven by the apprehension in seeing view controllers that are doing detailed interaction with a view's controls. The thing is, if you want to isolate your controller from some of the implementation details of the view, then go ahead and subclass the view and put the view specific stuff in there. IB can interface with both view controller subclasses as well as view subclasses. So you can happily use IB and still isolate your view controller from some of these implementation details.
Personally, I only do this subclassing of UIView when the view hits some subjective complexity threshold (e.g. for me, that threshold is when I find myself doing some complicated animation, such as using CADisplayLink; complicated gesture recognizers, etc.). I also subclass those subviews that are logical entities of their own (e.g. UITableViewCell or UICollectionViewCell). But for simple views where I'm interacting with my model to setting a control's properties, interacting with text fields, etc., I think putting that in the view controller is fine. Having said that, if I have a lot of view-specific code in my controller which has nothing to do with the integration of my model with my view, then start subclassing the UIView and shifting the view-only code into that.
Implicit in your question is the notion of programmatically building view rather than using NIBs/storyboards. In my opinion, using Interface Builder (IB) to build your UI is much easier to develop and maintain. There might be some pedagogical value to doing a test project where you build your views programmatically, so you really understand what's going on, but after that, I think you'll find yourself quickly gravitating to storyboards. And you'll get plenty of chances to write your own non-IB code when you start doing things beyond the capabilities of the standard IB controls (e.g. complicated custom container views, etc.). There are definitely those who prefer to develop views programmatically, but I don't think you can beat the development speed and ease of maintenance of IB generated UIs.
I general, the controller does not know about the view, but the view knows about the controller.
The gang of four book says:
"MVC also lets you change the way a view responds to user input without changing its visual presentation. You might want to change the way it responds to the keyboard, for example, or have it use a pop-up menu instead of command keys. MVC encapsulates the response mechanism in a Controller object. There is a class hierarchy of controllers, making it easy to create a new controller as a variation on an existing one.
A view uses an instance of a Controller subclass to implement a particular response strategy; to implement a different strategy, simply replace the instance with a different kind of controller. It's even possible to change a view's controller at run-time to let the view change the way it responds to user input. For example, a view can be disabled so that it doesn't accept input simply by giving it a controller that ignores input events.
The View-Controller relationship is an example of the Strategy (315) design pattern. A Strategy is an object that represents an algorithm. It's useful when you want to replace the algorithm either statically or dynamically, when you have a lot of variants of the algorithm, or when the algorithm has complex data structures that you want to encapsulate."
I'd like to add some custom buttons to an ABUnknownPersonView. Can I use initWithNibName:bundle: in my ABUnknownPersonViewController to load a custom view that I've created in IB, while not using an "undocumented api?" And if I do, how can I make sure that it follows all the properties and responds to all the hooks that the controller expects?
I typically create all my views programmatically and I generally like the view that ABUnknownPersonViewController creates. I'd rather just start from there. And so I accessed the view and dropped in a button, but with later versions of iOS that broke since that isn't a hook that Apple created.
initWithNibName is also not mentioned in the ABUnknownPersonViewController documentation but it is a method of it's parent class UIViewController. Does that make it safe to use?
You cannot provide a replacement XIB. While I understand you want to avoid it, you will have to use the underlying AddressBook framework and building your own version out of it.
You can, of course, look at open source stuff such as this for a good starting point.