When to use class vs struct in a specific case [duplicate] - swift

This question already has answers here:
Why Choose Struct Over Class?
(17 answers)
Closed 3 years ago.
Here's my scenario:
I have a list of user present in a TableView, in each row I show some user's information like address, phone number.
I can tap on a user, I pass the user to another screen like Detail View Controller, in here I can change the user's information. Then I can tap back and those change affect to TableView.
In the scenario above, what class or struct should I use.
I've tried both, class might be easier when I only need to modify user's info in the Detail View Controller but can it lead any side effect ?
I've read some article and they says that always choose struct by default but it make me confused
Some one can give me some advice when to use one instead of another and explain why. Thanks a lot.

If you choose class then you don't need to do anything just pass the same object which exists in the user's array.
If you choose struct it will call by value and will not change anything in another instance, so you will need to inform your ViewController regarding the changes (May be in back button click) via delegate or notification. You can pass your user model in the delegate call back or notification object and replace it in your user's array by comparing its id.

Its better to use structs because they are value types and have a unique memory address(creates a copy). In your case its better because you have multiple users and each user will be unique.
Instead if you use classes for user and if there are multiple instances of the same user then changing the properties of one user will change another because classes are reference types and points to the same memory address.

Related

How to check if a word is defined in the English dictionary in cocoa-touch?

I am trying to make a crossword app for IOS but i Don't know that how to check if a string is valid english word or not.
How can i check it.
Is there any API or online facility to check it.
Thanks in Advance
Easy to do in iOS5 using the UIReferenceLibraryViewController class' +dictionaryHasDefinitionForTerm: method.
A UIReferenceLibraryViewController object provides a dictionary
service to look up the definition of terms. You create and initialize
a reference library view controller using the initWithTerm: method.
You pass the term to define as the parameter to this method and the
definition is displayed. You can present this view controller modally
or as part of another interface. On iPad, you can set the reference
library view controller as the content view controller of a
UIPopoverController object. Optionally, use the
dictionaryHasDefinitionForTerm: class method to check if a definition
is available for a given term before creating an instance—for example,
use this method if you want to change the user interface depending on
whether a definition is available.
There is no API for this.
In order to do this, you will need to have a dictionary file (text file or database) in your application bundle. One of the faster ways to check will be to load the dictionary into memory when the application launches so you don't have to read the file for each word. This may be overkill if you simply want hardcoded crosswords, but if you are randomly generating them then this is a must.

CoreData Relationships in two different ManagedObjectContexts

Warning: This is my first IPhone Application and I'm new to Objective C, therefore my question might be very basic.
Actually I have a conceptual problem:
I have a one to many relationship between my NSObjects Project and WorkTime (Project<-->>WorkTime). WorkTime has attributes like startDate, endDate, … and a relationship named project to the Project object.
On the UITableViewController subclass that shows my list of WorkTimes, I fetch the CoreData Model with a FetchedResultsController. When I create a new WorkTime, I use a second context and merge it with the "default" once, once the user has clicked on "save" on the drill-down View, like in the CoreDataBooks example from the Apple Documentation. That works well.
The problem starts when I set the relationship. Since the projects are in the “default” context, I can’t assign any project object to the project key in WorkTime, since they are in two different contexts.
So, should I copy all the projects into the “saving” context? Or should I use just one context for everything?
One problem that arises when I use only one context is that the tableview that shows the WorkTimes gets actualized when the user clicks on the addbutton (insertNewObjectForEntityForName). So the list grows right before it presents the new view controller (addWorkTimeDetail) in modalviewcontroller. And if the user clicks cancel in that detail view and decides not to save the WorkTime, I’d have to delete the newly created entity from the context. I don’t think this sounds the way to do it.
Suggestions would be very appreciated!
UPDATE
I'm still having some issues:
When the AddWorkTimeViewController is created from the RootViewController, I create a new NSObject WorkTime. When the user clicks "cancel" I delete the newly created WorkTime and return to the RootViewController. The FetchedResultsController actualizes the tableView and I see a short animation that comes because the object has been deleted. That's doesn't look nice.
I know it would be better to create the object ONLY if the user clicks "save" and by "cancel" do nothing, but I need that object in order to populate the drilldown views with values. The drilldown views work with a NSManagedObject. I see two possible ways to solve this:
1) Have a temporary object TempWorkTime subclassed from NSObject with the same attributes from the WorkTime NSManagedObject. I would create the TempWorkTime in the AddWorkTimeViewController and use it for the drilldown views. I would of course have to subclass them to accept an NSObject instead of a NSManagedObject. I guess type casting wouldn't work. When the user clicks "save", I would create a WorkTime NSManagedObject and pass it the values from the TempWorkTime.
2) Is it possible to trick the FetchedResultsController so that it doesn't update itself while the tableView is not visible? In that case, it would not respond to the changes in the context until it's back in view, and so it would not do the delete animation.
Any suggestions?
SECOND UPDATE - maybe it's useful for people trying to do this same thing
I found this link which proved to be very helpful:
http://www.timisted.net/blog/archive/multiple-managed-object-contexts-with-core-data/
It's very well explained why it's sometimes a good idea to use two contexts. I had some problems with using one context explained in the UPDATE part of my question.
Now I'm using two contexts and it works perfectly, even with relationships. Important is to use the NSManagedObjects of the second context when creating the relationship. That was my mistake when I started to work with this approach.
I don't see why you use two different contexts.
The way to do it is to pass your tableView's context to addWorkTimeDetail, and add any new WorkTimes to that context. If the user cancels, i.e. doesn't create a new object, there will be nothing new in the list when you return. If the user creates the new WorkTime in the context it was passed, it will show up in the list when you return.
In your example, use only one context, and pass it along to your subviews.
I found this link which proved to be very helpful:
http://www.timisted.net/blog/archive/multiple-managed-object-contexts-with-core-data/
It's very well explained why it's sometimes a good idea to use two contexts. I had some problems with using one context explained in the UPDATE part of my question.
Now I'm using two contexts and it works perfectly, even with relationships. Important is to use the NSManagedObjects of the second context when creating the relationship. That was my mistake when I started to work with this approach.

