Does every ivar have to be in CoreData? - ios

This might be a completely dumb question, but I'm a CD noob...
I have an object that tracks rectangular points on maps by defining the top left and bottom right corners, like this...
#property (nonatomic) float latitudeNorth; // same as "northwest"
#property (nonatomic) float latitudeSouth; // same as "southeast"
#property (nonatomic) float longitudeEast; // same as "southeast"
#property (nonatomic) float longitudeWest; // same as "northwest"
Now I need to add four more points, so that we can have polys instead of pure rectangles. So I want to add this...
#property (nonatomic) float latitudeNorthEast;
#property (nonatomic) float latitudeSouthWest;
#property (nonatomic) float longitudeNorthEast;
#property (nonatomic) float longitudeSouthWest;
These data points are ephemeral and exist only as long as the app is running. They were, however, originally built in the xcdatamodeld. Is this a problem? Or am I find just adding the additional properties and using the old xcdatamodeld as-is?

I depends on you complete structure.
If you have some more entities that are fetched several times and saved again, and you need every time you fetch also the ephemeral properties, you have to hold them of course in the DB.
But if you only need them while you fetched and holding the Object, you can handle them just in class and there is no need to put them into the DB.
Not every item in the DB also has to be in the extracted class ;)
But the most attributes will also be saved, because they have to be updated via other services i.e. or have to present these updates in other views. Or maybe also because you don't want to hold the attributes all the time or will fetch them again (i.e. after a tableView.reloadData) and don't want to lose the calculated results

You can have other properties declared in your managed object subclass. They won't be initialized when you load up your object from a persistent store (when you close your app and open it up again, the values will go away), but you can get around that. However, there are better ways to do this. For example, you can write methods that calculate the values on the spot:
-(float)latitudeNorthEast;
-(float)latitudeSouthWest;
-(float)longitudeNorthEast;
-(float)longitudeSouthWest;
In your case, all that these methods do is return one of the other property values, so this seems like the way to go.

Related

Can KVO be used to deeply observe variable collections?

I get how to use K-V-O for simple property stuff. I have a model that looks like
#interface WateringScript : NSObject
#property (strong, nonatomic) NSMutableArray* spans; // holds WateringSpans
...
#end
#interface WateringSpan : NSObject
#property (strong, nonatomic) WateringAnchor* begin;
#property (strong, nonatomic) WateringAnchor* end;
...
#end
#interface WateringAnchor : NSObject
#property (assign, nonatomic) NSTimeInterval offset;
...
#end
Basically a top level object that holds a series of spans, the spans being defined as end and begin anchor objects, which amongst other things have an offset.
I have a custom view that would like to draw all of the offsets. Is there a simple way to observe all of the offsets? Such that as they change, or spans or added or removed, I can be notified of it and react accordingly?
Or do I have to observe the collection, and then on initial/add/remove changes observe and unobserve the collection elements? I think I could code this up if I have to, the real question is there KVO Juju that makes it easier?
You can't key-value observe through arrays. You have to observe the to-many property (spans) for changes to its content and separately observe the elements.
Once you handle addition and removal of elements so that you start and stop observing their properties, you can leverage that for the initial setup by specifying NSKeyValueObservingOptionInitial when you start observing the to-many property itself. You'll essentially be told that the initial elements have been "added".
For actually handling the added and removed elements, you can use -[NSArray addObserver:toObjectsAtIndexes:forKeyPath:options:context:] and -removeObserver:fromObjectsAtIndexes:forKeyPath: to start and stop observing their properties en masse.
It ends up being not too much code.

Correct way to declare properties

I am little confused about specifying strong, copy, or assign and not specifying them. We don't use NIB files. My colleague always use following - he says iOS detects it and use it automatically strong, weak etc.
#interface viewController : UIViewController
#property (nonatomic) UIImageView *imageView1;
#property (nonatomic) NSUInteger num;
#property (nonatomic) NSArray *array;
#end
I prefer following way doing it.
#interface viewController : UIViewController
#property (nonatomic, strong) UIImageView *imageView1;
#property (nonatomic, assign) NSUInteger num;
#property (nonatomic, copy) NSArray *array;
#end
Which one is better programming style? First option always have strong type as it defaults but I always specifies them explicitly.
As pointed out in earlier answers, in Objective C properties are by default,
atomic, strong/retain, readwrite --> For pointer types
atomic, assign, readwrite --> For primitive types
Property types weak, copy need to be explicitly specified by the programmer and in no way gets automatically decided.
What does each mean,
strong/retain referenced objects are kept alive in the memory until specified.
weak referenced objects will be destroyed when there is no strong reference. Typically used to reference delegate objects.
copy will create a shallow copy of the object getting assigned to the property.
assign/usafe_unretained(ARC) assigns the value. If used in case of pointer types this is an unsafe unretained assignment of the pointer. In ARC, typically use weak for pointer types because it will make the ivar=nil once weak referenced object is destroyed. assign in this case will lead to dangling pointer.
Personally, I prefer specifying property types even if it strong by default. This adds readability, which comes handy specially when profiling application for memory leaks or debugging crashes.
You can read more about properties here.
Hope that helps.
With ARC, strong is the default so the two are technically the same. From the Transitioning to ARC Release Notes:
__strong is the default. An object remains “alive” as long as there is a strong pointer to it.
Note that ARC will NOT automatically detect when something needs to be weak, however.
I tend to be explicit, like your second example, but I think it's mostly a matter of style/habit.
The default for a property is strongand for a variable is __strong too. In your current example the recommended property would actually be weak, but strong is acceptable too.
For properties of non-primitives you should no longer use assign, but rather unsafe_unretained. Practically they're the same, but the latter lets you know that you're using an object unsafely.
The copy property means that an object is copied (using the copy method) and not retained. It's recommended for classes such as NSString and NSArray, which have mutable forms. This is because you don't want to retain what you think is an immutable string but is actually being changed elsewhere.
The assign property declaration should be used only for primitive types and structs, e.g. int and CGSize.

