Programmatically setting NSLayoutConstraints for UITableView and UISearchBar - ios6

I've got a UIViewController that does add a UISearchBar and a UITableView in it's -viewDidLoad method as subviews of it's view property. After adding those, I create constraints using the visual format language like this:
NSDictionary *views = #{#"searchBar": [_searchController searchBar],
#"dataTable": [self tableView]};
NSArray *horizontalSearchBarConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[searchBar]|"
options:0
metrics:nil
views:views];
NSArray *horizontalDataTableConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[dataTable]|"
options:0
metrics:nil
views:views];
NSArray *verticalSearchBarDataTableConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[searchBar(44)][dataTable]|"
options:0
metrics:nil
views:views];
NSMutableArray *allConstraints = [NSMutableArray new];
[allConstraints addObjectsFromArray:horizontalDataTableConstraints];
[allConstraints addObjectsFromArray:horizontalSearchBarConstraints];
[allConstraints addObjectsFromArray:verticalSearchBarDataTableConstraints];
[[self view] addConstraints:allConstraints];
Read: The widths should be the whole screen's width, the searchBar's height should be exactly 44 and the dataTable's height should stretch out from the bottom of the searchBar to the bottom of the view.
Before doing that, I set translatesAutoresizingMaskIntoConstraints for those views to NO. The UIViewController itself gets presented in a modal view. We're talking iOS 6.
What I get: An empty view. Just plain white.
What did I miss? I'm still new to Auto Layout and try to wrap my head around it.
Thanks!
Update: Adding the entire -viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
BOOL translatesAutoreszingMaskIntoConstraints = NO;
[[self view] setTranslatesAutoresizingMaskIntoConstraints:translatesAutoreszingMaskIntoConstraints];
// manually create the search bar
UISearchBar *searchBar = [[UISearchBar alloc] init];
[searchBar setDelegate:self];
[searchBar setShowsCancelButton:NO];
[searchBar setTranslatesAutoresizingMaskIntoConstraints:translatesAutoreszingMaskIntoConstraints];
// create the search bar controller
_searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
[_searchController setDelegate:self];
[[_searchController searchResultsTableView] setDelegate:self];
[_searchController setSearchResultsDataSource:self];
[_searchController setSearchResultsDelegate:self];
// add the search bar
[[self view] addSubview:[_searchController searchBar]];
// manually create the table view and add it to the view
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
[_tableView setBackgroundView:nil];
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLineEtched];
[_tableView setSeparatorColor:NEA_COLOR_MEDIUM_GREY];
[_tableView setBackgroundColor:NEA_COLOR_VIEW_BACKGROUND];
[_tableView setDataSource:self];
[_tableView setDelegate:self];
[_tableView setTranslatesAutoresizingMaskIntoConstraints:translatesAutoreszingMaskIntoConstraints];
[[self view] addSubview:[self tableView]];
// set up the layout using Auto Layout
NSDictionary *views = #{#"searchBar": [_searchController searchBar],
#"dataTable": [self tableView]};
NSArray *horizontalSearchBarConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[searchBar]|"
options:0
metrics:nil
views:views];
NSArray *horizontalDataTableConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[dataTable]|"
options:0
metrics:nil
views:views];
NSArray *verticalSearchBarDataTableConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[searchBar(44)][dataTable]|"
options:0
metrics:nil
views:views];
NSMutableArray *allConstraints = [NSMutableArray new];
[allConstraints addObjectsFromArray:horizontalDataTableConstraints];
[allConstraints addObjectsFromArray:horizontalSearchBarConstraints];
[allConstraints addObjectsFromArray:verticalSearchBarDataTableConstraints];
[[self view] addConstraints:allConstraints];
// add our little gradient
UIImage *shadow = [UIImage imageNamed:#"searchbar_bg_shadow"];
UIImageView *shadowView = [[UIImageView alloc] initWithImage:shadow];
[shadowView setFrame:CGRectMake(0, 44, 900, 14)];
[shadowView setBackgroundColor:[UIColor clearColor]];
[shadowView setTranslatesAutoresizingMaskIntoConstraints:YES];
[[self view] addSubview:shadowView];
// add the cancel button for the search bar
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"ui_navigationbar_close"] style:UIBarButtonItemStyleBordered target:self action:#selector(cancel:)];
[[self navigationItem] setRightBarButtonItem:cancelButton];
// set a short back button title
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
}
Update: Additional Infos
The encapsulating UINavigationController is being created through a storyboard. In there, added a UIViewController set to my class as it's rootViewController. Thats all.
When I manually add the width in that format string, it displays the views. So when I manually specify the sizes, it works. But then, I guess, I could simply use frames instead…

I don't know if your issue was resolved or not, but I noticed a potential problem in your code.
Try eliminating the following line of code:
[[self view] setTranslatesAutoresizingMaskIntoConstraints:translatesAutoreszingMaskIntoConstraints];
Don't set that property to NO for the root view.

