I'm having some issues when I build my react-native app in XCode to test on app on my iPhone.
The 4 errors are:
Expected identifier
Expected identifier or '('
Missing context for method declaration
'#end' must appear in an Object-C context
All of these errors are in my project's test .m file 3rsTests.m
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#define TIMEOUT_SECONDS 600
#define TEXT_TO_LOOK_FOR #"Welcome to React Native!"
#interface threeRsTests : XCTestCase
#end
#implementation 3RsTests //Error: Expected Identifier
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
if (test(view)) {
return YES;
}
for (UIView *subview in [view subviews]) {
if ([self findSubviewInView:subview matching:test]) {
return YES;
}
}
return NO;
}
- (void)testRendersWelcomeScreen //Error: missing context for method declaration
{
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
__block NSString *redboxError = nil;
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
if (level >= RCTLogLevelError) {
redboxError = message;
}
});
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
return YES;
}
return NO;
}];
}
RCTSetLogFunction(RCTDefaultLogFunction);
XCTAssertNil(redboxError, #"RedBox error: %#", redboxError);
XCTAssertTrue(foundElement, #"Couldn't find element with text '%#' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
}
#end //Error: '#end' must appear in an Objective-C context
I'm not a Swift or Object-C programmer so these errors are quite cryptic to me. I'd appreciate if anyone can give me a hand on how to get my code to compile.
This was a test file of sort and does not affect the way the name appears to the user. I followed #David Liaw's advice and renamed the identifier at line 17 and the app completed its built 100%
Related
I'm using Expressplay SDK for playing DRM contents. I have linked the Expressplay.framework to my iOS project. But while building its giving linking error
Below .h and .mm files
iosdrm.h file
#import <ExpressPlay/ExpressPlay.h>
// import RCTBridgeModule
#import <UIKit/UIKit.h>
#if __has_include(<React/RCTBridgeModule.h>)
#import <React/RCTBridgeModule.h>
#elif __has_include(“RCTBridgeModule.h”)
#import “RCTBridgeModule.h”
#else
#import “React/RCTBridgeModule.h” // Required when used as a Pod in a Swift project
#endif
#define EXP_INIT_ASYNC 1
typedef enum {
DRMCommandStatus_NO_RESULT = 0,
DRMCommandStatus_OK,
DRMCommandStatus_CLASS_NOT_FOUND_EXCEPTION,
DRMCommandStatus_ILLEGAL_ACCESS_EXCEPTION,
DRMCommandStatus_INSTANTIATION_EXCEPTION,
DRMCommandStatus_MALFORMED_URL_EXCEPTION,
DRMCommandStatus_IO_EXCEPTION,
DRMCommandStatus_INVALID_ACTION,
DRMCommandStatus_JSON_EXCEPTION,
DRMCommandStatus_ERROR
} DRMCommandStatus;
#interface iosdrm : NSObject <RCTBridgeModule>
{
UIAlertView* alertView;
NSMutableData *receivedData;
long responseCode;
NSMutableArray* proxies;
NSDictionary * cdvCommand;
}
// #property(nonatomic, readonly) WSB_PlaylistProxy* proxy;
#end
#pragma mark - Private methods
WSB_Result EXP_Initialize(void (^callback)(WSB_Result initialization_result))
{
// initialize the Wasabi runtime
WSB_Result result = WSB_Runtime_Initialize();
if (result != WSB_SUCCESS) {
NSLog(#"Failed to initialize Wasabi Runtime: %d", result);
return result;
}
// check if we're already personalized, without blocking
if (WSB_Runtime_IsPersonalized()) return WSB_SUCCESS;
// personalize in a separate thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// personalize and block until we're done
WSB_Result result = WSB_Runtime_Personalize(nil, 0);
NSLog(#"Wasabi Personalization result: %d", result);
dispatch_async(dispatch_get_main_queue(), ^{ callback(result); });
});
return EXP_INIT_ASYNC;
}
The
iosdrmManager.mm
#import "iosdrm.h"
#import <Foundation/Foundation.h>
#import <React/RCTLog.h>
// import RCTBridge
#import <React/RCTUtils.h>
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridge.h>
#elif __has_include(“RCTBridge.h”)
#import "RCTBridge.h"
#else
#import "React/RCTBridge.h" // Required when used as a Pod in a Swift project
#endif
// import RCTEventDispatcher
#if __has_include(<React/RCTEventDispatcher.h>)
#import <React/RCTEventDispatcher.h>
#elif __has_include(“RCTEventDispatcher.h”)
#import "RCTEventDispatcher.h"
#else
#import "React/RCTEventDispatcher.h" // Required when used as a Pod in a Swift project
#endif
struct Node
{
WSB_PlaylistProxy* proxy;
};
static void EXP_OnPlaylistProxyEvent(void* instance, const WSB_PlaylistProxy_Event* event)
{
// instance not used in this example
switch (event->type) {
case WSB_PPET_ERROR_NOTIFICATION:
WSB_PlaylistProxy_ErrorNotificationEvent* e;
e = (WSB_PlaylistProxy_ErrorNotificationEvent*)event;
NSLog(#"Error notification from Playlist Proxy: %d, %s",
e->result, e->error_string);
break;
default:
break;
}
}
static dispatch_queue_t RCTGetMethodQueueDRM()
{
// We want all instances to share the same queue since they will be reading/writing the same database.
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("drmQueue", DISPATCH_QUEUE_SERIAL);
});
return queue;
}
#implementation iosdrm
#synthesize bridge = _bridge;
// Export a native module
// https://facebook.github.io/react-native/docs/native-modules-ios.html
RCT_EXPORT_MODULE(lstdrm);
- (dispatch_queue_t)methodQueue
{
return RCTGetMethodQueueDRM();
}
// Export constants
// https://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#exporting-constants
- (NSDictionary *)constantsToExport
{
return #{
#"EXAMPLE": #"example"
};
}
// Return the native view that represents your React component
- (UIView *)view
{
return [[UIView alloc] init];
}
#pragma mark - Private methods
WSB_Result EXP_Initialize(void (^callback)(WSB_Result initialization_result))
{
// initialize the Wasabi runtime
WSB_Result result = WSB_Runtime_Initialize();
if (result != WSB_SUCCESS) {
NSLog(#"Failed to initialize Wasabi Runtime: %d", result);
return result;
}
// check if we're already personalized, without blocking
if (WSB_Runtime_IsPersonalized()) return WSB_SUCCESS;
// personalize in a separate thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// personalize and block until we're done
WSB_Result result = WSB_Runtime_Personalize(nil, 0);
NSLog(#"Wasabi Personalization result: %d", result);
dispatch_async(dispatch_get_main_queue(), ^{ callback(result); });
});
return EXP_INIT_ASYNC;
}
while building i'm getting the following error
Undefined symbols for architecture x86_64:
"_WSB_Runtime_Initialize", referenced from:
EXP_Initialize(void (int) block_pointer) in iosdrmManager.o
"_WSB_Runtime_IsPersonalized", referenced from:
EXP_Initialize(void (int) block_pointer) in iosdrmManager.o
"_WSB_Runtime_Personalize", referenced from:
____Z14EXP_InitializeU13block_pointerFviE_block_invoke in iosdrmManager.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Undefined symbols for architecture x86_64:
Seems to suggest you are building for the emulator, instead of for an actual device. The library will likely not work on the emulator (neither does FairPlay, or any other DRM library that i know of). Make sure you are building for an actual iOS device (which should have some variant of arm architecture).
I have production code which I see that it crashes once in a while with a EXC_BAD_ACCESS KERN_INVALID_ADDRESS on the block handler. I could for the life of me figure out what is wrong with my code. I have tried to reproduce this and could not in my controlled environment. Here is the stripped out and cleaned up code :
Code Snippet :
typedef void (^TestCallBackHandler)(NSString* location, NSError* error);
#interface _TestClass : NSObject
#property (nonatomic, copy) TestCallBackHandler handler;
#property (nonatomic, strong)NSTimer *endTimer;
- (void)fireOneOff:(TestCallBackHandler)handler;
#end
#implementation _TestClass
- (void)fireOneOff:(TestCallBackHandler)handler
{
_handler = handler;
NSLog(#"** New %p %# Incoming %p, %# Ours %p %#",self,self,handler, handler, _handler, _handler);
_endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(_stop) userInfo:nil repeats:NO];
}
- (void)dealloc
{
NSLog(#"%# Dealloced",self);
_handler = nil;
}
- (void)_stop
{
NSLog(#"** Stopping ? %#",self);
if (_handler)
_handler([NSString stringWithFormat:#"Hello %#",[NSDate date]], nil);
}
#end
The calling code in my class is defined as :
#property (nonatomic, strong)_TestClass *testClassInstance;
and called like this :
- (void)startTestClass {
_testClassInstance = [[_TestClass alloc] init];
[_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
NSLog(#"Got new String! %#",newString);
_testClassInstance = nil;
}];
}
Few things to note :
The startTestClass can be called multiple times
The app wakes up in the background and this can be created.
Any pointers, help highly appreciated.. I just cant put a finger in this code and say that is what is wrong. Please help!
Two hints which occur a little bit strange to me:
First: why are you setting the object to nil in it's own block.
- (void)startTestClass {
_testClassInstance = [[_TestClass alloc] init];
[_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
NSLog(#"Got new String! %#",newString);
_testClassInstance = nil;
}];
}
Second your object may be released already and the NSTimer is trying to execute a method on a release object
- (void)fireOneOff:(TestCallBackHandler)handler
{
_handler = handler;
NSLog(#"** New %p %# Incoming %p, %# Ours %p %#",self,self,handler, handler, _handler, _handler);
_endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(_stop) userInfo:nil repeats:NO];
}
I also dont get what the code does exactly and why. I believe there would be an easier and better maintainable solution for what you are achieving in this class.
If you want to have more information about EXC_BAD_ACCESS, then you can turn of NSZombies. In Xcode go to Product > Scheme > Edit Scheme and set checked Enable Zombie Objects.
I have an iPhone hybrid app using INTULocationManager that works well but the software is far more than I need. I have cut down to the basics as far as I can see, but I have obviously got something wrong when trying to invoke the callback to the block saved when the location request. Please can someone spot the probably pretty obvious error for me.
My .h file for this is
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
typedef void(^SBLocationRequestBlock)(CLLocation *currentLocation);
#interface SBLocationManager : NSObject
// Returns the singleton instance of this class.
+ (instancetype)sharedInstance;
// Creates a subscription for location updates
- (void)subscribeToLocationUpdatesWithBlock:(SBLocationRequestBlock)block;
// Set the minimum distance between two successive location returns
- (void)setDistanceFilter:(double)distance;
#end
My .m file is as follows
#import "SBLocationManager.h"
#import "SBLocationManager+Internal.h"
#interface SBLocationManager () <CLLocationManagerDelegate>
// The instance of CLLocationManager encapsulated by this class.
#property (nonatomic, strong) CLLocationManager *locationManager;
// Whether or not the CLLocationManager is currently sending location updates.
#property (nonatomic, assign) BOOL isUpdatingLocation ;
//Whether an error occurred during the last location update.
#property (nonatomic, assign) BOOL updateFailed;
// the code to be called when a location is available
#property (nonatomic, assign) SBLocationRequestBlock block;
#end
#implementation SBLocationManager
static id _sharedInstance;
// Create instance of this class.
- (instancetype)init
{
//self = [super init];
if (self) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.pausesLocationUpdatesAutomatically = NO; // to keep it going in background mode
#ifdef __IPHONE_8_4
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4
/* iOS 9 requires setting allowsBackgroundLocationUpdates to YES in order to receive background location updates.
We only set it to YES if the location background mode is enabled for this app, as the documentation suggests it is a
fatal programmer error otherwise. */
NSArray *backgroundModes = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIBackgroundModes"];
if ([backgroundModes containsObject:#"location"]) {
if ([_locationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[_locationManager setAllowsBackgroundLocationUpdates:YES];
}
}
#endif /* __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4 */
#endif /* __IPHONE_8_4 */
}
self.isUpdatingLocation = NO ;
return self;
}
+ (instancetype)sharedInstance
{
static dispatch_once_t _onceToken;
dispatch_once(&_onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
- (void)subscribeToLocationUpdatesWithBlock:(SBLocationRequestBlock)block
{
self.block = block;
[self requestAuthorizationIfNeeded];
[self.locationManager startUpdatingLocation];
self.isUpdatingLocation = YES;
}
- (void)setDistanceFilter:(double)distance
{
self.locationManager.distanceFilter = distance ;
self.locationManager.desiredAccuracy = distance ;
}
#pragma mark Internal methods
//Requests permission to use location services on devices with iOS 8+.
- (void)requestAuthorizationIfNeeded
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1
// As of iOS 8, apps must explicitly request location services permissions
// SBLocationManager supports both levels, "Always" and "When In Use".
// SBLocationManager determines which level of permissions to request based
// which description key is present in your app's Info.plist
// If you provide values for both description keys, the more permissive "Always
// level is requested.
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
BOOL hasAlwaysKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationAlwaysUsageDescription"] != nil;
BOOL hasWhenInUseKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationWhenInUseUsageDescription"] != nil;
if (hasAlwaysKey) {
[self.locationManager requestAlwaysAuthorization];
} else if (hasWhenInUseKey) {
[self.locationManager requestWhenInUseAuthorization];
} else {
// At least one of the keys NSLocationAlwaysUsageDescription
// NSLocationWhenInUseUsageDescription MUST be present in the Info.plis
// file to use location services on iOS 8+.
NSAssert(hasAlwaysKey || hasWhenInUseKey, #"To use location services in iOS 8+, your Info.plist must provide a value for either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription.");
}
}
#endif /* __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1 */
}
#pragma mark CLLocationManagerDelegate methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
self.updateFailed = NO;
CLLocation *mostRecentLocation = [locations lastObject];
dispatch_async(dispatch_get_main_queue(), ^{
if (self.block) {
self.block(mostRecentLocation);
}
});
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
self.updateFailed = YES;
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
}
#end
I invoke the request as follows :
- (void)requestLocationUpdates:(double)distanceValue
{
SBLocationManager *locMgr = [SBLocationManager sharedInstance];
[locMgr subscribeToLocationUpdatesWithBlock:^(CLLocation *currentLocation) {
NSLog (#"New Location:\n%#", currentLocation);
NSString *javascriptString = [NSString stringWithFormat:#"UpdateOwnLocation('%.6f','%.6f','%.6f');", currentLocation.coordinate.latitude, currentLocation.coordinate.longitude, currentLocation.horizontalAccuracy];
[webView stringByEvaluatingJavaScriptFromString:javascriptString];
}];
[locMgr setDistanceFilter:distanceValue];
}
- (void) changeLocationUpdates:(double)distanceValue
{
SBLocationManager *locMgr = [SBLocationManager sharedInstance];
[locMgr setDistanceFilter:distanceValue];
}
However when I run this (in the simulator) I get
EXC_BAD_ACCESS in the line self.block (mostRecentLocation).
i.e. the location manager is setup and returns a location but my code for calling the requesting block fails. I have noted in the debugger that self.block is correctly pointing at my view controller code when in subscribeToLocationUpdatesWithBlock but by the time the code gets to invoking the block on the main queue it points somewhere else. Is this because self is no longer the same in this bit of code.
My apologies for bad terminology, I am a javascript programmer attempting to do something with XCode that is probably beyond my skills. Any help anyone can provide would be lovely.
I would use copy, not assign for the block property. assign is for simple things like int usually.
To narrow down if it's the block or location, add an NSLog for mostRecentLocation before calling the block.
If that's not it, check out my blog post on debugging EXC_BAD_ACCESS:
http://loufranco.com/blog/understanding-exc_bad_access
As AudioSessionInitialize and AudioSessionGetProperty are deprecated, I am getting the wrong return values:
CFStringRef state = nil;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
[[AVAudioSession sharedInstance] setActive:YES error:nil];
if (status == kAudioSessionNoError) {
return CFStringGetLength(state) == 0; // YES = silent
}
return NO;
From this code (I found it here), I get the same incorrect result no matter what state is actually device on. How can I detect if the silent mode is ON on device right now?
The API is no longer available. But the work around is simple:
Play a short audio and detect time that it finishes playing
If the time that it finishes playing is shorter than the actual length of the audio, than the device is muted
Hoishing posted a helper class MuteChecker on his blog. Use it as the following:
self.muteChecker = [[MuteChecker alloc] initWithCompletionBlk:^(NSTimeInterval lapse, BOOL muted) {
NSLog(#"muted: %d", muted);
}];
[self.muteChecker check];
This is the complete code for the class, you can simple copy past to your project:
MuteChecker.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef void (^MuteCheckCompletionHandler)(NSTimeInterval lapse, BOOL muted);
// this class must use with a MuteChecker.caf (a 0.2 sec mute sound) in Bundle
#interface MuteChecker : NSObject
-(instancetype)initWithCompletionBlk:(MuteCheckCompletionHandler)completionBlk;
-(void)check;
#end
MuteChecker.cpp
#import "MuteChecker.h"
void MuteCheckCompletionProc(SystemSoundID ssID, void* clientData);
#interface MuteChecker ()
#property (nonatomic,assign) SystemSoundID soundId;
#property (strong) MuteCheckCompletionHandler completionBlk;
#property (nonatomic, strong)NSDate *startTime;
-(void)completed;
#end
void MuteCheckCompletionProc(SystemSoundID ssID, void* clientData){
MuteChecker *obj = (__bridge MuteChecker *)clientData;
[obj completed];
}
#implementation MuteChecker
-(void)playMuteSound
{
self.startTime = [NSDate date];
AudioServicesPlaySystemSound(self.soundId);
}
-(void)completed
{
NSDate *now = [NSDate date];
NSTimeInterval t = [now timeIntervalSinceDate:self.startTime];
BOOL muted = (t > 0.1)? NO : YES;
self.completionBlk(t, muted);
}
-(void)check {
if (self.startTime == nil) {
[self playMuteSound];
} else {
NSDate *now = [NSDate date];
NSTimeInterval lastCheck = [now timeIntervalSinceDate:self.startTime];
if (lastCheck > 1) { //prevent checking interval shorter then the sound length
[self playMuteSound];
}
}
}
- (instancetype)initWithCompletionBlk:(MuteCheckCompletionHandler)completionBlk
{
self = [self init];
if (self) {
NSURL* url = [[NSBundle mainBundle] URLForResource:#"MuteChecker" withExtension:#"caf"];
if (AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &_soundId) == kAudioServicesNoError){
AudioServicesAddSystemSoundCompletion(self.soundId, CFRunLoopGetMain(), kCFRunLoopDefaultMode, MuteCheckCompletionProc,(__bridge void *)(self));
UInt32 yes = 1;
AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(_soundId),&_soundId,sizeof(yes), &yes);
self.completionBlk = completionBlk;
} else {
NSLog(#"error setting up Sound ID");
}
}
return self;
}
- (void)dealloc
{
if (self.soundId != -1){
AudioServicesRemoveSystemSoundCompletion(self.soundId);
AudioServicesDisposeSystemSoundID(self.soundId);
}
}
#end
Important note: you will also have to provide a short audio MuteChecker.caf for the code to work. You could download one from his blog directly or generate one yourself.
I am new to using OCMock. I have the following simplified code I want to test -
#implementation ViewController
- (void)presentSomething:(NSString *)string {
NSLog(#"doSomethingElseWithString - %#", string);
}
- (BOOL)handleResult:(NSString *)result
{
BOOL handled = YES;
NSString *changedString = [result uppercaseString];
[self presentSomething:changedString];
return handled;
}
#end
and I have a test as follows
- (void)testExample {
ViewController *vc = [ViewController new];
id mockViewController = OCMPartialMock(vc);
OCMStub([mockViewController presentSomething:#"1234"]);
BOOL handled = [vc handleResult:#"1234"];
XCTAssertTrue(handled);
OCMVerify([mockViewController presentSomething:#"1234"]);
}
I want to verify presentSomething gets called with the correct argument after I call handleResult.
The test either gives a EXC_BAD_ACCESS while verifying or fails saying the presentSomething method was not invoked.
If I change the handleResult method as follows the test runs and passes.
- (BOOL)handleResult:(NSString *)result
{
BOOL handled = YES;
[self presentSomething:result];
return handled;
}
It seems that intermediate [result uppercaseString] and variable caused the issue. Is this an issue with how I am using OCMock or a bug in OCMock?
Must be trying to do a pointer comparison instead of isEquals. I haven't tried debugging the issue against the source code yet, but there is a workaround:
- (void)testExample
{
ViewController *vc = [ViewController new];
id mockViewController = OCMPartialMock(vc);
OCMExpect([mockViewController presentSomething:#"1234"]);
BOOL handled = [vc handleResult:#"1234"];
XCTAssertTrue(handled);
OCMVerifyAll(mockViewController);
}