in my viewDidLoad I included this parameter to control the state of a button that I have in my custom cell of TableView ..
Obviously with "i<20" do a litime reuse of the cells but I need instead of the limit there is no ...
My tableView should display the list of users registered to the app and not having a user limit how can I remove the limit of cells?
Currently the value is <20 but I'm 24 users (it could also be 1000000) and the app crashes when I scroll the tableview ...
how can I fix this?
Graize to all and sorry for the stupid question
This is the code :
- (void)viewDidLoad {
[super viewDidLoad];
self.buttonPressedSelectedRowArray = [[NSMutableArray alloc] init];
int i = 0;
for (i=0; i<20; i++) {
[self.buttonPressedSelectedRowArray addObject:[NSNumber numberWithInt:0]];
}
}
Related
I would like to rearrange UICollectionView cells during the rotation of my device in a similar way this is done in the evernote iPads app for the notes. In the default implementation there is just a fade-in and fade-out of the cells but i would like to have the cells to move around during the rotation.
What would be the recommended way to achieve a similar animation? Do I need to create a custom UICollectionViewLayout?
I managed to get the desired rotation effect by subclassing UICollectionViewFlowLayout and overriding the two methods: initialLayoutAttributesForAppearingItemAtIndexPath and finalLayoutAttributesForDisappearingItemAtIndexPath which are the two points of controls to respectively define the starting/final layout information for an item being inserted into the collection view.
See source code:
.h:
#import "UICollectionView.h"
#interface UITestCollectionViewFlowLayout : UICollectionViewFlowLayout
#end
.m:
#import "UITestCollectionViewFlowLayout.h"
#interface UITestCollectionViewFlowLayout ()
{
BOOL _isRotating;
}
#property (strong, nonatomic) NSIndexPath* lastDissappearingItemIndex;
#end
#implementation UITestCollectionViewFlowLayout
#synthesize lastDissappearingItemIndex = _lastDissappearingItemIndex;
// returns the starting layout information for an item being inserted into the collection view
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes* attributes = (UICollectionViewLayoutAttributes *)[self layoutAttributesForItemAtIndexPath:itemIndexPath];
if (_isRotating) // we want to customize the cells layout only during the rotation event
{
if ([self.lastDissappearingItemIndex isEqual:itemIndexPath])
return nil; // do not animate appearing cell for the one that just dissapear
else
{
attributes.alpha = 0;
// setting the alpha to the new cells that didn't match the ones dissapearing is not enough to not see them so we offset them
attributes.center = CGPointMake(attributes.center.x, attributes.size.height * 2 + attributes.center.y);
}
}
return attributes;
}
// returns the final layout information for an item that is about to be removed from the collection view
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath*)itemIndexPath
{
UICollectionViewLayoutAttributes* attributes = (UICollectionViewLayoutAttributes *)[self layoutAttributesForItemAtIndexPath:itemIndexPath];
if (_isRotating)
{
attributes.alpha = 1.0;
self.lastDissappearingItemIndex = itemIndexPath;
}
return attributes;
}
- (void) viewController:(UIViewController *)viewController didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
_isRotating = NO;
}
- (void) viewController:(UIViewController *)viewController willRotateToInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration
{
_isRotating = YES;
}
Note that i am using a flag that i set from the viewcontroller who create this flowlayout to know when we are actually rotating or not; the reason being that i want this effect to happen only during rotation.
I am interested to hear feedbacks/improvement about this code.
I'm going to create a book shelf in one of my projects. The basic requirements are as follows:
similar to iBooks bookshelf
supports both orientations well
supports all kinds of iOS devices well (different resolutions)
supports deleting and inserting items
supports reordering of items by long press gesture
shows a hidden logo when first row is pulled down
The UICollectionView is the first option that occurred to me. It easily supports grid cells. So I googled it and found some very useful tutorials:
Bryan Hansen's UICollectionView custom layout tutorial
Mark Pospesel's How to Add a Decoration View to a UICollectionView
LXReorderableCollectionViewFlowLayout
And here is the result: (Please ignore the color inconsistency problem because of the graphics I chose are not perfect yet.)
What I did:
Created a custom layout by creating a class inherited from LXReorderableCollectionViewFlowLayout (for reordering purposes) which inherited from UICollectionFlowLayout
Added a decoration view for showing logo
Added a decoration view for showing the bookshelfs
But I ran into a few problems:
1. I can't scroll at all if the items can be shown in one screen
Then I added the following code, to make the contentsize bigger
- (CGSize)collectionViewContentSize
{
return CGSizeMake(self.collectionView.bounds.size.width, self.collectionView.bounds.size.height+100);
}
Then I can scroll now. Here I pull down the first row:
You can see the the decoration view for logo is working.
2. But I got the second set of problems when I pull up the last row:
You can see the decoration view is not added at the green box part.
3. The background of decoration view for bookshelf is getting darker and darker. (Please refer to same problem here
4. The book shelf bar sometimes moves when I reorder the items
I list some of the important code here:
- (void)prepareLayout
{
// call super so flow layout can do all the math for cells, headers, and footers
[super prepareLayout];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSMutableDictionary *shelfLayoutInfo = [NSMutableDictionary dictionary];
// decoration view - emblem
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
UICollectionViewLayoutAttributes *emblemAttributes =
[UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[EmblemView kind]
withIndexPath:indexPath];
emblemAttributes.frame = [self frameForEmblem:YES];
dictionary[[EmblemView kind]] = #{indexPath: emblemAttributes};
// Calculate where shelves go in a vertical layout
int sectionCount = [self.collectionView numberOfSections];
CGFloat y = 0;
CGFloat availableWidth = self.collectionViewContentSize.width - (self.sectionInset.left + self.sectionInset.right);
int itemsAcross = floorf((availableWidth + self.minimumInteritemSpacing) / (self.itemSize.width + self.minimumInteritemSpacing));
for (int section = 0; section < sectionCount; section++)
{
y += self.headerReferenceSize.height;
//y += self.sectionInset.top;
int itemCount = [self.collectionView numberOfItemsInSection:section];
int rows = ceilf(itemCount/(float)itemsAcross)+1; // add 2 more empty row which doesn't have any data
for (int row = 0; row < rows; row++)
{
indexPath = [NSIndexPath indexPathForItem:row inSection:section];
shelfLayoutInfo[indexPath] = [NSValue valueWithCGRect:CGRectMake(0,y, self.collectionViewContentSize.width, self.itemSize.height + DECORATION_HEIGHT)];
y += self.itemSize.height;
if (row < rows - 1)
y += self.minimumLineSpacing;
}
y += self.sectionInset.bottom;
y += self.footerReferenceSize.height;
}
dictionary[[ShelfView kind]] = shelfLayoutInfo;
self.shelfLayoutInfo = dictionary;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributesArrayInRect = [super layoutAttributesForElementsInRect:rect];
// cell layout info
for (BookShelfLayoutAttributes *attribs in attributesArrayInRect)
{
attribs.zIndex = 1;
CATransform3D t = CATransform3DIdentity;
t = CATransform3DTranslate(t, 0, 0, 40);
attribs.transform3D = CATransform3DRotate(t, 15 * M_PI / 180, 1, 0, 0);
}
// Add our decoration views (shelves)
NSMutableDictionary* shelfDictionary = self.shelfLayoutInfo[[ShelfView kind]];
NSMutableArray *newArray = [attributesArrayInRect mutableCopy];
[shelfDictionary enumerateKeysAndObjectsUsingBlock:^(id key, NSValue* obj, BOOL *stop) {
if (CGRectIntersectsRect([obj CGRectValue], rect))
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[ShelfView kind] withIndexPath:key];
attributes.frame = [obj CGRectValue];
NSLog(#"decorationView rect = %#",NSStringFromCGRect(attributes.frame));
attributes.zIndex = 0;
//attributes.alpha = 0.5; // screenshots
[newArray addObject:attributes];
}
}];
attributesArrayInRect = [NSArray arrayWithArray:newArray];
NSMutableDictionary* emblemDictionary = self.shelfLayoutInfo[[EmblemView kind]];
NSMutableArray *newArray2 = [attributesArrayInRect mutableCopy];
[emblemDictionary enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *innerStop) {
if (CGRectIntersectsRect(rect, attributes.frame)) {
[newArray2 addObject:attributes];
}
}];
attributesArrayInRect = [NSArray arrayWithArray:newArray2];
return attributesArrayInRect;
}
I'll appreciate if you're patient enough to read this post and provide any advice or suggestions. And I'll post the complete source code if I can fix all the issues. Thank you in advance.
I would suggest to check your last row and do the [self.collectionView ScrollEnable:NO] same for first row, set background color clear of collectionView and collectionViewCell and that bookshelf image sets on background view.
I'm make an iPhone app, in this app the user can send a SMS.
On my iPhone 4 is my screen perfect, but on my iPhone 5 i get a blank box.
iPhone only. iOS 6x
Screenhot (iphone5): http://i.stack.imgur.com/ZOqu1.png
#import "smsview.h"
#interface smsview ()
#end
#implementation smsview
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
if (result == MessageComposeResultCancelled)
NSLog(#"Message cancelled");
else if (result == MessageComposeResultSent)
NSLog(#"Message sent");
else
NSLog(#"Message failed");
}
- (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
-(IBAction)Text:(id)sender
{
{
[self sendSMS:#"" recipientList:[NSArray arrayWithObjects:#"+1-234-567-8910", nil]];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Follow these steps if u failed to.
Are you using the latest version of Xcode if not download from here.
You can use the Auto layout feature and create the design the using iPhone 5 screen resolution and it will work for the both 4" and 3.5" devices, but in this case you should have a enough knowledge of layout manager.
Set a 4-inch launch image for your app. This is how you get 1136 px screen height (without it, you will get 960 px with black margins on top and bottom), To adapt your app to the new taller screen, the first thing you do is to change the launch image to: Default-568h#2x.png. Its size should be 1136x640 (HxW). Yep, having the default image in the new screen size is the key to let your app take the whole of new iPhone 5's screen..
Hopefully everything should work if you had set auto resizing masks properly.
If you didn't, adjust your view layouts with proper auto resizing masks or look into Auto Layout if you only want to support iOS 6 going forward.
If there is something you have to do for the larger screen specifically, then it looks like you have to check height of [[UIScreen mainScreen] bounds] (or applicationFrame, but then you need to consider status bar height if it's present) as there seems to be no specific API for that.
for instance:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
//iPhone 4 specific
} else {
//iPhone 5 specific
}
Hope this solves your problem.
I have a series of images that I want to make use of in an app. What I wanted to do is store them in an NSArray for easy identification within the drawRect: function.
I have created a .plist file, which details an NSDictionary with the keys simply ascending integer values, and the values corresponding to the image file names. This allows me to iterate through the dictionary and add a series of NSImage objects into the array. I am using a for loop here because the order is important and fast enumeration does not guarantee order of execution when reading from a dictionary!
Currently I am doing the following: (This is in a Subclass of NSView)
#property (strong) NSDictionary *imageNamesDict;
#property (strong) NSMutableArray *imageArray;
...
// in init method:
_imageNamesDict = [[NSDictionary alloc] initWithContentsOfFile:#"imageNames.plist"];
_imageArray = [[NSMutableArray alloc] initWithCapacity:[_imageNamesDict count]];
for (int i=0; i<_imageNamesDict.count; i++) {
NSString *key = [NSString stringWithFormat:#"%d", i];
[_imageArray addObject:[NSImage imageNamed:[_imageNamesDict objectForKey:key]];
}
// When I want to draw a particular image in drawRect:
int imageToDraw = 1;
// Get a pointer to the necessary image:
NSImage *theImage = [_imageArray objectAtIndex:imageToDraw];
// Draw the image
NSRect theRect = NSMakeRect (100,100, 0, 0);
[theImage drawInRect:theRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
This all appears to work properly, but with one quirk. I have noticed a small amount of lag that happens in drawing the display, but only when drawing a new image for the first time. Once each image has been seen at least once, I can re-draw any desired image with no lag whatsoever.
Is it that I am not loading the images properly, or is there some way that I can pre-cache each image when I create the objects to add to the for loop?
Thanks!
Assuming you have overcome the "... NSMutableDictionary instead of an NSMutableArray ..." problem pointed out in the comments, you are loading the images properly.
The lag you are describing is because [NSImage imageNamed: ] doesn't do all the work required to draw the image, so that is happening on your first draw.
You could probably get rid of the lag by drawing the images into an offscreen buffer as you add them to your array, something like:
// Create an offscreen buffer to draw in.
newImage = [[NSImage alloc] initWithSize:imageRect.size];
[newImage lockFocus];
for (int i=0; i<_imageNamesDict.count; i++) {
NSString *key = [NSString stringWithFormat:#"%d", i];
NSImage *theImage = [NSImage imageNamed:[_imageNamesDict objectForKey:key]];
[_imageArray addObject: theImage];
[theImage drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
}
[newImage unlockFocus];
[newImage release];
I have a predicament, in as much that I need to create an arbitrary amount of UIView Objects. I have an NSArray and what I need to do is create UIView Objects for the number of items in the array, so I got an int from the [NSArray count]; method, so I know the number of objects needing creating, but the way to implement this has me stumped. I'll include some psudocode below to attempt to give across what I need to do:
[UIView returnMultipleUIViewsForInt:[theArray count]];
Obviously that won't work, but some way of creating an arbitrary amount of objects at runtime, which I can work with would be good.
So in short:
I need to create a certain number of UIViews based upon the number of items in an array.
I then need to access each view that is created and use it as a regularly created view might be used, doing things like adding one of them as a subview to a different view.
- (NSArray *)createNumberOfViews:(NSInteger)number
{
NSMutableArray *viewArray = [NSMutableArray array];
for(NSInteger i = 0; i < number; i++)
{
UIView *view = [[UIView alloc] init];
// any setup you want to do would go here, e.g.:
// view.backgroundColor = [UIColor blueColor];
[viewArray addObject:view];
[view release];
}
return viewArray;
}
NSMutableArray *newViews = [NSMutableArray array];
for (int i=0; i<[theArray count]; ++i) {
UIView *view = [[UIView alloc] init];
[newViews addObject:view];
[view release];
}