EXC_BAD_ACCESS using ARC only during testing - ios

I have an issue where I'm getting bad access exceptions but only when running a testing build (calling the same methods in a debug build doesn't cause the problem to come up). The project has ARC enabled and I'm running this on the iPad 5.1 simulator using Xcode 4.3:
Here's where the problem crops up:
- (void)testChangeFoodNotification {
Player* p = [[Player alloc] init];
[p addObserver:self forKeyPath:#"food" options:0 context:0]; // <-EXC_BAD_ACCESS (code=2)
p.food += 1;
STAssertTrue(_wasNotifiedOfFoodChange, nil);
}
At the point when the addObserver: method is called it doesn't seem like any of the objects involved should have been released so what could be causing the exception?
EDIT:
Apologies if it wasn't clear but the code above is being executed as part of a test case (using the standard Xcode OCUnit). Also in case it clarifies anything here's the relevant code from the player class (there's other ivars and methods but they don't have any connection to the property or methods being tested):
// Public interface
#interface Player : NSObject
#property (nonatomic, assign) NSInteger food;
#end
// Private interface
#interface Player() {
NSInteger _food;
}
#end
#implementation Player
#synthesize food = _food;
#pragma mark - Getters/Setters
- (void)setFood:(NSInteger)food {
[self willChangeValueForKey:#"food"];
_food = food;
[self didChangeValueForKey:#"food"];
}

If your class is indeed key-value compliant, ensure that the implementation for the class exhibiting the issue is not included in your test product. This means that the Target Membership panel of the Identity inspector for your .m file should only have your app checked (not YourAppTests).
I experienced the same issue in Xcode 4.3.1 when an implementation was included in both products and I registered observers in both production and test code. The following logs tipped me off:
Class YourClass is implemented in both /Users/yourUser/Library/Application Support/iPhone Simulator/5.1/Applications//YourApp.app/YourApp and /Users/yourUser/Library/Developer/Xcode/DerivedData/YourApp-/Build/Products/Debug-iphonesimulator/YourAppTests.octest/YourAppTests. One of the two will be used. Which one is undefined.

As per the Key-Value Observing Programming Guide, is your Player key-value-compliant? You want to make sure you are Ensuring KVC Compliance. I also assume that you have also implemented your observeValueForKeyPath:ofObject:change:context:? If you think you've done all of this and it's still not working, then perhaps you can share your code.
Also, minor thing, but I assume this is a code snippet to highlight the issue. I only mention it because ARC is going to be releasing your p object at the end of your testChangeFoodNotification and I would have thought that you'd want to remove your observer first.

Related

No known class method for selector 'simplePingWithHostName: SimplePing iOS Objective C

Hello I am having trouble using SimplePing I receive the following error when copying over the SimplePing.h and SimplePing.m files I downloaded from Apple SimplePing
No known class method for selector 'simplePingWithHostName:'
From this method in my SimplePingClient.m class:
-(void)pingHostname:(NSString*)hostName andResultCallBlock:(void(^)(NSString* latency))result
{
_resultCallback = result;
_pingClient = [SimplePing simplePingWithHostName:hostName]; // No known class method for selector 'simplePingWithHostName:'
_pingClient.delegate = self;
[_pingClient start];
}
I'm calling this method from another file like this, where there are no errors:
-(void)testNetworkLatency {
[SimplePingClient pingHostname:#"www.apple.com"
andResultCallback:^(NSString *latency) {
NSLog(#"your latency is: %#", latency ? latency : #"unknown");
}];
}
I tried changing [SimplePing simplePingWithHostName... in SimplePingClient.m to variations of pingHostname, initWithHostName, sendPingWithData but nothing has worked so far. Did something change with SimplePing or am I going wrong somewhere?
Link to a screenshot of all the methods available in SimplePing.h as you can see, there is no simplePingWithHostName
it is wise to read the class definitions before coping and pasting but once done you can take them for granted because thats what they are for. You will have much more fun when following them. But keep on trying as this is a classic beginner mistake in objC when taking over language concepts from elsewhere but not objC.
You will want to set a global variable to keep your simple ping object around.
#implementation YourClass {
SimplePing *_pingClient;
}
alternative in
#interface YourClass : YourInheritingClass <NeverGiveUpProtocol>
#property (nonatomic) SimplePing *pingClient;
#end
and in your implementation method allocation and initiation of your ping object is done like
_pingClient = [[SimplePing alloc] initWithHostName:hostName];
Also you will have to be careful with the definition of block parameters that are doing nothing and are set up to accept NSStrings. You can read about block definitions in methods here
https://riptutorial.com/objective-c/example/1761/blocks-as-method-parameters
You can tell the compiler that you don't need a specific parameter like so ..
if you cant avoid to define it.
-(void)yourmethod:(NSString*)hostname resultBlock:(void(^)())result {
#pragma unused(result)
// your stuff
}
Hint: SimplePing and SimplePingClient seem to be total different classes where the last one contains pingHostname: as external method. (Means you can call it without explicit initiation.) Ending up in a method definition like..
+(void)pingHostname:(NSString *)hostname; which is why you would need to call it directly on the ClassName.
The Apple example does not contain a class named SimplePingClient.
Thats probably result of your creative process. Yeah maybe you want to ping from the app you create to the same app on a different device - well, why not. Cheers

Objective C - Dynamically compile or do not compile class and codes

First of all; I don't know if this question is duplicate or not. Because I don't know how to search for this question.
Let me explain my question with scenario.
I've iOS 11 Project (Deployment target 9.2). Let's call it Master.
I've coded 2 POD Projects and Master project has reference for them.
POD1 has classes A.class B.class and C.class
POD2 has classes D.class E.class and F.class
Master project is using both POD1 and POD2
Here is the question; What if I want to remove POD1 reference and want to distribute project with just POD2?
I have to remove all codes inside Master which using POD1? I don't think so... It is very amateur way to do it. And there should be professional way to do it.
Maybe Run Script?
or
Maybe putting some flags inside code where using POD1 classes to exclude from build? So I don't get error as File Not Found..
I know the way using
#ifndef HIDE_<insert name here>
CODE
#endif
But don't think it's a correct way to do it..
Any ideas & suggestions are welcome.
Thank you.
Using Objective-C categories, you can conditionally compile groups of methods for different targets. Here's an example.
Let's say you have two targets that both use a class A. In one target (a background daemon) you need just the core functionality of class A. In the GUI version of your app you need the same functionality plus additional methods to support the user interface. The problem is that you can't simply compile all of class A in the daemon target because it will reference Cocoa classes that the daemon target doesn't get linked to. You need to isolate the user interface code and compile/link it only in the target that uses it. Here's how:
Base classes
A.h
#interface A : NSObject
#property NSUInteger someProperty;
- (void)doSomething;
#end
A.m
#implementation A
- (void)doSomething
{
// Do something useful
}
#end
Now define the GUI specific methods in a category:
A+ViewAdditions.h
#interface A (ViewAdditions)
#property (readonly,nonatomic) NSView* view;
#end
A+ViewAdditions.m
#implementation A (ViewAdditions)
- (NSView*)view
{
// Create a view that will display this object
NSView* view = [[NSView alloc] initWithFrame:NSZeroRect];
return view;
}
#end
In both targets, you include/compile the A.m module, so both targets compile the core class A which includes its someProperty and doSomething method. But in your GUI target, you also compile the A+ViewAdditions.m module. In your GUI app, the A class has a view property, but in your daemon it will not. You can test for this at runtime:
A* a = [A new];
if ([a respondsToSelector:#selector(view)])
NSLog(#"a.view is a %#",a.view.className); // prints "is a NSView"
else
NSLog(#"a has no view property");
This can be extended to subclasses:
B.h
#interface B : A
#end
B.m
#implementation B
#end
B+ViewAdditions.h
#interface B (ViewAdditions)
#end
B+ViewAdditions.m
#implementation B (ViewAdditions)
- (NSView*)view
{
NSTextField* fieldView = [[NSTextField alloc] initWithFrame:NSZeroRect];
return fieldView;
}
#end
And...
A* a = [A new];
B* b = [B new];
if ([a respondsToSelector:#selector(view)])
NSLog(#"a.view is a %#",a.view.className); // prints "is a NSView"
if ([b respondsToSelector:#selector(view)])
NSLog(#"b.view is a %#",b.view.className); // prints "is a NSTextField"
There are limitations to categories, which you should be aware of. The most problematic is that you can't add instance variables or stored properties to a class via a category. But category methods can access private variables in the class, and I'll sometimes define private ivars in the base class that only get used by the category. Your style may vary.

Xcode Admob singleton - "use of undeclared identifier "shared"" error

Okay first post ever on any forum but i'll do my best to describe my problem. I'm a beginner at Xcode so i'm sorta expecting an easy solution, but i just can't seem to figure this one out.
In Xcode i am trying to create an Admob singleton to get admob in all my view controllers. Admob will back up iAd, which will be showed should Ad fail.
I followed this guide: http://googleadsdeveloper.blogspot.dk/2012/04/creating-gadbannerview-singleton-in.html
I created a GADMasterViewController .m and .h file
The GADMasterViewController.h looks like this
#import "GADBannerView.h"
#interface GADMasterViewController : UIViewController <GADBannerViewDelegate> {
GADBannerView *adbanner_;
BOOL isLoaded_;
id currentDelegate_;
}
#end
and the GADMasterViewController.m file looks exactly as the one in the guide except i put #import "GADMasterViewController.h" at the top.
Then in my viewController.m where i want the ad to show i put
- (void)bannerView:(GADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
_UIiAd.hidden = YES;
shared = [GADMasterViewController singleton];
[shared resetAdview:self]
}
However in viewController.m i get the following errors:
https://dl.dropboxusercontent.com/u/63928888/Sk%C3%A6rmbillede%202014-09-15%20kl.%2000.17.02.png
Basically it doesn't recognize the returned "shared" err singleton (or whatever "shared" is) from GADMasterViewController.m
How do i "get" "shared" so my viewController doesn't produce these errors?
You are using shared, but you haven't defined it as a variable (local or otherwise).
So, change
shared = [GADMasterViewController singleton];
[shared resetAdview:self]
to either
GADMasterViewController *shared = [GADMasterViewController singleton];
[shared resetAdview:self];
or
[[GADMasterViewController singleton] resetAdview:self];
so that you are defining the variable, or so that you don't need a variable.

Dropbox iOS API - Simple Questions / DBRestClient Problems

EDIT:
I think I have fixed my issues. Thank you for the help - I really appreciate it.
Original Question:
I am new to objective-c and iOS programming, so hopefully my issues are not difficult to correct. I am trying to add the ability to open a file from Dropbox to my simple iOS application. I have been following the tutorial here:
http://www.mathiastauber.com/integration-of-dropbox-in-your-ios-application-making-api-calls/
I have so far successfully gotten my app to link to my Dropbox account and display the "link successful" message.
Now I am having trouble using the DBRestClient. I have the following code currently:
myviewcontroller.h
...
#end
DBRestClient *restClient;
myviewcontroller.m
- (DBRestClient *)restClient {
if (!restClient) {
restClient =
[[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}
I am getting an error on the line
restClient.delegate = self;
that says
"Assigning to 'id<DBRestClientDelegate>' from incompatible type 'myviewcontroller'"
What could be going wrong? I have read through every example I can find and can see no issues with what I am trying to do.
If I try to cast by doing the following, it does not work
restClient.delegate = (id)self;
I have also found that if I remove the code in myviewcontroller.m and only have the variable declaration in the header file (as shown above) I get an error that says "Apple Mach-O Linker Error"
I would greatly appreciate any help you can provide. I am very much stuck with this problem.
In your header file you need to specify that you adhere to the DBRestClientDelegate's protocol.
For example:
#interface MyViewController: UIViewController <DBRestClientDelegate>
If you're already adhering to other protocols, simply add the DBRestClientDelegate and comma seperate, such as...
#interface MyViewController: UIViewController <UITableViewDelegate, DBRestClientDelegate>
For more information, I'd recommend a read of the Delegation section of Cocoa Core Competencies, especially as you'll be encountering delegates (and indeed perhaps defining your own protocols, etc.) a lot in Cocoa.
The error is because the right side of restClient.delegate = self; is not of type id<DBRestClientDelegate>
id<DBRestClientDelegate> is basically any object that conforms to the DBRestClientDelegate protocol
The first step (maybe only step) to removing the error is in your Myviewcontroller.h file
change
#interface Myviewcontroller : UIViewController //<-- my best guess at your interface line
to
#interface Myviewcontroller : UIViewController <DBRestClientDelegate>

Automatic Reference Counting not working [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is object not dealloc'ed when using ARC + NSZombieEnabled
I must be doing something wrong here. Compiler is set to Apple LLVM Compiler 3.0 and Objective-C Automatic Reference Counting is set to YES. I also have 3rd Party Software included that requires ARC to be active.
So my basic problem is that my properties don't get released. I have the following header:
#interface ArchiveController : UIViewController <CloseSubviewDelegate> {
NSArray *journals;
NSMutableArray *archiveViews;
}
#property (nonatomic, strong) NSArray *journals;
#property (nonatomic, strong) NSMutableArray *archiveViews;
....
#end
I synthesized those and initialize the archiveViews array like this:
self.archiveViews = [NSMutableArray array];
later I add objects to it, everything works fine; same for the journals array.
I added a dealloc method to check that the ArchiveController gets released:
-(void)dealloc
{
DLog(#"dealloc archive controller");
}
which works, but the arrays are never released; Why? If I change the dealloc method to this:
-(void)dealloc
{
DLog(#"dealloc archive controller");
self.archiveViews = nil;
}
everything works fine, but thats not the way it should be, right? I'm a 100 % certain that the array and its objects aren't referenced anywhere else.
And isn't the Preprocessor supposed to handle the insertion of all the retains/releases/deallocs? when I let Xcode generate preprocessed output, nothing seems changed!
I suspect a circular dependency.
Instruments can help you locate them at times.

Resources