Xcode get text of textfield from a different class - ios

I am a beginner in terms of xcode and objective-c and I am currently building an app that reads xml Files and compares their values to textfield values.
I have 2 classes. The first one is my View Controller where my textfields are. The second class is where I iterate through my xml files.
I simply want to be able to access the textfield's text my XML iterator class.
It is important that I can save the text that has been entered in the textfield as a variable in my iterator class.
I attempted to do something like this, but it didn't work:
ViewController *viewcontroller = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
viewcontroller.string = self.myTextField.text;
Help would be greatly appreciated since I have had trouble with this for a long time now.

Let's return to the basics of MVC pattern (which stands for Model-View-Controller) — your view controller talks directly to your views and model (or any helpers, like XML iterator in our case). So most likely the right approach would be to give your XML iterator text values directly in your ViewController's implementation and update / reset XML iterator every time text field's value changes.
One way to implement this is to have a strong #property to your XML iterator in your ViewController class (create XML iterator instance once, then assign in to the property and use it later). Another common way is to implement your XML iterator as a singleton class.
It's hard to tell which option is better in your exact case (for example, you can also use protocols or even notifications). However, this general MVC-oriented approach described above works in most basic cases. For more, read about Model-View-Controller pattern — Apple Documentation is the right place to start.

Related

UILexicon in Objective-C

How do you use UILexicon in Objective-C? I find the documentation Apple provides is extremely unhelpful.
What does it do? Does it return a dictionary or proper spellings of words? Or do I provide a word like "hellllo" and it matches it with the proper spelling "Hello" and returns that as a string?
Any help would be appreciated.
requestSupplementaryLexiconWithCompletion:
Here's my error report, but obviously I'll have errors because I'm completely guessing how to use the function, no clue what goes inside the block statement (because the docs (at the time) don't say! (Beta 4 docs)) Hahahah!
I've never used this feature, but a quick web search for "UILexicon" landed me in Apple's documentation; reading and following links from there filled in the picture pretty quick.
App Extension Programming Guide has a quick explanation of what lexicons are for:
Every custom keyboard (independent of the value of its RequestsOpenAccess key) has access to a basic autocorrection lexicon through the UILexicon class. Make use of this class, along with a lexicon of your own design, to provide suggestions and autocorrections as users are entering text.
Clicking the UILexicon link on that page took me to the reference doc for that class, which explains that it's a read-only list of Apple-provided term pairs. Each of its entries is a UILexiconEntry object -- the docs for that class say it provides a userInput (what the user typed, e.g. "ipad") and a documentText (what to substitute for it, e.g. "iPad"). Since those classes are read-only, it follows that they're probably not a way for you to provide your own autocorrection pairs -- as stated in the docs, they're for supplementing whatever autocorrection system you implement.
At this point, I don't even have to look at the doc for requestSupplementaryLexiconWithCompletion: to get a good idea how to use it: just the declaration tells me:
It's a method on UIInputViewController, the class I'd have to subclass to create a custom keyboard. Somewhere in that subclass I should probably call it on self.
Its return type is void, so I can't get a lexicon by assigning the result of a requestSupplementaryLexiconWithCompletion call to to a variable.
It calls the block I provide, passing me a UILexicon object as a parameter to that block.
It's got words like "request" and "completionHander" in it, so it'll probably do something asynchronous that takes awhile, and call that block when it's done.
So, I'm guessing that if I were writing a custom keyboard, I'd call this method early on (in viewDidLoad, perhaps) and stash the UILexicon it provides so I can refer to it later when the user is typing. Something like this:
#property UILexicon *lexicon;
- (void)viewDidLoad {
[super viewDidLoad];
[self requestSupplementaryLexiconWithCompletion:^(UILexicon *lexicon){
self.lexicon = lexicon;
}];
}
Because it's unclear how long requestSupplementaryLexiconWithCompletion will take to complete, any place where I'm using self.lexicon I should check to see if it's nil.
Back in the App Extension Programming Guide, it lists "Autocorrection and suggestion" under "Keyboard Features That iOS Users Expect", right before saying:
You can decide whether or not to implement such features; there is no dedicated API for any of the features just listed
So it sounds like autocorrection is something you have to do yourself, with your own UI that's part of the view presented by your UIInputViewController subclass. The API Quick Start for Custom Keyboards section in the programming guide seems to hint at how you'd do that: use documentContextBeforeInput to see what the user has recently typed, deleteBackward to get rid of it, and insertText: to insert a correction.