how to make an array of UITableView #property's at build-time

How can I control the number of multiple UITableView's at build-time, using a single #define number?
My app presently needs 4 UITableView's. Later, the number will increase, so I want to control this at build-time with a single #define of how many.
But I get an error when I use an array in the #property declaration:
#define TOTAL_TX_CHANNELS 4
#interface blah() <UITableViewDataSource, UITableViewDelegate CBPeripheralDelegate>
{
}
#property (strong, nonatomic) UITableView* channel_tableView[ TOTAL_TX_CHANNELS ] ;
What's the trick? Should I use an NSArray or something?
Yes, use NSArray.
If it's configured in Interface Builder you could use:
#property (weak, nonatomic) IBOutletCollection (UITableView) NSArray * tableViews;
Why exactly do you need to control the # of UITableViews?
If you must do this, you could do some mathematical operation.
int adder = 4;
int currentNumberOfTvs = 4;
//Do some logic, that will add the number of current table views
if (...) //Test if user has added, or however, if another table view was added,
{
adder++;//now adder = 5. So you have a current count of how many table views there are
}
Hope that helps:)
I agree with the others that this is a terrible implementation. Wain's answer is very good.
However, still it is possible to implement it this way, just make sure to declare the property as
#property (assign, nonatomic) UITableView** channel_tableView;
Reference counting works only on Obj-C objects but you are creating a C array here.
Note that you have to use malloc to allocate the storage.
If you don't want to malloc, implement it as an ivar:
#interface Blah {
UITableView* channel_tableView[4];
}
#end
The solution was not to use an a property array, but to use an UITextView array at implementation scope, the .m...
UITextView* channel_pipe_textview[ TOTAL_TX_CHANNELS ];
Then, in function viewDidLayoutSubviews I created a UITableView for each channel, and added the standard functions for initializing the cells, all by following Apple's excellent UITableView programming guide.
It worked perfectly, completely independent of storyboard: I get four vertical side-by-side columns displaying any kind of images and text details regarding every device on the channel, with the ability to scroll, which allows any number of devices per channel.
The Apple UITableView Programming Guide also has tutorial and sample code for programmatically generating UITableViews solely at run-time.

How do i create this custom UI in iOS

I'm basically an Android programmer and on my way to learning some skills on iOS platform.
I have an Android application, which has a custom UI component which looks like
.
I want to create a similar re-usable UI component for my sample iOS application. I'm not able to get any lead on how to do this in iOS.
On Android I can create a composite UI element using a layout file but in iOS i'm not sure if i can create a composite UI element or extend UIView and then somehow layout Text and image components inside it.
I'm looking for some leads on implementing this. I plan to have a multiple instances of these component on screen & the values gets updated from a web service.
I recommend something called interface builder in iOS.
It is a place where you can visually place elements that the user interacts with and you can see how the design looks as you layout your structure.
For tutorials, you can look at http://mobile.tutsplus.com/tutorials/iphone/interface-builder/
or search up "ios xib tutorial"
Hope this helped!
If you want it to be a simple view, then you could create a UIView sub-class with a few UITextFields's and probably an UIImageView or two that all have outlets so that your controller can make changes to it. For instance:
#interface StockInfo <UIView>
#property (nonatomic, strong, readonly) UITextField *ticker;
// You may want to make these numbers so that you can do calculations with them, and then update the text field automatically
#property (nonatomic, strong, readonly) UITextField *price;
#property (nonatomic, strong, readonly) UITextField *priceChange;
// This could be automatically calculated based on the price and priceChange if appropriate
// It could also automatically show the Up or Down indicator
#property (nonatomic, strong, readonly) UITextField *percentChange;
#end
Then, your controller could create an instance and set the various properties:
StockInfo *djia = [[StockInfo alloc] init];
djia.ticker = #"DJIA";
djia.price = #"14550.35" ;
djia.priceChange = #"-111.66";
// ...
You can create the actual UI elements within the view either in Interface Builder, or do it in code. Which to do is kind of a personal preference. There are plusses and minuses to both, and building the view in code in this case would be pretty easy and not require you to have two files in order to use the control.

where to put a model's method?

I'm new to Core Data so I thought I'd ask this here.
I have a model, User Recording, which, for now, has the following:
#property (nonatomic, retain) NSDate * dateCreated;
#property (nonatomic, retain) NSData * audioData;
#property (nonatomic, retain) NSString * name;
What I'd really like is to have a method in there, called "play", to play the recording. Right now, I'm putting it in my view controllers but that's clearly bad because I've got that same method in two controllers. I've looked around a bit (and will keep looking) but can't figure it out - where should it go? Should I have a model controller (manager)?
Thanks.
your controller should have a hold to the model (that is, an instance variable or property), so that when the user clicks a button in the view (which should have an outlet to connect to the controller) you can invoke the message you want.
Just add the play method to your model (in the header file, so that is's public) and let the controller call that method when the user interacts with the view.

Resources