is it good practice to share the ADD and EDIT screen to use the same UIViewController?

is it good practice to share the ADD and EDIT screen to use the same UIViewController?
That is in the case where the only real difference would be in one the values would be populated with existing (EDIT).
PS. Some clarification. So perhaps take the simple case where there is just one or two NSString fields (e.g. title & description) - so is there anything wrong (e.g any gottchas) associated with using the same controller/NIB(view) for both EDIT and ADD?
Not sure about "good practise", but...
Populating a Label with one or another string is easy, also easy is hiding buttons or fields on depending if the ADD or EDIT view is displayed.
The problems tend to come when your view has received the user input and then needs to decide whether to modify an existing object or to create a new object.
So before exiting, the view has to decide how to treat user input. If the differentiation is mind boggling complex you are better off with two viewsControllers. If it is a matter of a simple if-the-else in or near the viewWillDisapper method then one view can do.
I would use inheritance in this case. Some base UIViewController and two additional UIViewControllers - one for add, second for editing. You can use one UIViewController too, but it depends on how difficult your task is or isn't. It's too general question.

Which pattern should be used for editing properties with modal view controller on iPhone?

I am looking for a good pattern for performing basic property editing via a modal view on the iPhone.
Assume I am putting together an application that works like the Contacts application. The "detail" view controller displays all of the contact's properties in a UITableView. When the UITableView goes into edit mode a disclosure icon is displayed in the cells. Clicking a cell causes a modal "editor" view controller to display a view that allows the user to modify the selected property. This view will often contain only a single text box or picker. The user clicks Cancel/Save and the "editor" view is dismissed and the "detail" view is updated.
In this scenario, which view is responsible for updating the model?
The "editor" view could update the property directly using Key-Value Coding. This appears in the CoreDataBooks example. This makes sense to me on some level because it treats the property as the model for the editor view controller.
However, this is not the pattern suggested by the View Controller Programming Guide. It suggests that the "editor" view controller should define a protocol that the "detail" controller adopts. When the user indicates they are done with the edit, the "detail" view controller is called back with the entered value and it dismisses the "editor" view. Using this approach the "detail" controller updates the model. This approach seems problematic if you are using the same "editor" view for multiple properties since there is only a single call-back method.
Would love to get some feedback on what approach works best.
I don't think any of the Apple examples (or anyone else's) actually show you how to structure an entire real world application. Instead, each example is just a test harness which shows you how to use one particular feature of the API but pays no attention to how that feature really integrates with anything else. Data models are given particularly short shift.
I prefer a design in which the data model is the spine of the application upon which hands all the view-controller/view pairs. The view controllers do not communicate with each other directly but instead communicate through the data model. The data model tracks what information the app is currently working on and therefore what data each particular view controller needs at any given time.
Let's use a contact manager type apps as an example. The basic of the data model would be a list of contact objects each of which in turn would hold attributes of a contact. The data model would completely control access to the data and monitors which data was currently being used. The UI is hierarchal such that the user first sees a list of all contacts in a masterView, then the details of each contact in a contactDetailView and then can edit each contact attribute in a custom attribute edit view for each type of data so there is a nameEditView, a phoneDetailView, an emailEditView etc. Each has a paired view controller masterVC, contactDetailVC, nameEditVC etc.
The to build it's tableview, the masterVC ask the data model for the number of contacts, their divisions into sections and then request each particular contact object at each particular index path so it can display a table. When the user selects a table row, the masterVC tells the data model which contact object was selected by sending it the index. Then the masterVC pushes the contactDetailVC. It does nothing else.
When the contactDetailVC activates, it ask the data model for the currently active Contact object. It doesn't know or care how the current contact was selected nor even which view/VC preceded it. The data model returns the currently active contact. When the user selects a field, the contactDetailVC tells the data model which attribute of the contact was selected and then pushes the proper editorVC onto the stack.
When the editorVC loads it ask for the data model for the current contact and the current attribute being edited. It doesn't know or care how the current contact attribute was selected nor even which view/VC preceded it. When the user makes a change, it ask the data model to save the change (the data model can refuse if verification fails for some reason) and then pops itself.
Internally, I like to implement the data model in two parts each managed by separate object. One is the abstracted data manager itself in this case a Core Data stack. The second is an user defaults manager that tracks the actual state of operations in the data model and saves them to user defaults. A master object holds these objects as attributes and serves as the interface of the data model.
This type of model makes it easy to suspend, resume or restart the application back to its previous state. Since each view/VC is self contained, when you restart the app, you just push all the views on the stack without animation and the last one pushed pops up fully populated with data even though the user chose nothing in the previous views and indeed did not even see them.
It also protects the user from data loss in the event of a crash since each VC saves its data and the app state every time it pushes or pops. It's easy to add additional view/VC because each VC only has to know about and communicate with the data model instead of bunch of other VC. It makes the components of the app easy to use in different versions of the app or in different apps altogether.
Edit:
Do you just hard code some if
statements to pair up the attributes
with the correct editor, or are you
doing something more dynamic based on
the entity/attribute metadata?
In most the most common design, the Contact entity could have a variable number of phone#s, emails or other data fields so each attribute would actually be a separate entity and the Contact would have a relationships pointing to those entities. When the user selected that contact to edit in the ContactDetailView, the data-model would simply mark the NSManagedObject representing the desired attribute of the contact. It could do so by setting an attribute like "lastChosenAttribute" or storing the URI for the object. When the editor view loaded it would be hard coded to ask the data-model for the "lastChosenAttribute" and would receive an NSManagedObject for a phone#, email etc. The editor would make changes to that object and they would be automatically saved back into the contact.
For data that is singular, such as a name or name components, the data-model would provide the editorVC with the contact entity and the editorVC would be hard coded to ask the contact object for that specific attribute.
It's a tough call--the View Controller Guide recommendation seems cleaner conceptually, but the other method can be easier, especially if you're using Core Data. To give a blanket generalized opinion, I would say use your first method if you're using Core Data, since managed objects inherently have their own context and can update themselves (and classes such as NSFetchedResultsController can automatically respond to updates).
If you're not using Core Data, I would go with the "official" recommendation, since it makes it easier to manage updated properties manually. As to the concern about multiple properties, it's certainly possible to have multiple delegate methods and call the appropriate one. For instance:
//if property is an address
if ([self.delegate respondsToSelector:#selector(editorView:didUpdateAddress:)])
[self.delegate editorView:self didUpdateAddress:theAddress];
//if property is a name
if ([self.delegate respondsToSelector:#selector(editorView:didUpdateName:)])
[self.delegate editorView:self didUpdateName:theName];
This could get hard to manage, though--you'd probably want to have an abstract superclass for properties, or something along those lines.

Applying user-entered data in one view to a second view

I'm trying to write an iphone OS app that includes a logbook feature. The problem that I'm having is that I want each new logbook to have its own categories that are user-defined, for example a chemical receipt log would have chemical name, vendor, receipt date, expiration date and comments.
The way that I'm trying to go about this is by calling an editCategory view controller when a new logbook is created that contains a number of UITextields where the user can enter the categories. I want to take those strings and apply them to a newLogEntry view controller, so that when the user creates a new log entry, they are presented with each category followed by a UITextfield so they can enter the relevant data.
The trick is, I have no idea how to grab the category data from editCategory and apply it to newLogEntry. I'm currently using Core Data, as that seems to be the easiest way to go about this, but I'm not married to it if it interferes with a good solution. Also, I'm still more comfortable with genetic code than objective-C code, so please bear with my ignorance.
Have you considered using the App Delegate? You could keep those values in the App Delegate, and call on them in the ViewDidLoad method of your newLogEntry view controller.