i dont know what is wrong with code below
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray * buttons;
NSMutableArray * centers;
int counter;
int index;
}
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
buttons = [NSMutableArray new];
centers = [NSMutableArray new];//error here expected identifier or '('
}
//other methods
#end
i am getting two arrays, xcode works normally for buttons but it gives error for centers when creating. What may be the problem?
note: i tried deleting derived data.
Okay, I know this isn't the question you asked, but I would like to suggest an alternative to instantiating variables in viewDidLoad. It's something called "lazy instantiation", and it looks like this:
- (NSMutableArray *)buttons
{
if (!_buttons) _buttons = [NSMutableArray new];
return _buttons;
}
When you need to reset the array, just set it to nil. It won't reallocate the memory until you call it again.
P.S. Whatever you do, don't call self.buttons within that method, or you will create an infinite loop.
Related
every time i make a request to my web server via NSURLSession/Connection it leaks! To be honest it is not much but if you have to make a couple hundreds or thousands of calls this gets nasty.
I have been on this for about a week now. I have tried everything. NO cache , little cache, setting everything on nil after the call is done(which is unnecessary), using datatask for sessions or just connection with requests. Every time i get a little more memory allocated and i have not found a way to solve this problem.
So i set up a little testApp:
#import "ViewController.h"
#interface ViewController ()
#property NSString *param;
#property NSURL * url;
#property NSURLConnection *test;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.param = [NSString stringWithFormat:#"hi"];
self.url = [[NSURL alloc]initWithString:#"http://127.0.0.1/xmlfile.php"];
for (int i = 0; i<20000; i++){
[self connect:self.param url:self.url];
}
NSLog(#"I AM DONE!");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSData *)connect:(NSString*)param url:(NSURL*)url{
self.test = [[NSURLConnection alloc]initWithRequest:nil delegate:self];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
return nil;
}
#end
i would love to add images of the memory usage but i am too new.
so just go here:
5k:iterations
http://i59.tinypic.com/123tts2.png
20k:
http://i59.tinypic.com/1zzqsrk.png
I have heard that this could be a problem with ios8.
Please help!
I am open for everything and would be happy if someone could prove me wrong and show me the right way. Thanks a bunch
You're never actually turning your URL into a request and giving it to the NSURLConnection. Because of that, the connection will never complete, and its memory will stay allocated. You'll find a world of difference with the above code if you add this to your connect:url: method:
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];
...and pass that into your NSURLConnection so it actually does something:
self.test = [[NSURLConnection alloc]initWithRequest:request delegate:self];
...because then, as soon as the connection finishes doing its work—successfully or otherwise—its memory will be deallocated.
I want to add a KVO observation that removes itself after it fires once. I have seen lots of folks on StackOverflow doing stuff like this:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"myKeyPath"])
{
NSLog(#"Do stuff...");
[object removeObserver:self forKeyPath:#"isFinished"];
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
This seems plausible, but I'm aware that calling -removeObserver:forKeyPath: from within -observeValueForKeyPath:... can be lead to non-deterministic crashes that are hard to debug. I also want to be sure this observation only gets called once (or not at all if the notification is never sent). What's a good way to do this?
I'm answering my own question here because I've seen the pattern in the question all over the place, but haven't had a reference to a good example of a better way. I've lost days, if not weeks, of my life to debugging problems ultimately found to be caused by adding and removing observers during the delivery of KVO notifications. Without warranty, I present the following implementation of a one-shot KVO notification that should avoid the problems that come from calling -addObserver:... and -removeObserver:... from inside -observeValueForKeyPath:.... The code:
NSObject+KVOOneShot.h:
typedef void (^KVOOneShotObserverBlock)(NSString* keyPath, id object, NSDictionary* change, void* context);
#interface NSObject (KVOOneShot)
- (void)addKVOOneShotObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context block: (KVOOneShotObserverBlock)block;
#end
NSObject+KVOOneShot.m: (Compile with -fno-objc-arc so we can be explicit about retain/releases)
#import "NSObject+KVOOneShot.h"
#import <libkern/OSAtomic.h>
#import <objc/runtime.h>
#interface KVOOneShotObserver : NSObject
- (instancetype)initWithBlock: (KVOOneShotObserverBlock)block;
#end
#implementation NSObject (KVOOneShot)
- (void)addKVOOneShotObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context block: (KVOOneShotObserverBlock)block
{
if (!block || !keyPath)
return;
KVOOneShotObserver* observer = nil;
#try
{
observer = [[KVOOneShotObserver alloc] initWithBlock: block];
// Tie the observer's lifetime to the object it's observing...
objc_setAssociatedObject(self, observer, observer, OBJC_ASSOCIATION_RETAIN);
// Add the observation...
[self addObserver: observer forKeyPath: keyPath options: options context: context];
}
#finally
{
// Make sure we release our hold on the observer, even if something goes wrong above. Probably paranoid of me.
[observer release];
}
}
#end
#implementation KVOOneShotObserver
{
void * volatile _block;
}
- (instancetype)initWithBlock: (KVOOneShotObserverBlock)block
{
if (self = [super init])
{
_block = [block copy];
}
return self;
}
- (void)dealloc
{
[(id)_block release];
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
KVOOneShotObserverBlock block = (KVOOneShotObserverBlock)_block;
// Get the block atomically, so it can only ever be executed once.
if (block && OSAtomicCompareAndSwapPtrBarrier(block, NULL, &self->_block))
{
// Do it.
#try
{
block(keyPath, object, change, context);
}
#finally
{
// Release it.
[block release];
// Remove the observation whenever...
// Note: This can potentially extend the lifetime of the observer until the observation is removed.
dispatch_async(dispatch_get_main_queue(), ^{
[object removeObserver: self forKeyPath: keyPath context: context];
});
// Don't keep us alive any longer than necessary...
objc_setAssociatedObject(object, self, nil, OBJC_ASSOCIATION_RETAIN);
}
}
}
#end
The only potential hitch here is that the dispatch_async deferred removal may marginally extend the lifetime of the observed object by one pass of the main run loop. This shouldn't be a big deal in the common case, but it's worth mentioning. My initial thought was to remove the observation in dealloc, but my understanding is that we don't have a strong guarantee that the observed object will still be alive when the -dealloc of KVOOneShotObserver is called. Logically, that should be the case, since the observed object will have the only "seen" retain, but since we pass this object into API whose implementation we can't see, we can't be completely sure. Given that, this feels like the safest way.
I have an application with UITabBarController, where the first tab contains a ViewController of an HomePage. What I have to do, is to switch between the tabs (this is pretty simple: [[self tabBarController] setSelectedIndex:index]), AND to navigate through outlets of the selectedTab from the "HomePage".
Just to explain myself: TabElement1--->TabElementX---->UISegmentedController:segmentY
The problem is that the UISegmentedController is nil because it is not initialized yet (at least the first time I do the operation). How should I fix this problem? The tab elements are loaded with nibs.
EDIT-- Here's some code:
#implementation HomeViewController // Tab Indexed 0
// ...
- (void)playVideoPreview {
NSArray *array;
array = [[self tabBarController] viewControllers];
// This is a test where I programmatically select the tab AND the switch.
[[[array objectAtIndex:2] switches] setSelectedSegmentIndex:1];
[[self tabBarController] setViewControllers:array];
}
#end
#implementation TGWebViewController // Tab Indexed 2
// ...
#synthesize switches; // In .h file: #property (nonatomic, retain) IBOutlet UISegmentedControl switches; Properly linked within the XIB.
- (IBAction)switchHasChangedValue {
// Foo operations.
}
Now the first time I fire playVideoPreview I manage to get Into the Tab Indexed 2, TGWebViewController, but switches doesn't exists yet, so I find myself with the segmentedControl named "switches" with the first segment selected. If I get back to HomeViewController, then I fire again playVideoPreview, I get the correct behaviour.
I've fixed the problem using the delegates and a boolean. Now, when the loading of the ViewController at index 2 of TabBar is finished, it sends a message to its delegate which tells what segment has to be selected.
EDIT Here's the code (hope it helps):
// Method in the first View that asks to tab the tab bar to launch the other
// view controller
- (void)playVideoPreview {
NSArray *array;
array = [[self tabBarController] viewControllers];
if ( ![[array objectAtIndex:2] catSwitch] ) {
[[array objectAtIndex:2] setDelegate:self];
[[array objectAtIndex:2] setHasBeenLaunchedByDelegate:YES];
} else {
[self selectTab];
}
[[self tabBarController] setViewControllers:array];
[[self tabBarController] setSelectedIndex:2];
}
// Now the operations performed by the second View Controller
- (void)somewhereInYourCode {
if ( hasBeenLaunchedByDelegate ) {
[[self delegate] selectTab];
}
}
// In the First View Controller this is the delegate method,
// launched from the Second View Controller
- (void)selectTab {
NSArray *array;
array = [[self tabBarController] viewControllers];
[[[array objectAtIndex:2] catSwitch] setSelectedSegmentIndex:[[bannerPreview pageControl] currentPage]];
}
// Some declaration
#protocol SecondViewControllerDelegate;
class SecondViewController : ViewController {
id<TGWebViewControllerDelegate> delegate;
}
#end
#protocol SecondViewControllerDelegate
- (void)selectTab;
#end
// Meanwhile in the first view
class FirstViewController : ViewController <SecondViewControllerDelegate> {
// ...
}
Dear community.
I have NSOperation subclass with property:
#property(readwrite, getter=isCancelled) BOOL cancelled;
from where i was create object of subclass NSObject (from init):
database = [[[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled] retain];
In this custom object i try to declare local iVar:
#interface MySQLIXC : NSObject {
BOOL _currentQueueStatus;
In init:
- (id)initWithQuene:(NSUInteger)quene andCarrier:(NSString *)carrierName withState:(BOOL)currentQueueStatus;
_currentQueueStatus = currentQueueStatus;
But currentQueueStatus allways null.
Can somebody suggest a problem location?
1) you should avoid re-declaring implemented subclass interface for your additions (e.g. -[NSOperation isCancelled] exists)
2) it is very unusual to start with two retain counts:
database = [[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled];
[otherThingThatHoldsAReference setDatabase:database];
instead of:
database = [[[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled] retain];
3) _currentQueueStatus is not null it's a BOOL, which is a signed char. it should be 0 (NO) or 1 (YES).
4) what is currentQueueStatus? more code would help you receive more specific answers.
EDIT: updated for clarification in response to comments
/* things would look different if you subclass MONOperation */
#interface MONOperation : NSOperation
{
#private
MySQLIXC * sqlIxc;
BOOL didCancelDatabaseRequest;
}
/*
do not use isCancelled for your name - NSOperation declares this method, and
its implementation is well defined. this would override the implementation
and likely cause runtime errors.
specifically, NSOperation/NSOperationQueue uses cancel and isCancelled in its
interface and state. if you must cancel, then call cancel from cancelDatabaseRequest.
you may override cancel, but call [super cancel] in your implementation.
*/
#property (readonly) BOOL didCancelDatabaseRequest;
#property (retain) MySQLIXC * sqlIxc;
#end
#implementation MONOperation
/* ... */
- (BOOL)didCancelDatabaseRequest
{
return didCancelDatabaseRequest;
}
- (void)cancelDatabaseRequest /* in this example, there is no sense making cancelDatabaseRequest publicly visible */
{
/* for example */
assert(self.sqlIxc);
self.sqlIxc = nil;
didCancelDatabaseRequest = YES;
[self cancel]; /* do this rather than overriding NSOperation's cancellation interfaces in your subclass */
}
- (void)main
{
NSAutoreleasePool * pool = [NSAutoreleasePool new];
assert(self.sqlIxc);
self.sqlIxc.doStuff;
if (self.sqlIxc.didTimeout || self.sqlIxc.couldNotAccessFile) {
[self cancelDatabaseRequest];
}
else {
/* use the result */
}
[pool release];
}
#end
I have the following problem making me crazy.
My app has to play a tick sound every second for a specified number of times (e.g. 5) after the user has pressed a button.
I used this:
for (int w=1; w<=5; w++) {
[NSThread detachNewThreadSelector:#selector(tic) toTarget:self withObject:nil];
[NSThread sleepForTimeInterval:1.0];
}
where:
- (void)tic {
NSAutoreleasePool *ticPool = [[NSAutoreleasePool alloc] init];
player_tic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:#"tick" ofType:#"aif"]] error:nil];
[player_tic setDelegate:self];
[player_tic play];
[ticPool drain];
}
and:
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *)player_tic successfully:(BOOL)flag {
NSLog(#"Audio finished playing.");
[player_tic release];
}
All seems to work. My problem is that the object are released together at the end.
I need that after every played sound the related 'player_tic' has to be released immediately.
Other Info:
In .m:
#synthesize player_tic;
In .h:
#interface myController : UIViewController {
...
AVAudioPlayer *player_tic;
}
#property (nonatomic, retain) AVAudioPlayer *player_tic;
On top of all, I have this warning in compilation:
local declaration of 'player_tic' hides instance variable
Please help me!
Thank you very much in advance.
--Carlo
I found System Sound Services more responsive than AVAudioPlayer.
It also solves your release problem, which is caused by the retain property of your controller. Read the reference manual on memory management for further information on retain/release.
I think you want to use self.player_tic when setting that variable, and i believe you also want to autorelease that instance. I'm not sure that setting up a separate NSAutoreleasePool is necessary either.
self.player_tic = [[[AVAudioPlayer alloc] initWithContentsOfURL:... error:nil] autorelease]