xcode v:9.2
I am trying to load user information from the database to set as placeholder text. I have tested this code on a simpler project that does not have segment views, and it works fine. I did some research and I think it might be a hierarchical issue. I am struggling to understand how I can make the textfield values load so that the locations they point to are connected when I try to access them and set placeholder values.
GetCurr retrieves database values and sends them to completion handler function to write placeholder value. When run, "setPH = nil"
Calls GetCurr for email
Completion handler that sets placeholder text
loadUserView should tell when to load the values of this particular segment
I know it's not my IBOutlets because they are all connected and as previously said, this code works perfectly fine in a simpler app that does not have segment views.
I figured it out! I connected the segments to uiviews that had their own uiviewcontroller class, as subclasses of the parent base class. It also makes my code cleaner and prettier!
Useful:
https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html
https://cocoacasts.com/managing-view-controllers-with-container-view-controllers/
Related
I am drawing a tableview via BehaviorRelay.
Currently, I am using the code below as a way to add data.
viewModel.user.append(Person(name: "king", phoneNumber: "12341234"))
viewModel.personObservable.accept(viewModel.user)
I wonder if this code changes the user itself so that the whole tableView is redrawn.
If so, what method can I use to change only the data I added?
The code presented causes the personObservable (which is actually a BehaviorRelay apparently,) to emit a next event that contains an entire array of Person values, not just the latest Person added. Importantly, it's not emitting the viewModel.user object (at least not conceptually) but an entirely different object that happens to be equal to viewModel.user.
The default dataSource, the one that you get when you call items with anything other than a DataSource object, will call reloadData on the table view. This doesn't cause "the whole tableView" to be redrawn though, but it will cause the table view to query the data source for all of the visible cells, even if they haven't changed.
If you only want the table view to load the new cell, then the data source object needs to be smart enough to compare the new array with the array it's currently displaying so it can figure out which values are different and add/remove/move cells as appropriate, instead of just calling reloadData. As #Sweeper said in the comments, the RxDataSources library contains a set of data source classes that have that logic built in. If you wanted to reinvent the wheel, just write a class that conforms to both RxTableViewDataSourceType & UITableViewDataSource and implement the diffing yourself.
I'm trying to set up a view-based table in Swift using bindings. All of the examples I've seen use a datasource/delegate setup.
I have an array of Flag objects which has two properties - flagName: String and flagImage: NSImage. I have an NSArrayController managing this array.
If I set up a cell-based table, and bind one column to arrangedObjects.flagImage and the other to arrangedObjects.flagName, I get a table displaying images and names, and I can use the array controller's add and remove methods, so there are no problems with my datasource or my array controller.
I have been following the instructions in Apple's TableView Programming Guide to bind my view-based table to my array controller:
tableView Content binding: FlagController.arrangedObjects
textField Value binding: TableCellView.objectValue.flagName
imageView Value binding: TableCellView.objectValue.flagImage
(IBs autocomplete is not happy with the paths for objectValue.flagName respectively flagImage; it doesn't feel that there should be any completion whatsoever and says it can't resolve the path, so it looks as if the problem is with the tableView's content.)
If I do this, my table has a number of rows that corresponds to the number of elements that my array controller is managing at that moment (I have two simple setups, one object vs. 50 objects, so it's clear that something is bound). What I don't get is a display; and selecting a table row does not seem to send back a message to my flagController.
What am I missing? Has anyone been able to make this work? I've had no problems with other bindings in Swift so far, but I'm starting to think that the sudden reappearance of datasource examples is not unrelated to this.
It sounds like you've failed to implement the delegate method -tableView:viewForTableColumn:row:. That's a common cause of blank tables.
You don't actually have to implement that if you make sure the identifier of the table column and the identifier of the table cell view are the same in IB.
Otherwise, the method can just do this:
- (NSView*) tableView:(NSTableView*)tableView viewForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
{
return [tableView makeViewWithIdentifier:#"TheIdentifierOfYourTableCellView" owner:self];
}
(It could also do more, if desired.)
I need to show some data in a textview coming from coredata (like this for example),
I imagine a possible solution (dont know if is the right one or how to do it, please advice),
so bring the data from coredata to a string, appending all the data neeeded in the string with the equivalent of "\n" for new line where needed; then show the data in the text view,
(please refer to example image to know what is needed)
so how to bring the data from coredata to this textView with this formatting?
please note I only want to know if this is a proper way to do it (imagined solution? or if there is a more proper way?)
Thanks a lot!!
I tackled an identical issue in one of my apps.
The approach I took was to first structure my core data model so that the pieces of data had enough granularity so that I could construct different views as required. In other words, instead of one property for "name", I have three properties. One for "first name", one for "middle name", and a third for "last name". I also created a separate "data layer" object so that I could easily get to pieces of my data from anywhere in the app.
Next, to construct my view that shows data in a sort of form view. Using Interface Builder, I simply laid out a view using primarily UILabel view objects as placeholders. Then, as the user switches between person views, I call on the data layer object for pieces of data and just "fill in" in the UILabel placeholders.
I also render a PDF file in paragraph form. Similar to what you are doing. For that, I use an NSMutableString along with the NSString stringWithFormat convenience method. Using NSMutableString, you can concatenate strings with newline characters embedded as needed. For this, I also call on my data layer object for the pieces of data.
[[NSString stringWithFormat:#"Date of Visit: %#", dateOfVisitString] drawInRect:stringRect withFont:theFont];
Hope this helps. Good Luck.
Yes, your strategy of
'bring the data from coredata to a
string, appending all the data neeeded
in the string with the equivalent of
"\n" for new line where needed; then
show the data in the text view'
will work fine.
(Bit of an odd answer, but it seems to be what you're asking, from your comment clarification.)
Your approach is fine. If you're targeting a textview for display, then constructing a formatted string from a managed object's properties is reasonable. Use NSMutableString and its -appendFormat: method.
You may also want to explore creating a report form out of UILabels laid out inside a UIView. Interface Builder would be the tool to use for this, but you could also create this in code.
I'm a c++ programmer new to objective-c.
I created a calculator app that is working fine using a single view. I have a Calculations class and a ViewController. Every time a button is pressed, an IBAction method in the ViewController calls methods defined in the Calculations class to handle the input and returns the output as an NSString which I then set as the value of the label.text field.
Now I am working on a tab bar app using the same Calculations class. This app has two tabs, each with a unique set of input buttons for the calculator (both views sharing the same input/output data). The first tab is identical to my first app with the single view, so I am trying to do this in a similar fashion.
Here is the problem:
When a button is pressed, the IBAction method that handles the input runs through the calls to the Calculations class methods (shown below) without error:
-(IBAction)readInput:(id)sender {
[_calculations input:[sender titleForState:UIControlStateNormal]];
inputField.text = [_calculations inputDisplay];
outputField.text = [_calculations outputDisplay];
}
however, both the inputDisplay and outputDisplay methods return nil. Using the debugger I noticed that I am unable to "step into" the calls to _calculations methods, instead the line is skipped and the value returned by both is nil. I added the following method:
-(IBAction)setNumber:(id)sender {
NSString *button =(NSString *)[sender titleForState:UIControlStateNormal];
inputField.text = button;
}
and if I attach this to the input buttons I can see the display updated. This seems to be an issue with calling the _calculations member functions and tab bar views (because this issue is not present using a single view).
I realize that I left out a lot of information, but I did it to avoid providing irrelevant information. I will provide all details that are necessary if asked.
Check to make sure _calculations is not nil.
You can send any message (call any method) on nil and it will just return nil, not cause an exception.
Without seeing more code it is going to be a bit difficult to diagnose.
If I was trying to debug this issue I would first make sure _calculations points to the object you want it to point to. If its loaded from a NIB then it might not be getting initialised, and still be nil. You can send messages to nil objects without any issues. If an object receives a message that it cant handle (the method doesn't exist, or the target object is nil) then the return for that call will be nil.
I have in the past put initilization code into the init: method, and spent a few hours why it wasn't being called, until it dawned on me that I needed to put my init code into the viewDidLoad:, or the initWithNibName:bundle: or even the initWithCoder: selector.
HTH, Matt
How does look the practical usage of IBOutletCollection? Unfortunately Apple documentation mentions it briefly without giving an wider idea of usage. OK, it maintains one-to-many relation with IB, but how to access and use particular objects efficiently? With TagName? How to ensure the order of objects?
I've recently used this to easily initialize a grid of labels. I have a n by n matrix of labels on a view, and reference each one individually (via an IBOutlet) in order to display relevant data. However when the view first loads I wanted to control the default text that displayed in all the labels. Initially i wanted a dash to display, but since this is for a client I wanted it to be easy to change. The view contents have and continue to change over time, per client requests.
Instead of writing N line of code, I created an IBOutletCollection and accomplished the same results in 4 (#property, #synthesize, and for loop). YMMV but I found it very useful in this situation.
Read again this section in the Interface Builder User Guide.
IBOutletCollections are actually just NSArrays you can connect to more than one object in IB. All the objects you connected end up in this array and can be accessed from code like any other object in an array.
I used it to minimize code. I have a range of UIViews that should react on "touch up inside" events of some UIButtons (custom mode).
I gave all UIButtons a tag (lets say 1005 to 1010) and all UIViews the same tag as the UIButton they shall respond to.
Then I connected the UIViews with the collection in Interface Builder. All UIButton touch up events go to the same function in my controller. This function gets the tag of the sender object, iterates through the NSArray list (of "IBOutletCollection(UIView)") and compares the tag. Everytime it hits, the appropriate action is done.
It is a pity that NSArrays seem not to hold the order...