iPhone 5c and anything running bluetooth 4.0 has wcsession timout - bluetooth
I have tested my code on the iPhone 6 plus running 9.0 with apple watch 1 and iPhone 7 running 10.0 with apple watch 2.
//HeartrateModel_Phone.m
#import "HeartrateModel_Phone.h"
#implementation HeartrateModel_Phone
{
Communicator * comm;
communicatorStatus commStatus;
HealthDataService * hkService;
workoutStatus monitoringStatus;
}
#synthesize delegate;
-(id)init
{
self = [super init];
if (self)
{
comm = [[Communicator alloc]init];
hkService = [[HealthDataService alloc]init];
monitoringStatus = noWorkoutActivated;
commStatus = noCommunicationActivated;
comm .delegate = self;
hkService.delegate = self;
bluetoothManager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
[comm start];
}
return self;
}//eom
-(void)activate
{
[comm start];
}//eom
/*
//disable to remove singleton option
+(HeartrateModel_Phone *)sharedInstance
{
static HeartrateModel_Phone * sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[HeartrateModel_Phone alloc] init];
});
return sharedInstance;
}//eom
*/
#pragma mark - Bluetooth
/*!
* #discussion Accepts a CBCentralManager and returns the bluetooth status
* #param CBCentralManager
* #return bluetoothStatus
*/
-(bluetoothStatus)getBluetoothStatus:(CBCentralManager *)central
{
switch (central.state)
{
case CBManagerStateUnsupported:
return bluetooth_notSupported;
break;
case CBManagerStateUnauthorized:
return bluetooth_unathorized;
break;
case CBManagerStatePoweredOff:
return bluetooth_off;
break;
case CBManagerStatePoweredOn:
return bluetooth_on;
break;
default:
return bluetooth_unknown;
break;
}
}//eom
#pragma mark Bluetooth Delegates
-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
bluetoothStatus status = [self getBluetoothStatus:central];
[delegate heartrateModelBluetoothStatusChanged:status];
if (VERBOSE) {
NSLog(#"%# Bluetooth '%#'", self, hrModelBluetoothStatusToString(status));
}
}//eom
#pragma mark - Start Workout Process
/*!
* #discussion Starts heartrate mode by sending a message to watch to start workout
if the following conditions are met:
* #brief 1) bluetooth must be enable/turned on
* #brief 2a) to start watch app automatically the iOS version must be 10 & above
*/
-(void)start
{
//making sure bluetooth is on
bluetoothStatus BTstatus = [self getBluetoothStatus:bluetoothManager];
if (BTstatus == bluetooth_on)
{
//checking OS version
NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo]operatingSystemVersion];
NSInteger currOSVersion = osVersion.majorVersion;
if (currOSVersion >= 10)
{
//checking watch is ready
if( ((comm .session) .isPaired)
&& ((comm .session) .isWatchAppInstalled) )
{
//setup workout configuration
HKWorkoutConfiguration * wkConfig = [[HKWorkoutConfiguration alloc]init];
wkConfig.activityType = HKWorkoutActivityTypeOther;
wkConfig.locationType = HKWorkoutSessionLocationTypeUnknown;
//attempt to start watch app automatically
[(hkService .hkStore) startWatchAppWithWorkoutConfiguration:wkConfig
completion:^(BOOL success, NSError * _Nullable error)
{
[delegate heartrateModelStartWorkResult:success withError:error];
//start monitoring heartrate data from healthkit
if (success){
[self startReading_HeartrateData];
}
}];
}
else
{
//communication not possible
NSErrorDomain errorDomain= #"";
NSInteger errorCode = 1111;
NSError * error = [NSError errorWithDomain:errorDomain
code:errorCode
userInfo:nil];
[delegate heartrateModelStartWorkResult:false withError:error];
}
}
else
{
//sending a live message to watch
[self messageStartWorkout:true];
}
}
else
{
//notify that bluetooth status is not on
[delegate heartrateModelBluetoothStatusChanged:BTstatus];
}
}//eom
/*!
* #discussion Stops the Heartrate model, sends message to watch to stop workout and stops monitoring healthkit for heartrate data
*/
-(void)end
{
[self stopReading_HeartrateData];
[self messageEndWorkout];
}//eom
#pragma mark - Live Message Start Workout
/*!
* #discussion Sends a start workout commands to counterpart via live message
* #param BOOL whether the listener/delegate VC would be notified of message delivery failures
*/
-(void)messageStartWorkout:(BOOL)reportFailure
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_start),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
} errorHandler:^(NSError * _Nonnull error) {
//communication not possible
if (reportFailure) {
[delegate heartrateModelStartWorkResult:false withError:error];
}
}];
}//eom
/*!
* #discussion Sends a stop workout commands to counterpart via live message
* #discussion if live message fails, sends a background message
*/
-(void)messageEndWorkout
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_end),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
//NSLog(#"reply message: %#", replyMessage);
} errorHandler:^(NSError * _Nonnull error)
{
//sending background message - optional
[comm sendApplicationContext:messageToSend];
}];
}//eom
-(void)messageRequestForWorkoutStatus
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_status),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
//NSLog(#"reply message: %#", replyMessage);
} errorHandler:^(NSError * _Nonnull error)
{
}];
}//eom
#pragma mark - Health Store Permission
/*!
* #discussion Request Heartrate Healthkit permission
* #return BOOL success
* #return NSError any errors with healthkit permission
*/
-(void)requestPermission:(void (^)(BOOL success, NSError *error)) completionBlock
{
[hkService requestPermission:^(BOOL success, NSError *error)
{
completionBlock(success, error);
}];
}//eom
#pragma mark - Communicator Delegates
-(void)communicatorActionStatus:(communicatorStatus)status
{
commStatus = status;
if (VERBOSE)
{
NSLog(#"%# Communication Status: '%#'", self, communicatorToString(status));
}
}//eom
-(NSDictionary<NSString *,id> *)communicatorDidReceivedLiveMessage:(NSDictionary<NSString *,id> *)message
{
[self handleMessageReceived:message];
NSDictionary<NSString *, id> * reply = [[NSDictionary alloc]
initWithObjectsAndKeys:#"Success", #"Received", nil];
if (delegate == nil)
{
reply = [[NSDictionary alloc] initWithObjectsAndKeys:#"Failed", #"Received", nil];
}
return reply;
}//eom
-(void)communicatorDidReceivedBackgroundMessage:(NSDictionary<NSString *,id> *)message
{
//nothing to do - not implemented for phone to received background messages
}//eom
-(void)communicatorStateChanged:(WCSession *)session
{
if (session .reachable) {
[self messageRequestForWorkoutStatus];
}
}//eom
#pragma mark Communication Helpers
/*!
* #discussion Handles message received and calls the corresponding handler
* #param NSDictionary Message Received from counterpart
*/
-(void)handleMessageReceived:(NSDictionary<NSString *,id> *)messageRcvd
{
if (VERBOSE)
{
NSLog(#"[hrModel] message RCVD %#", messageRcvd);
}
NSString * keyReceived = [messageRcvd objectForKey:hrModelKeysToString(monitor_key)];
//response / status
if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Response)])
{
NSString * responseReceived = [messageRcvd objectForKey:hrModelResponseToString(monitor_Response)];
[self handleMessage_Response:responseReceived];
}
//error
else if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Error)])
{
NSString * errorReceived = [messageRcvd objectForKey:hrModelErrorToString(monitor_Response)];
[self handleMessage_Error:errorReceived];
}
//Command
else if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Command)])
{
NSString * commandReceived = [messageRcvd objectForKey:hrModelCommandToString(monitor_Command)];
[self handleMessage_Command:commandReceived];
}
}//eom
/*!
* #discussion Handles the response received from counterpart
* #param NSString Response received
*/
-(void)handleMessage_Response:(NSString *)responseRcvd
{
dispatch_async(dispatch_get_main_queue(),
^{
if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_started)])
{
monitoringStatus = started;
[self startReading_HeartrateData];
}
else if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_ended)])
{
monitoringStatus = ended;
[self stopReading_HeartrateData];
}
else if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_notStarted)])
{
monitoringStatus = noWorkoutActivated;
//no need to report failure to start since the nstimer on vc would be trigger
}
});
}//eom
/*!
* #discussion Handles the response received from counterpart
* #param NSString Response received
*/
-(void)handleMessage_Error:(NSString *)errorRcvd
{
monitoringStatus = noWorkoutActivated;
dispatch_async(dispatch_get_main_queue(),
^{
if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_workout)])
{
monitoringStatus = error_workout;
}
else if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_healthkit)])
{
monitoringStatus = error_healthkit;
}
else if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_communicator)])
{
monitoringStatus = error_communicator;
}
});
}//eom
/*!
* #discussion Handles the command received from counterpart
* #param NSString Command received
*/
-(void)handleMessage_Command:(NSString *)commandRcvd
{
//nothing to do - not implemented to received commands
}//eom
#pragma mark - Health Store Heartrate Reading
/*!
* #discussion Requests to Start monitoring healthkit for heartrate data
*/
-(void)startReading_HeartrateData
{
dispatch_async(dispatch_get_main_queue(), ^{
[hkService startHeartrateWithPollingTime:1.5
andSamplesWithSecondsBack:-25.0];
});
}//eom
/*!
* #discussion Requests to Stop monitoring healthkit for heartrate data
*/
-(void)stopReading_HeartrateData
{
dispatch_async(dispatch_get_main_queue(), ^{
[hkService stopPollingHeartrates];
});
}//eom
#pragma mark - HealthData Service Delegates
-(void)healthDataServicePollingSamplesReceived:(NSArray<__kindof HKSample *> *)samples
{
dispatch_async(dispatch_get_main_queue(), ^{
HKQuantitySample * lastHrSample = [samples firstObject];
//value
HKQuantity * hrValue = lastHrSample.quantity;
double hr = [hrValue doubleValueForUnit:hkService.hrUnit];
//dates
NSDate * startDate = lastHrSample.startDate;
NSDate * endDate = lastHrSample.endDate;
[delegate heartrateModelDidReceiveHeartrate:hr
withStartDate:startDate
andEndDate:endDate];
if (VERBOSE)
{
NSLog(#"[hrModel] hr %f |\n start %# |\n end %# ", hr, [startDate debugDescription], [endDate debugDescription]);
}
});
}//eom
#end
When I run my code with the iPhone 5c running 10.0 and apple watch 3.0, it will connect but it is inconsistent. Sometimes I would get wcsession timeout error and it failed to deliver the message.
Related
Siri : IntentHandler not behaving correctly with device Touch ID
What is the right approach to handle device LocalAuthentication with NSIntent? Currently it is not showing payment sent pop up in Siri INSendPaymentIntent. - (void)handleSendPayment:(INSendPaymentIntent *)intent completion:(void (^)(INSendPaymentIntentResponse *response))completion { __block INSendPaymentIntentResponse *siriResponse; LAContext *context = [[LAContext alloc] init]; NSError *error = nil; // Check if device supports TouchID if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { // TouchID supported, show it to user [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:#"Unlock using Touch ID to transaction” reply:^(BOOL success, NSError *error) { if (success) { // This action has to be on main thread and must be synchronous dispatch_async(dispatch_get_main_queue(), ^{ // Payment handling code goes here }); } else if (error) { dispatch_async(dispatch_get_main_queue(), ^{ siriResponse = [[INSendPaymentIntentResponse alloc] initWithCode:INSendPaymentIntentResponseCodeSuccess userActivity:nil]; }); } }]; } } If I remove Local Authentication payment works just fine!!
Front Camera recording is MUTE
I am working with some camera recoding app. I want to record video using front and back camera both. For back camera my video is working fine but for front camera my final video is mute (without audio). CODE: - (id)initWithPreviewView:(UIView *)previewView { self = [super init]; if (self) { NSError *error; self.captureSession = [[AVCaptureSession alloc] init]; self.captureSession.sessionPreset = AVCaptureSessionPresetHigh; //AVCaptureSessionPresetHigh AVCaptureSessionPresetPhoto // AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDevice *videoDevice; // if (isNeededToSave) // { // //for Front cam // videoDevice = [self frontCamera]; // // } // else // { // //for back cam videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; // } AVCaptureDeviceInput *videoIn = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; if (error) { NSLog(#"Video input creation failed"); return nil; } if (![self.captureSession canAddInput:videoIn]) { NSLog(#"Video input add-to-session failed"); return nil; } [self.captureSession addInput:videoIn]; /*Take PHoto*/ self.isUsingFrontFacingCamera = 0; // Make a still image output stillImageOutput = [AVCaptureStillImageOutput new]; [stillImageOutput addObserver:self forKeyPath:#"capturingStillImage" options:NSKeyValueObservingOptionNew context:(__bridge void *)(AVCaptureStillImageIsCapturingStillImageContext)]; if ( [self.captureSession canAddOutput:stillImageOutput] ) [self.captureSession addOutput:stillImageOutput]; // Make a video data output videoDataOutput = [AVCaptureVideoDataOutput new]; // we want BGRA, both CoreGraphics and OpenGL work well with 'BGRA' NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; [videoDataOutput setVideoSettings:rgbOutputSettings]; [videoDataOutput setAlwaysDiscardsLateVideoFrames:YES]; // discard if the data output queue is blocked (as we process the still image) // create a serial dispatch queue used for the sample buffer delegate as well as when a still image is captured // a serial dispatch queue must be used to guarantee that video frames will be delivered in order // see the header doc for setSampleBufferDelegate:queue: for more information videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL); [videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue]; if ( [self.captureSession canAddOutput:videoDataOutput] ) [self.captureSession addOutput:videoDataOutput]; [[videoDataOutput connectionWithMediaType:AVMediaTypeVideo] setEnabled:NO]; /*Take PHoto*/ // save the default format self.defaultFormat = videoDevice.activeFormat; defaultVideoMaxFrameDuration = videoDevice.activeVideoMaxFrameDuration; AVCaptureDevice *audioDevice= [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; AVCaptureDeviceInput *audioIn = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error]; [self.captureSession addInput:audioIn]; self.fileOutput = [[AVCaptureMovieFileOutput alloc] init]; [self.captureSession addOutput:self.fileOutput]; self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession]; self.previewLayer.frame = previewView.bounds; self.previewLayer.contentsGravity = kCAGravityResizeAspectFill; self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [previewView.layer insertSublayer:self.previewLayer atIndex:0]; [self.captureSession startRunning]; } return self; } - (void)switchCameras { // [self frontCamera]; // AVCaptureDevicePosition desiredPosition; // desiredPosition = AVCaptureDevicePositionFront; AVCaptureDevicePosition desiredPosition; NSInteger isFront = [[NSUserDefaults standardUserDefaults] integerForKey:#"isUsingFrontFacingCamera"]; if (isFront) desiredPosition = AVCaptureDevicePositionBack; else desiredPosition = AVCaptureDevicePositionFront; for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { if ([d position] == desiredPosition) { [[self.previewLayer session] beginConfiguration]; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil]; for (AVCaptureInput *oldInput in [[self.previewLayer session] inputs]) { [[self.previewLayer session] removeInput:oldInput]; } [[self.previewLayer session] addInput:input]; [[self.previewLayer session] commitConfiguration]; break; } } if (isFront==0) { [[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"isUsingFrontFacingCamera"]; } else { [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"isUsingFrontFacingCamera"]; } [[NSUserDefaults standardUserDefaults] synchronize]; //NSInteger isFront1= [[NSUserDefaults standardUserDefaults] integerForKey:#"isUsingFrontFacingCamera"]; }
FBLoginView: login isn't performed
I'm adding FBLoginView to my ViewController < FBLoginViewDelegate >: FBLoginView *loginview = [[FBLoginView alloc] init]; loginview.frame = CGRectOffset(loginview.frame, 5, 5); loginview.delegate = self; [self.view addSubview:loginview]; [loginview sizeToFit]; All the necessary fields in plist (FacebookAppID, FacebookDisplayName, URL Schemes) are all set according to the tutorial. The facebook app is also configured according to the tutorial (bundle ID is set, Facebook login is enabled). But the login still isn't performed. When I press on "log in", I get redirected to the browser with facebook login, but when it's finished, I'm not logged in the app (loginViewFetchedUserInfo:user: isn't called, "log in" hasn't changed to "log out"). What can be the problem?
Everything worked after I implemented the following in the AppDelegate.m (taken from one of the official examples): - (void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error { switch (state) { case FBSessionStateOpen: if (!error) { // We have a valid session //NSLog(#"User session found"); [FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) { if (!error) { self.loggedInUserID = user.id; self.loggedInSession = FBSession.activeSession; } }]; } break; case FBSessionStateClosed: case FBSessionStateClosedLoginFailed: [FBSession.activeSession closeAndClearTokenInformation]; break; default: break; } [[NSNotificationCenter defaultCenter] postNotificationName:FBSessionStateChangedNotification object:session]; if (error) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]; [alertView show]; } } /* * Opens a Facebook session and optionally shows the login UX. */ - (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI { return [FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:allowLoginUI completionHandler:^(FBSession *session, FBSessionState state, NSError *error) { [self sessionStateChanged:session state:state error:error]; }]; } /* * */ - (void) closeSession { [FBSession.activeSession closeAndClearTokenInformation]; } /* * If we have a valid session at the time of openURL call, we handle * Facebook transitions by passing the url argument to handleOpenURL */ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { // attempt to extract a token from the url return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication]; }
You need to add the following to the app delegate - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { // Call FBAppCall's handleOpenURL:sourceApplication to handle Facebook app responses BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication]; // You can add your app-specific url handling code here if needed return wasHandled; }
You may need to implement the (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url method Be sure to call: return [FBSession.activeSession handleOpenURL:url]; When applicable.
#Sergey: Are you want to open FBDialog on your native app or in browser? If you to want open in your native app then use "FBSessionLoginBehaviorForcingWebView". Here is my code that I am using: NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil]; FBSession *session = [[FBSession alloc] initWithPermissions:permission]; [FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ]; [[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) { switch (status) { case FBSessionStateOpen: [self yourmethod]; break; case FBSessionStateClosedLoginFailed: { // prefer to keep decls near to their use // unpack the error code and reason in order to compute cancel bool NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode]; NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason]; BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]); if(error.code == 2) { UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:#"FBAlertTitle" message:#"FBAuthenticationErrorMessage" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil]; [errorMessage performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES]; errorMessage = nil; } } break; // presently extension, log-out and invalidation are being implemented in the Facebook class default: break; // so we do nothing in response to those state transitions } }]; permission = nil; or you want to open in browser then use following : In your .h file #import <FacebookSDK/FacebookSDK.h> and add FBLoginViewDelegate delegate In you .m file FBLoginView *loginview = [[FBLoginView alloc] init]; loginview.frame = CGRectOffset(loginview.frame, 5, 5); loginview.delegate = self; [self.view addSubview:loginview]; [loginview sizeToFit]; // use following delegate methods - (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView { // first get the buttons set for login mode } - (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user { // here we use helper properties of FBGraphUser to dot-through to first_name and // id properties of the json response from the server; alternatively we could use // NSDictionary methods such as objectForKey to get values from the my json object NSLog(#"userprofile:%#",user); } - (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView { //BOOL canShareAnyhow = [FBNativeDialogs canPresentShareDialogWithSession:nil]; } - (void)loginView:(FBLoginView *)loginView handleError:(NSError *)error { // see https://developers.facebook.com/docs/reference/api/errors/ for general guidance on error handling for Facebook API // our policy here is to let the login view handle errors, but to log the results NSLog(#"FBLoginView encountered an error=%#", error); }
Singleton class for displaying iAds for iPhone
I have written a Singleton Class for managing iAds.The iAds pop up after 5 seconds of the user inactivity. The idleTimerExceeded call generate a notification to show the iAd. This code works fine for my requirements but since I am new to iOS development, my application sometimes hangs unexpectedly after integrating this code. This code results in lots of warnings etc. I would like to optimize my code in terms of memory and performance. I would be very thankful for your kind suggestions and reviews. Below is my code: iAdSingleton.h #import <Foundation/Foundation.h> #import "AppDelegate.h" #import "iAd/iAd.h" #interface iAdSingleton : UIViewController<ADBannerViewDelegate> { ADBannerView *adView; UIViewController *displayVC; NSTimer *idleTimer; BOOL isItFirstTime; } #property (nonatomic, retain) ADBannerView *adView; #property (nonatomic, retain) UIViewController *displayVC; #property (nonatomic) BOOL isItFirstTime; + (id) shareAdSingleton; - (void) resetIdleTimer; - (void) idleTimerExceeded; #end iAdSingleton.m #import "iAdSingleton.h" #implementation iAdSingleton static iAdSingleton* _sharedAdSingleton = nil; BOOL bannerVisible = NO; BOOL controlAccessBannerVisibility = NO; #synthesize adView, displayVC; #synthesize isItFirstTime; #define kMaxIdleTimeSeconds 5.0 +(id)sharedAdSingleton { #synchronized(self) { if(!_sharedAdSingleton) _sharedAdSingleton = [[self alloc] init]; return _sharedAdSingleton; } return nil; } +(id)alloc { #synchronized([iAdSingleton class]) { NSAssert(_sharedAdSingleton == nil, #"Attempted to allocate a second instance of a singleton."); _sharedAdSingleton = [super alloc]; return _sharedAdSingleton; } return nil; } -(id)init { self = [super init]; if (self != nil) { /* Initialize The Parameters Over Here */ //adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 480, 0, 0)]; adView = [[ADBannerView alloc] init]; adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait; self.adView.delegate=self; [self resetIdleTimer]; } return self; } -(void)dealloc { displayVC = nil; if (adView) { [adView removeFromSuperview]; //Remove ad view from superview [adView setDelegate:nil]; adView = nil; } [super dealloc]; } -(UIViewController *)viewControllerForPresentingModalView { return displayVC; } - (void)bannerViewDidLoadAd:(ADBannerView *)banner { banner.hidden = NO; if(!bannerVisible){ NSLog(#"Banner Changes 1 - Purpose: Visibility"); // [UIView beginAnimations:#"bannerAppear" context:NULL]; // banner.frame = CGRectOffset(banner.frame, 0, -100); // [UIView commitAnimations]; bannerVisible = YES; controlAccessBannerVisibility = YES; } } - (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error { //NSLog(#"Unable to receive Ad."); NSLog(#"Banner Changes 2 - Purpose: Unable to Receive Ad."); banner.hidden = YES; if(bannerVisible){ [UIView beginAnimations:#"bannerDisappear" context:NULL]; banner.frame = CGRectOffset(banner.frame, 0, 100); [UIView commitAnimations]; bannerVisible = NO; } } - (BOOL) bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave { NSLog(#"Pause anything necessary"); return YES; } - (void) bannerViewActionDidFinish:(ADBannerView *)banner { NSLog(#"We now resume to normal operations"); } - (void)resetIdleTimer { if (!idleTimer) { idleTimer = [[NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds target:self selector:#selector(idleTimerExceeded) userInfo:nil repeats:NO] retain]; } else { if (fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) { [idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]]; /* Notification: HideAd */ NSLog(#"Notification Generated For HideAd"); [[NSNotificationCenter defaultCenter] postNotificationName:#"HideAdBanner" object:nil userInfo:nil]; } } } - (void)idleTimerExceeded { AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate]; if (appDel.adVisible == NO) { NSLog(#"Notification Generated For ShowAd"); /* Notification: ShowAd */ if (controlAccessBannerVisibility == YES) { [[NSNotificationCenter defaultCenter] postNotificationName:#"ShowAdBanner" object:nil userInfo:nil]; } } } #end
This is what you need. This code is thread safe as well as will not have any memory issue and warnings. + (iAdSingleton *) sharedInstance { static dispatch_once_t onceToken; static iAdSingleton * __sharedInstance = nil; dispatch_once(&onceToken, ^{ __sharedInstance = [[self alloc] init]; }); return __sharedInstance; }
accessing unknown 'flipDelegate' component of a property
Hi when I am compiling my code i am getting this error-"accessing unknown 'flipDelegate' component of a property" this is the code from where i am getting error- // // RootViewController.m // Dolphia // // Created by Dolphia Nandi on 4/3/11. // Copyright 2011 State University of New York at Buffalo. All rights reserved. // #import "RootViewController.h" #import "MainViewController.h" #import "FlipSideViewController.h" #implementation RootViewController #synthesize mainViewController; #synthesize flipSideViewController; - (void)loadMainViewController { MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil]; self.mainViewController = viewController; self.mainViewController.flipDelegate = self; [viewController release]; } - (void)loadFlipSideViewController { FlipSideViewController *viewController = [[FlipSideViewController alloc] initWithNibName:#"FlipSideViewController" bundle:nil]; self.flipSideViewController = viewController; self.flipSideViewController.flipDelegate = self; [viewController release]; } - (void)viewDidLoad { [self loadMainViewController]; // Don't load the flipside view unless / until necessary [self.view addSubview:mainViewController.view]; } // This method is called when either of the subviews send a delegate message to us. // It flips the displayed view from the whoever sent the message to the other. - (void)toggleView:(id)sender { if (flipSideViewController == nil) { [self loadFlipSideViewController]; } UIView *mainWindow = mainViewController.view; UIView *flipSideView = flipSideViewController.view; /*[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:1]; if(flipeffect >= 0 && flipeffect < 2) { flipeffect++; [UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES]; } else if (flipeffect >= 2 && flipeffect < 4) { flipeffect++; [UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionCurlUp : UIViewAnimationTransitionCurlDown) forView:self.view cache:YES]; } else if (flipeffect >= 4 && flipeffect < 6) { flipeffect++; [UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.view cache:YES]; } else { flipeffect++; if(flipeffect > 7) flipeffect = 0; [UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionCurlDown : UIViewAnimationTransitionCurlUp) forView:self.view cache:YES]; }*/ if (mainViewController == sender) { [flipSideViewController viewWillAppear:YES]; [mainViewController viewWillDisappear:YES]; [mainWindow removeFromSuperview]; [self.view addSubview:flipSideView]; [mainViewController viewDidDisappear:YES]; [flipSideViewController viewDidAppear:YES]; } else { [mainViewController viewWillAppear:YES]; [flipSideViewController viewWillDisappear:YES]; [flipSideView removeFromSuperview]; [self.view addSubview:mainWindow]; [flipSideViewController viewDidDisappear:YES]; [mainViewController viewDidAppear:YES]; } //[UIView commitAnimations]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview // Release anything that's not essential, such as cached data } - (void)dealloc { [mainViewController release]; [flipSideViewController release]; [super dealloc]; } #end
Both mainViewController and flipSideViewController should have flipDelegate as instance variable and make sure you add #synthesize and #property