obtaining a property name at Run time using Objective C

with MBaas services getting really affordable, and easy to use, I was wondering if anyone could give me an advice on the following design choice ?
Context: Send the content of an NSDictionary for remote storage. So the idea is to build a key/value relation, on the fly.
How:
using the piece of code here, it is possible to retrieve the name of an instance variable. so, the key/value relation results from [{ivar_name ="the value I'm interested in from this ivar"}, etc.... ]
I understand the limitations of the proposed code, but I think they are outweighed by the benefits.
In my case, the dictionary will not live beyond the class life-cycle, so I should not keep strong references on ivars, when the View is removed from the stack. Furthermore, it's going to be NSString taken from TextFields.
However, there is one question I can't really answer: if the ivars I'm looking at are part of reusable UITableViewCells (ex: IBOutlet textField in a UItableviewCell), should I make a copy of the textField.text or can I keep a reference on the string pointed at by textField.text? or it doesn't matter?
Thanks !

Confusion over running methods on Class Method instances of objects

So I'm getting myself into a confusion over where my data's going and where it's stored in my application. It's not a specific question so hopefully someone can provide a generalised answer.
I need to pass some data around between a few UIViewController instances, and I'm currently doing that with a singleton object called my dataManager. This class has one method, a class method, called + (LCDataManager *) sharedDataManager, and that method basically checks if whether the sharedDataManager already exists, if so, return it, if not, create it and set up its variables. This means that I can refer to that class anywhere I like, access and modify its variables anywhere I like, from across multiple classes.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Second question: what if I want to put an instance method in that class, and call it from within the class method? Let's say my sharedDataManager needs to call a method to grab some objects one of its variables (an array), and put them in another array, then send that back out again. I can't do that, can I? What's the way around that? If I make an instance of that class (rather than using the shared instance), I lose the ability to use that instance across multiple viewControllers.
I'm hideously confused, and it seems like it's not the problem I'm making it. Appreciate any guidance, and preferably not that "Read the Apple documentation" stuff – they write as if you already know what you're doing, and frankly I don't yet.
First question: is this the correct / best / most appropriate means of passing data around like this? I'm hoping it obeys MVC, it feels like it does, and I hope I'm right.
Your design is perfectly MVC compliant.
Second question: what if I want to put an instance method in that class, and call it from within the class method?
you can surely define an instance method and call it like this:
[[MyModelClass sharedModel] myInstanceMethod];
indeed, [MyModelClass sharedModel] will give you an instance of MyModelClass (which should be guaranted to be unique being it a singleton).
If you want to call the instance method from the sharedModel class method, you could also do that, because sharedModel owns a reference to your singleton, so it can send messages to it.
is this the correct / best / most appropriate means of passing data around like this?
There's nothing wrong with only having a single instance of LCDataManager, but using the Singleton pattern has potential problems. An alternative is to just initialize one LCDataManger and to pass it around to wherever it's needed.
what if I want to put an instance method in that class, and call it from within the class method?
The accessor + (LCDataManager *) sharedDataManager should only return the instance. I guess what you want is something like
+ (LCDataManager *)preparedDataManager {
LCDataManager *shared = [self sharedDataManager];
[shared doSomeInstanceMagic];
return shared;
}
- (void)doSomeInstanceMagic {
// magic!
// grab some objects one of its variables (an array),
// and put them in another array
}
Matthijs Hollemans has an excellent three-part tutorial on his blog about the correct way to make your view controllers talk to each other:
Part 1
Part 2
Part 3
there is no problem with this development architecture, and it is the must used (I think) in the iOS development. In the book IOS Programming: The Big Nerd Ranch Guide they call it Model View Controller Store.
Regarding your second question, yes, you can declare instance methods and call then from your sharedDataManager. What is not usual is creating other instances of a singleton class, but it is possible.

How to use the values from an array defined in another class