Related

Accessing Array Values in other instances

In my application, I am trying to access the array values but the array is return zero values. I have been stuck on this for a few hour now, and cannot seem to solve it. So any help would be appreciated:
#implementation MyScene{
NSMutableArray *_touchPoints;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [[touches anyObject] locationInNode:self.scene];
[self clearTouchPoints];
[self addTouchPointToMove:touchPoint];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint touchPoint = [[touches anyObject] locationInNode:self.scene];
CGPoint targetPoint = CGPointMake(touchPoint.x , touchPoint.y - delta.y);
[self addTouchPointToMove:touchPoint];
NSLog(#"Value: %lf", touchPoint.y);
}
- (void)move:(NSNumber *)_tempTime{
CGPoint currentPoint = [_touchPoints[0] CGPointValue];
CGPoint targetPoint = [_touchPoints[1] CGPointValue];
NSLog(#"Check Value: %lf", targetPoint.y);
}
- (void)addTouchPointToMove:(CGPoint)point {
[_touchPoints addObject:[NSValue valueWithCGPoint:point]];
}
- (void)clearTouchPoints {
[_touchPoints removeAllObjects];
}
The array is never initialized (e.g., _touchPoints = [NSMutableArray new];) so it is nil. Attempting to invoke methods on a nil object does nothing, nor does it complain (i.e., does not throw an exception). So in the addTouchPointToMove method:
[_touchPoints addObject:[NSValue valueWithCGPoint:point]];
does nothing.
In the init method, initialize the array.

Create an array of UiImageVIews to feed iCarousel from 2 arrays

I am trying to create an NSMutableArray of UIImageViews to feed an iCarousel. Each UIImageView is to have a thumbnail of a video and labels for name and length.
I have found that creating the video thumbnails as the iCarousel loads leads to an unacceptable delay once there are more than 10 video thumbnails are loaded. i haven't found an asynchronous way to create the video thumbnails as they are required by the iCarousel.
The current solution I'm trying to make work is to save both the video and a matching thumbnail to the apps documents folder at the time the video is saved. These are then loaded into 2 time sorted arrays ( with exactly the same count ).
The puzzle I'm trying to solve is what is the best way to create the new array of UIImageViews using the thumbnail image from one array and the name and video length from the video with the matching index in the second array.
I was previously creating the thumbs and labels from an array of just the videos using this code.
UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 135.0f)];
((UIImageView *)view).image = [UIImage imageNamed:#"page.png"];
view.contentMode = UIViewContentModeCenter;
UIImage *thumb = [UIImage imageWithContentsOfFile:anyPath];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:view.bounds];
imageView.tag = 1000;
[imageView setImage:thumb];
[view addSubview:imageView];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150.f, 200.f, 25.f)];
[nameLabel setTextAlignment:NSTextAlignmentLeft];
[nameLabel setTag:2000];
[nameLabel setTextColor:[UIColor whiteColor]];
[nameLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:12.f]];
[nameLabel setText:anyPath.lastPathComponent];
[view addSubview:nameLabel];
UILabel *lengthLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150.f, 200.f, 25.f)];
[lengthLabel setTextAlignment:NSTextAlignmentRight];
[lengthLabel setTag:3000];
[lengthLabel setTextColor:[UIColor whiteColor]];
[lengthLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:12.f]];
[lengthLabel setText:[MediaManager lengthOfVideoWithPath:anyPath]];
[view addSubview:lengthLabel];
Any suggestions would be greatly appreciated.
OK the solution was to use a block to create the array of UIImageViews from the 2 Arrays like so ( this loads the carousel quickly)
[self.aryVideos enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 135.0f)];
((UIImageView *)view).image = [UIImage imageNamed:#"page.png"];
view.contentMode = UIViewContentModeCenter;
UIImage *thumb = [UIImage imageWithContentsOfFile:self.aryThumbs[idx]];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:view.bounds];
imageView.tag = 1000;
[imageView setImage:thumb];
[view addSubview:imageView];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150.f, 200.f, 25.f)];
[nameLabel setTextAlignment:NSTextAlignmentLeft];
[nameLabel setTag:2000];
[nameLabel setTextColor:[UIColor whiteColor]];
[nameLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:12.f]];
NSString *path = [item lastPathComponent];
[nameLabel setText:path];
[view addSubview:nameLabel];
UILabel *lengthLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150.f, 200.f, 25.f)];
[lengthLabel setTextAlignment:NSTextAlignmentRight];
[lengthLabel setTag:3000];
[lengthLabel setTextColor:[UIColor whiteColor]];
[lengthLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:12.f]];
[lengthLabel setText:[MediaManager lengthOfVideoWithPath:item]];
[view addSubview:lengthLabel];
[self.aryThumbViews addObject:view];
}];

