I find calling invalidateLayout in iOS8 to cause crashy behaviour, probably due to the new invalidateLayout with contexts introduced last WWDC. Still, I haven't found an equivalent to invalidating the whole collection view layout.
Say I want it all to happen exactly like iOS7's invalidateLayout. What should be done?
iOS7: [collectionView.collectionViewLayout invalidateLayout];
iOS8: ???
As of iOS 8 you will want to invalidate the layout within a batch update block:
[collectionView performBatchUpdates:^{
[layout invalidateLayout];
} completion:nil];
Related
I've been working a photo editing app that takes pictures and passes it on to the
next view controller.
Of course I use AVSession to have the camera preview shown.
When the picture is taken the current view controller passes the image on to the view controller that has all the editing features.
I use modal segues to control transition between views.
The Problem is that when the segue happens there is a increase in memory by 4mb that never gets released.
Viewcontoller-->EditorViewcontoller
EdiorViewcontroller-->Viewcontroller
I also have a segue from the editor to camera,again there is a accumulation of memory.
A few times back and forth and the app crashes.
I can't post picture due to lack of reputation.
How can I clean the memory of the previous Viewcontroller and just have the current view controller running.
Things I've tried
*setting all the instances to nil.
*dismissing the view controller.
*setting the entire view controller to nil.
*profiled it.
*using #autorealease.
*spent hours on the internet searching for a solution.
I use this line of code to perform the segue.
[self performSegueWithIdentifier:#"effectsegue" sender:self];
I even tried using a weak self hoping it might help.
__weak ViewController *weakself=self;
[weakself performSegueWithIdentifier:#"effectsegue" sender:self];
When I profile it,it tells me these lines of code
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
and
[self performSegueWithIdentifier:#"effectsegue" sender:self];
are taking memory.
I would like some suggestions and idea as to what can be done to clear memory of previous view controller and free memory,any other alternates other than segues.
I've been working on this for weeks and this is really not allowing me to proceed forward.
Thanks in advance.
If you're using storyboards and ARC you can create a button inside EditorViewcontroller (that you'll use to go back to Viewcontroller) and link it to the following action on your EditorViewcontroller.m file:
- (IBAction)goBack:(UIButton *)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
This should release the memory used by EditorViewcontroller
I am building an App that needs to be able to refresh by pulling, and then re-run the ViewDidLoad.
So I know i could use a UIRefreshControl, but I can only find code that is used in a UITableViewController.
Has anyone got an idea on how to use a UIRefreshControl in a UIView instead of in a UITableView.
Thanks in advance.
try this…
[myView setNeedsDisplay];
this would reload your view controller. you can put this in a method and call it during pull to refresh…Hope this helps you.
Happy coding ;)
Very easily:
Keep the control as amember or property:
UIRefreshControl *_refreshControl;
Add this to your viewDidLoad method: (simply adding the control to your tableView. make sure the tableView is not nil ofcourse).
_refreshControl = [[UIRefreshControl alloc] init];
[_refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[_tableView insertSubview:_refreshControl atIndex:0];
implement the refresh method:
- (void)refresh:(UIRefreshControl *)refreshControl {
[self reloadData];
//Don't forget to stop the refreshing animation after data reloads.
[_refreshControl endRefreshing];
}
UIRefreshControl isn't meant to be used without a table. This note in the documentation specifically warns against such use:
Note: Because the refresh control is specifically designed for use in a table view that's managed by a table view controller, using it in
a different context can result in undefined behavior.
So although it may be possible to get the control to work, you really shouldn't use it without a table. Rolling your own refresh control is a better solution.
Better still, try to engineer your app such that the user doesn't need to refresh the view. The app should know when new data is available. The only excuse for making the user refresh is if doing so automatically would somehow confuse the user or otherwise make the app more difficult to use.
I have troubles with NSArrayController rearrangeObjects function - this function called from some background treads and sometimes App crashes with error: 'endUpdates called without a beginUpdates'.
How can i detect if arrayController is rearranging objects in current moment and add next rearrange to some like queue or cancel current rearranging and run new?
May be there is another solution for this problem?
Edit code added:
TableController implementation:
- (void)setContent{//perfoms on main thread
//making array of content and other functions for setting-up content of table
//...
//arrayController contains objects of MyNode class
//...
//end of setting up. Call rearrangeObjects
[arrayController rearrangeObjects];
}
- (void)updateItem:(MyNode *)sender WithValue:(id)someValue ForKey:(NSString *)key{
[sender setValue:someValue forKey:key];
[arrayController rearrangeObjects];//exception thrown here
}
MyNode implementation:
- (void)notifySelector:(NSNotification *)notify{
//Getted after some processing finished
id someValue = [notify.userInfo objectForKey:#"observedKey"];
[delegate updateItem:self WithValue:someValue ForKey:#"observedKey"];
}
Don't do that. AppKit (to which NSArrayController belongs) is not generally thread safe. Instead, use -performSelectorOnMainThread:... to update your UI (including NSArrayController). ALWAYS do updating on the main thread.
Joshua and Dan's solution is correct. It is highly likely that you are performing operations on your model object in a background thread, which then touches the array controller, and hence touches the table.
NSTableView itself is not threadsafe. Simply adding in a "beginUpdates/endUpdates" pair will just avoid the race condition for a bit. However, like Fin noted, it might be good to do the pair of updates for performance reasons, but it won't help with the crash.
To find the sources of the crash, add some assertions in your code on ![NSThread currentThread].mainThread -- particularly any places before you touch the array controller's content. This will help you isolate the problem. Or, subclass NSTableView and add the assertion in somewhere key, like overriding -numberOfRows (which is called frequently on changes), and calling super.
-corbin
AppKit/NSTableView
I solved this by adding this at the very start of my UI initialisation
[myTableView beginUpdates];
and then at the end after the persistant store has been loaded fully:
[myTableView endUpdates];
This also make the app startup a lot better since it does not constantly have to reload all loads from the MOC.
I am using latest Xcode, and trying to find memory leaks.
When i use 'Analyze'
It shows following as potential leak:
+ (UITableViewCell *) method {
UITableViewCell *cell = [[TestX alloc]init];
... do some stuff
return [cell autorelease];
}
Should i just ignore it ?
No, you shouldn't ignore warnings. Sometimes Xcode is buggy and forgets you've changed the code. Try restarting Xcode. Remove do some stuff so that it's just the two lines and see if the analyser stops warning you. It could be the case that you're affecting the retain count in that code somewhere without realising it.
You need to name the method properly to show that it's returning an autoreleased object. I forget the preferred name. Try something like 'newObject'.
I have a list view class that just like NSCollectionView requires an additional prototype item and a prototype view to be of any use.
When dropping an NSCollectionView from the library in Interface Builder those two helper items are automatically created. However I couldn't find a single official Apple document dealing with this use case (describing how its done).
Digging thru the Apple Dev Guides I could however find "ibDidAddToDesignableDocument:".
With the following code I managed to get my auxiliary items created on drop from library:
- (void)ibDidAddToDesignableDocument:(IBDocument *)document {
[super ibDidAddToDesignableDocument:document];
NSView *prototypeView = [[[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 65.0)] autorelease];
DLListViewItem *prototypeViewItem = [[[DLListViewItem alloc] initWithNibName:nil bundle:nil] autorelease];
[document addObject:prototypeViewItem toParent:nil];
[document addObject:prototypeView toParent:nil];
[document connectOutlet:#"view" ofSourceObject:prototypeViewItem toDestinationObject:prototypeView];
[document connectOutlet:#"listView" ofSourceObject:prototypeViewItem toDestinationObject:self];
[document connectOutlet:#"prototypeItem" ofSourceObject:self toDestinationObject:prototypeViewItem];
}
However…
…IB adds those aux items for NSCollectionView only on the actual initial drag from the library, not on any other call of "ibDidAddToDesignableDocument:", such as when embedding, copying or duplicating the item. (while my method would, and on all)
This makes me wonder whether Apple actually uses "ibDidAddToDesignableDocument:" for this and if I'm on the right track with this at all.
How does one imitate this properly? I'm having a hard time trying to distinguish between different contexts for "ibDidAddToDesignableDocument:". Anybody successfully done this?
Unfortunately none of Google, Google Code, GitHub, or the documentation revealed anything helpful, so I'm in desperate need of help here. :(
Thanks in advance!
Edit: Oh great, this question just brought me the tumbleweed badge, yay! Not.
I'm more into useful answers actually, but thanks anyway ;)
I struggled with this on a plugin I did myself a while ago. In my case I was able to check a property of the object to see if it had been initialized already and skip adding the auxilliary objects in that case. I believe BWToolkit uses some internal checking that is similar. Couldn't you check your object's 'prototypeItem' property to see if you need to skip creating your aux objects?