UISegmentedControl
encapsulated in SegmentedAtom
.ViewController
’s children. For example, an atom to select an account from the list (and by filter from the context). The main thing is that all the complexity remains inside the atom. Outside, it remains just as easy to use. class PayPPQuickOperation : Operation, AtomValueSubscriber { private let dataSource = PayPPDataSource() private var srcTitle, destBicInfo: TextAtom! private var destName, destInn, destKpp, destAccount, destBic, destDesc, amount: TextInputAtom! private var btnSend: ButtonAtom! override init() { super.init() create() initUI() } func create() { srcAccount = AccountPickerAtom(title: " ") destName = TextInputAtom(caption: " ") destInn = TextInputAtom(caption: " ", type: .DigitsOnly) destKpp = TextInputAtom(caption: " ", type: .DigitsOnly) destAccount = TextInputAtom(caption: " ", type: .DigitsOnly) destBic = TextInputAtom(caption: "", type: .DigitsOnly) destBicInfo = TextAtom(caption: " , ") destDesc = TextInputAtom(caption: " ") amount = TextInputAtom(caption: ", ₽", type: .Number) btnSend = ButtonAtom(caption: "") // : atoms = [ srcAccount, destName, destInn, destKpp, destAccount, destBic, destBicInfo, destDesc, amount, btnSend, ] destInn!.optional = true destKpp!.optional = true btnSend.controlDelegate = self // onButtonTap destBic.subscribeToChanges(self) } func initUI() { destName.wideInput = true destAccount.wideInput = true destDesc.wideInput = true destBicInfo.fontSize = COMMENT_FONT_SIZE destName.capitalizeSentences = true destDesc.capitalizeSentences = true } func onAtomValueChanged(sender: OperationAtom!, commit: Bool) { if (sender == destBic) && commit { dataSource.queryBicInfo(sender.stringValue, success: { bicInfo in self.destBicInfo.caption = bicInfo?.data.name }, failure: { error in // , self.destBicInfo.caption = "" }) } } func onButtonTap(sender: AnyObject?) { // , sender var hasError = false for atom in atoms { if atom.needsAttention { atom.errorView = true hasError = true } } if !hasError { var params: [String : AnyObject] = [ "operation" : "pp", "from" : srcAccount.account, "name" : destName.stringValue, "kpp" : destKpp.stringValue, "inn" : destInn.stringValue, ... "amount" : NSNumber(double: amount.doubleValue), ] self.showSignVC(params) } } }
onAtomValueChanged()
is the implementation of the AtomValueSubscriber
protocol. We subscribed to the BIK text field changes and there we make a request that returns the name of the bank on the BIC. The commit == true
value for the text field comes from the event UIControlEventEditingDidEnd
.showSignVC()
is to show the ViewController
for the signing operation, which is just another operation that consists of the same simple atoms (formed from the elements of the security matrix that come from the server).Operation
class code, since You can find a better solution. I decided (in order to save development time) to feed the atoms
table ViewController
. All “bricks” are drawn in IB by cells of tables, instantiated by cell id. The table gives automatic height recalculation and other amenities. But it turns out that now I can only place atoms in the table. For the iPhone it is good, for the iPad it may not be very. So far, only a few banks in the Russian appstore correctly use the space on the tablets, the rest stupidly copy the UI of iPhones and only add the left menu. But ideally, yes, you need to redo it on a UICollectionView
.NSPredicate
. func createDependencies() { // ppType - , - (EnumAtom) ppType.atomId = "type" ppType.subscribeToChanges(self) let taxAndCustoms = "($type == 1) || ($type == 2)" ... // : field106.dependency = taxAndCustoms field107.dependency = taxAndCustoms field108.dependency = taxAndCustoms ...
destInn.subscribeToChanges(self) destInnError.dependency = "isDestInnCorrect == NO"
destInnError.showIf("isDestInnCorrect == NO")
destInnError
, in case of incorrect input, tells the user how to correctly fill out the TIN according to the 107th order.isDestInnCorrect()
method, although you can probably do this with macros.Operation
(sorry for Objective C): - (void)recalcDependencies { for (OperationAtom *atom in atoms) { if (atom.dependency) { NSPredicate *predicate = [NSPredicate predicateWithFormat:atom.dependency]; BOOL shown = YES; NSDictionary<NSString*, id> *vars = [self allFieldsValues]; @try { shown = [predicate evaluateWithObject:self substitutionVariables:vars]; } @catch (NSException *exception) { // } atom.shown = shown; } } }
let verifications = Verifications.instance ... if let shown = predicate.evaluateWithObject(verifications, substitutionVariables: vars) { ...
JSONModel
class, inherit ServerReply
from it (because each answer contains a basic set of fields), from ServerReply
inherit server responses to specific types of requests. The main disadvantage of the library is that it is not on Swift (since it works on some language lifehacks), and for the same reason the syntax is weird ... @class OperationData; @protocol OperationOption; #pragma mark OperationsList @interface OperationsList : ServerReply @property (readonly) NSUInteger count; @property OperationData<Optional> *data; ... @end #pragma mark OperationData @interface OperationData : JSONModel @property NSArray<OperationOption, Optional> *options; @end #pragma mark OperationOption @interface OperationOption : JSONModel @property NSString<Optional> *account; @property NSString<Optional> *currency; @property BOOL isowner; @property BOOL disabled; ...
NSObject
fields must be marked as < Optional
> and checked for nil
yourself. If we want our property so that it does not interfere with JSONModel
, we write their modifier < Ignore
> or, as JSONModel
, (readonly)
.UITableView
, on smartphones it works, and for tablets, in the case of an “advanced” design, you need to redo the View and partially Presenter (just a general solution for smartphones and tablets).Source: https://habr.com/ru/post/318200/
All Articles