I followed John Wordsworth tutorial (http://www.johnwordsworth.com/2011/10/adding-charts-to-your-iphone-ipad-app-using-core-plot/) to produce a line graph with CorePlot.
Later I decided to get some JSON data from a website so that I can use it for my graph.
All the url connection methods are performed in my ViewController.m file. And there I created an NSArray called indicator containing all the JSON data.
My problem is that all of the graph's parameters are defined in a separate NSObject class called SimpleScatterPlot.m where I would like to use the array of strings "indicator" (defined in ViewController.m) to customize the x-Axis labels.
What do I have to do so that I can use this JSON data array in SimpleScatterPlot.m?
I tried #import "ViewController.h" but it did not solve it.
Thanks in advance for any guidance you can give me.
Not sure if I am understanding it correctly, but I think you have not try to access the indicator nsarray from SimpleScatterView.m but to set there the value from ViewController.m.
1) Define a public NSArray in SimpleScatterView.m and synthesize it.
2) Instead of trying to gain access, use "prepareForSegue" in ViewControler.m to set indicator in the destinationSegueController.
3) In SimpleScatterView.m implement "-(void)setIndicator:(NSArray *)indicator" and update the GUI as needed.
Although the "Model - View - Controller" paradigm recommends not to use ViewControllers to perform communications and so on, but that is for another thread.
Create a property in Viewcontroller and synthesize it. Then pass the JSON data to the property.
To access the array in SimpleScatterView.m:
Viewcontroller *viewcontrol = [[ViewController alloc] init];
You can then access the array by using viewcontrol.indicator.
NSLog(#"%#",viewcontrol.indicator);
If I do not read incorrectly what you are trying to do, my guess is that you could appropriately use SimpleScatterView from within your UIViewController view (this is, assuming that SimpleScatterView is actually a UIView).
In this case, when your controller has downloaded its data, you could instantiate SimpleScatterView and display it by adding it to your view controller view.
... <data has been downloaded> ...
SimpleScatterView* scatterView = [[SimpleScatterView alloc] initWithFrame:...];
[self.view addSubview:scatterView];
When you initialize your SimpleScatterView, you could pass it a reference to the data array (say, in its custom init method, or using a property). e.g.:
SimpleScatterView* scatterView = [[SimpleScatterView alloc] initWithFrame:... andData:(NSArray*)...];
or:
scatterView.dataSet = <your_json_array>;
Of course, you have plenty of alternatives to this design. Specifically, I would mention:
the possibility of using a model class to handle all of your data, such that the controller writes the data to the model, while the plot view reads the data from it. The model could be implemented though a singleton in this case for ease of access;
the possibility of using a "dataSource" for your plot view: this would entail defining a protocol between the view and its datasource (e.g., a getData method); your view controller would play the role of the data source (in other words, instead of passing the array to the plot view as in above example, you would pass a reference to the controller and the view would access its data).

How can I divide a bound array in parts that automatically fill the table?

I used this 'tutorial' to bind my array called 'collection' to a NSTableview on my interface:
http://www.cocoadev.com/index.pl?NSArrayController
The interfacebuilder stuff isn't that hard. It becomes difficult when I try to actually show the data in my array into the view.
in my .h file:
#interface MyDocument : NSDocument
{
NSMutableArray *collection;
//other variables
}
and in my .m file:
#implementation MyDocument
#synthesize collection;
//quite some functions
inside one function (that works):
[collection addObject:fileName];
//some other functions
inside the init function:
collection = [[NSMutableArray alloc] init];
Now I guess the array is bound well to the interface and the tableview inside it, but ofcourse the tableview and its columns need to be filled in a specific way. Right now nothing shows after adding an item. with collection addObject:fileName function
Should I create a sub-Array as one item, filled with fields? And how should I bind these values/fields to the specific columns. (the fields are 'artist', 'title', etc)
I have already bound every column in Interface Builder to Array Controller with Controller key 'arrangedObjects' and Model Key Path 'artist','title',etc.
Please keep the explanation simple since I'm slowly starting to think I will never get this Array Controller thing... Objective-C doesn't seem that hard, but the binding which it needs is what I just don't get. Apple's examples are not sufficient to newbies
Typically to populate your data you'd use a dictionary (the key would be the keyPath, and object the data) for each row, or even better, create a class to represent the data and create a new instance for each row. Bindings can be a little tricky at first (if you're new to Cocoa get used to the data source methods first), but have a look at this tutorial and the examples here. Both contain samples you can download and examine exactly how the bindings is set up in Interface Builder.
Just mutating the array doesn't tell anything that the array has changed. You need to send KVO notifications for the mutation.
The right way to do this is to implement accessor methods for the property, then call your own accessors. In this case, you'll want to implement insertObjectInCollection:atIndex: and pass the length of the array as the index ([self insertObjectIntoCollection:fileName atIndex:[self countOfCollection], after also implementing countOfCollection).
When you implement accessors, then when an object binds to the property, Cocoa will wrap the accessors in KVO magic that will send the appropriate notifications for the mutation.

Resources