Core data - how to get records from an entity and add them to another entity

I have two entities: TempProducts and Products
TempProducts is populated in TableView.
The user must enter the data in the tableview.Than when he clicks on a button i need to get all records from TempProducts and add them to Products.After that i delete all TempProducts in order the table to be empty for next time.
- (IBAction)saveData:(id)sender
{
//FETCH ALL RECORDS OF TEMPPRODUCTS
NSFetchRequest * allTempProducts = [[NSFetchRequest alloc] init];
[allTempProducts setEntity:[NSEntityDescription entityForName:#"TempProducts" inManagedObjectContext:self.managedObjectContext]];
[allTempProducts setIncludesPropertyValues:NO]; //only fetch the managedObjectID
//FETCH ALL RECORDS OF TEMPPRODUCTS
NSFetchRequest * allProducts = [[NSFetchRequest alloc] init];
[allProducts setEntity:[NSEntityDescription entityForName:#"Products" inManagedObjectContext:self.managedObjectContext]];
[allProducts setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError * error = nil;
NSArray * tProducts = [self.managedObjectContext executeFetchRequest:allTempProducts error:&error];
NSArray * products = [self.managedObjectContext executeFetchRequest:allProducts error:&error];
NSLog(#"The array TempProducts has %li records", [tProducts count]);
NSLog(#"The array Products has %li records", [products count]);
//-------------------------------------------------------------------------
//ADD OBJECT TO PRODUCTS
NSManagedObjectContext *con = [self managedObjectContext];
NSManagedObject *countryObject=[NSEntityDescription
insertNewObjectForEntityForName:#"Products"
inManagedObjectContext:con];
//--------------------------------------------------------------------------
//error handling goes here
for (NSManagedObject * tProduct in tProducts) {
[self.managedObjectContext deleteObject:tProduct];
}
NSError *saveError = nil;
[self.managedObjectContext save:&saveError];
//more error handling here
}
You could solve it by using only one entity: Products, but with one additional boolean attribute isTemp. It would simplify the use case you describe, but might complicate other parts of the code, e.g. in every fetch you'd have to remember to fetch only temporary or not temporary objects.

Xcode Storyboard segue to pass song title from array to detail view controller

I get this error message:-[MPConcreteMediaItem isEqualToString:]: unrecognized selector sent to instance…
I am creating an NSMutable array of songs from media picker into an array named "array". This array shows up properly in the tableview (myTable). HOWEVER when I try to segue to the detail view and send the song title to a label on the detail view following this tutorial. I get the crash and error message above.
Appreciate any help, thanks!
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"detailView"]) {
NSIndexPath *indexPath = [self.myTable indexPathForSelectedRow];
DetailViewController *vc = [segue destinationViewController];
vc.trackName = [array objectAtIndex:indexPath.row];
//crashes -[MPConcreteMediaItem isEqualToString:]: unrecognized selector sent to instance
}
}
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
[array addObjectsFromArray:mediaItemCollection.items];
[myTable reloadData];
// mediaItemCollection = nil;
[mediaPicker dismissViewControllerAnimated:YES completion:nil];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//this method is called to fill out table with data
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
// Configure the cell
anItem = nil;
anItem = [array objectAtIndex:indexPath.row];
cell.textLabel.text = [anItem valueForProperty:MPMediaItemPropertyTitle];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
The error looks like that you aren't calling 'isEqualToString:' on a string object... Which superclass has MPConcreteMediaItem

Print a specific value from ios UITABLEVIEW

SOffer[26229:c07] current Product: (
{
id = 20;
image = "img2.png";
name = "offer 2";
}
)
I have product which result the above when I print it through NSLog,, I need to print the these individually. Following code generate this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
NSString *currentProductName;
currentProductName = [productKeys objectAtIndex:indexPath.row];
currentProduct = [products objectForKey:[productKeys objectAtIndex:indexPath.row]];
NSLog(#"current Product: %#",currentProduct);
//currentProductName = [currentProduct objectForKey:#"image"];
//currentProduct = [currentProduct ];
[[cell textLabel] setText:currentProductName];
return cell;
}
currentProduct is declared as NSArray but when i try to print with objectForKey it say No visible interface for NSArray declares the selector ObjectForKey
objectForKey, I believe works with NSDictionary only.
NSArray does not have key value pairs. Unless currentProduct holds the JSON file, then you gonna have to first get out the Array Object of the first Product and assign it to a NSDictionary, where you can then use the objectForKey to get your image value.
Something like this:
// Get the first product object from the NSArray. Assuming you dropped your entire Product values into a NSArray
NSMutableDictionary *prodDict = [currentProduct objectAtIndex:indexPath.section];
NSString *prodID = [prodDict objectForKey:#"id"];
NSString *prodName = [prodDict objectForKey:#"name"];
...

Resources