iOS App killed But AppleWatch Can Send Messag To it ? why? - apple-watch

AppleWatch Enterforground, Watch client send dictionary of "#{#"check":#"I'm Back"} "
iOS client receive "#{#"check":#"I'm Back"} " , replay dictionary with static num i as "#{#"check":#"Rcheck_i"}"
kill iOS Client
AppleWatch enterbackground, 5 second , enterforround , AppleWatch receive message from ios client as "#{#"check":#"Rcheck_i"}", what's wrong???
who can help me,the code is ...
//iOS Client
static int i = 0;
- (void) session:(nonnull WCSession *)session didReceiveMessage:(nonnull NSDictionary<NSString *,id> *)message replyHandler:(nonnull void (^)(NSDictionary<NSString *,id> * __nonnull))replyHandler{
dispatch_async(dispatch_get_main_queue(), ^{
i++;
NSString *temKey = [message.allKeys objectAtIndex:0];
NSString *temStr = [NSString stringWithFormat:#"%#_%d",temKey,i];
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = temStr;
});
if([message objectForKey:#"check"]){
NSString *temStr = [NSString stringWithFormat:#"Rcheck_%d",i];
replyHandler(#{#"check":temStr});
}
});
}
//AppleWatch Client
static int i = 0;
- (void)willActivate {
[super willActivate];
i++;
if ([WCSession isSupported] ) {
WCSession* session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
[self performSelector:#selector(checkAction) withObject:nil afterDelay:0.1];
}
else{
[self.lblLockState setText:#"WATCH NOT support"];
}
}
- (void) checkAction{
WCSession* session = [WCSession defaultSession];
[session sendMessage:#{#"check":#"I'm Back"} replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *temStr;
if ([replyHandler objectForKey:#"check"]) {
temStr = [replyHandler objectForKey:#"check"] ;//[NSString stringWithFormat:#"CheckSucc_%d",i];
}
else{
temStr = [NSString stringWithFormat:#"CheckSucc??_%d",i];
}
[self.lblLockState setText:temStr];
});
} errorHandler:^(NSError * _Nonnull error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *temStr = [NSString stringWithFormat:#"CheckFail_%d",i];
[self.lblLockState setText:temStr];
});
}];
}

Related

Messages Extension Send Audio File

I have this URL
myString =
file:///var/mobile/Containers/Data/PluginKitPlugin/-------/Documents/MyAudio.m4a
and here is my send code
MSConversation * conversation = self.activeConversation;
if (conversation) {
MSMessageTemplateLayout * activeLayout = [[MSMessageTemplateLayout alloc] init];
// activeLayout.image = image;
activeLayout.caption = #"Message Counter";
activeLayout.subcaption = #"Message subcaption";
activeLayout.trailingCaption = #"Trailing caption";
activeLayout.trailingSubcaption = #"Trailing Subcaption";
activeLayout.mediaFileURL = [NSURL URLWithString:myString];
activeLayout.imageTitle = #"Image counter";
activeLayout.imageSubtitle = #"Image subtitle";
MSMessage * message = [[MSMessage alloc] init];
message.layout = activeLayout;
message.URL = [NSURL URLWithString:#"Empty URL"];
message.summaryText = #"This is Summary";
[conversation insertMessage:message completionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error sending message %#", [error localizedDescription]);
}
}];
}
else {
NSLog(#"No &%#%&^# conversation found");
}
i can't get the audio file for sending i have just Message Counter and etc..
Instead of using insertMessage use insertAttachment-
[[conversation insertAttachment:[NSURL URLWithString:myString]; withAlternateFilename:#"Alternate Name" completionHandler:^(NSError * error) {
DDLogInfo(#"Error is %#",error);
}];

Javascript Youtube API: buffering for ever - UIWebView iOS

I am using the YouTube API in UIWebView.
I have created a NSString with the HTML5 player that I load in the UIWebView. Everything works perfectly on iPhone 5 and iPad.
But, if I test the app using an iPhone 4, the player returns the buffering state all the time. Only if I explicitly press the play button, the player starts playing, without stopping again for buffering. It seems that although the video has been buffered, the player still gives me this state.
Is anyone aware of this problem? Any idea?
Thank you very much in advance!!
In LBYouTubePlayerViewController.m file
Replace Following method on yr old Method....
then test...
-(NSURL*)_extractYouTubeURLFromFile:(NSString *)html error:(NSError *__autoreleasing *)error {
NSString *JSONStart = nil;
// NSString *JSONStartFull = #"ls.setItem('PIGGYBACK_DATA', \")]}'";
NSString *JSONStartFull = #"bootstrap_data = \")]}'";
NSString *JSONStartShrunk = [JSONStartFull stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([html rangeOfString:JSONStartFull].location != NSNotFound)
JSONStart = JSONStartFull;
else if ([html rangeOfString:JSONStartShrunk].location != NSNotFound)
JSONStart = JSONStartShrunk;
if (JSONStart != nil) {
NSScanner* scanner = [NSScanner scannerWithString:html];
[scanner scanUpToString:JSONStart intoString:nil];
[scanner scanString:JSONStart intoString:nil];
NSString *JSON = nil;
[scanner scanUpToString:#"}\";" intoString:&JSON];
JSON = [NSString stringWithFormat:#"%#}",JSON]; // Add closing bracket } to get vallid JSON again
// [scanner scanUpToString:#"\");" intoString:&JSON];
JSON = [self _unescapeString:JSON];
NSError* decodingError = nil;
NSDictionary* JSONCode = nil;
// First try to invoke NSJSONSerialization (Thanks Mattt Thompson)
id NSJSONSerializationClass = NSClassFromString(#"NSJSONSerialization");
SEL NSJSONSerializationSelector = NSSelectorFromString(#"dataWithJSONObject:options:error:");
if (NSJSONSerializationClass && [NSJSONSerializationClass respondsToSelector:NSJSONSerializationSelector]) {
JSONCode = [NSJSONSerialization JSONObjectWithData:[JSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&decodingError];
}
else {
JSONCode = [JSON objectFromJSONStringWithParseOptions:JKParseOptionNone error:&decodingError];
}
if (decodingError) {
// Failed
*error = decodingError;
}
else {
// Success
NSDictionary *dict = [JSONCode objectForKey:#"content"];
NSDictionary *dictTemp = [dict objectForKey:#"video"];
NSArray* videos = [dictTemp objectForKey:#"fmt_stream_map"];
NSString* streamURL = nil;
if (videos.count) {
NSString* streamURLKey = #"url";
if (self.quality == LBYouTubePlayerQualityLarge) {
streamURL = [[videos objectAtIndex:0] objectForKey:streamURLKey];
}
else if (self.quality == LBYouTubePlayerQualityMedium) {
unsigned int index = MAX(0, videos.count-2);
streamURL = [[videos objectAtIndex:index] objectForKey:streamURLKey];
}
else {
streamURL = [[videos lastObject] objectForKey:streamURLKey];
}
}
if (streamURL) {
return [NSURL URLWithString:streamURL];
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:2 userInfo:[NSDictionary dictionaryWithObject:#"Couldn't find the stream URL." forKey:NSLocalizedDescriptionKey]];
}
}
}
else {
*error = [NSError errorWithDomain:kLBYouTubePlayerControllerErrorDomain code:3 userInfo:[NSDictionary dictionaryWithObject:#"The JSON data could not be found." forKey:NSLocalizedDescriptionKey]];
}
return nil;
}

GCDAsyncSocket "didReadDataWithTag" Never called with NSOperation subclass

In a "getMyFile" method of some XIB file.
I am creating a object of class "A"(subclass of NSOperation) and adding it to a "myFileQueue"(object of NSOperationQueue).
myFileQueue.MaxConcurrentOperationCount = 1;
Problem : didReadDataWithTag" delegate NEVER called in any case.
#import "GCDAsyncSocket.h"
//and all other required classes are imported correctly
//Class : A
#interface A : NSOperation
{
{
GCDAsyncSocket* socket;
dispatch_queue_t dQueue;
BOOL isWorkDone;
}
}
#implementation A {
-main(){
#autoreleasepool {
isWorkDone = NO;
dQueue = dispatch_queue_create(#"MyDQueue", NULL);
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dQueue];
//NOTE: Even after setting delegateQueue: dispatch_get_main_queue()
//didReadDataWithTag delegate never called
NSError *err = nil;
if (![socket connectToHost:#"192.168.1.142" onPort:12345 error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
do{
[NSThread sleep:0.2];
}while(!isWorkDone)
}
}
- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port
{
NSString* myString= #"testing";
NSData* data=[myString dataUsingEncoding: [NSString defaultCStringEncoding] ];
[socket writeData:data withTimeout:-1 tag:1];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[socket readDataToData:[GCDAsyncSocket ZeroData] withTimeout:-1 tag:TAG_RESPONSE_HEADER];
}
- (void)socket:(GCDAsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag
{
NSLog(#"didReadDataWithTag called...."); //this method never called in any case
isWorkDone = YES;
}
}

How to get user details using twitter api v1.1 (Twitter error 215)

I have used the twitter api provided by twitter,to get the details but
not able to execute it, even tried to pass the authentication data
like consumer secret key, consumer key, token but the result is same.
I am able to login and receiving twitter authentication token but not able to get user details.
Below code is used by me (I am using MGtwitter engine) :
NSMutableURLRequest *request =[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1.1/users/show.json?screen_name=%#",username]]];
NSData *returnData = [ NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil ];
NSString *returnString = [[NSString alloc]initWithData:returnData encoding:NSUTF8StringEncoding];
NSError *err = nil;
twitterLogin = [NSJSONSerialization JSONObjectWithData:[returnString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err];
Error is shown as below:
errors = (
{
code = 215;
message = "Bad Authentication data";
} );
First, you need to Authenticate your request (Get permission).
second, see follow these steps:
1.Download FHSTwitterEngine Twitter Library.
2.Add the folder FHSTwitterEngine" to your project and #import "FHSTwitterEngine.h".
3.add SystemConfiguration.framework to your project.
Usage : 1.in the [ViewDidLoad] add the following code.
UIButton *logIn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
logIn.frame = CGRectMake(100, 100, 100, 100);
[logIn setTitle:#"Login" forState:UIControlStateNormal];
[logIn addTarget:self action:#selector(showLoginWindow:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:logIn];
[[FHSTwitterEngine sharedEngine]permanentlySetConsumerKey:#"<consumer_key>" andSecret:#"<consumer_secret>"];
[[FHSTwitterEngine sharedEngine]setDelegate:self];
and don't forget to import the delegate FHSTwitterEngineAccessTokenDelegate.
you need to get the permission for your request, with the following method which will present Login window:
- (void)showLoginWindow:(id)sender {
[[FHSTwitterEngine sharedEngine]showOAuthLoginControllerFromViewController:self withCompletion:^(BOOL success) {
NSLog(success?#"L0L success":#"O noes!!! Loggen faylur!!!");
}];
}
when the Login window is presented, enter your Twitter Username and Password to authenticate your request.
add the following methods to your code:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[FHSTwitterEngine sharedEngine]loadAccessToken];
NSString *username = [[FHSTwitterEngine sharedEngine]loggedInUsername];// self.engine.loggedInUsername;
if (username.length > 0) {
lbl.text = [NSString stringWithFormat:#"Logged in as %#",username];
[self listResults];
} else {
lbl.text = #"You are not logged in.";
}
}
- (void)storeAccessToken:(NSString *)accessToken {
[[NSUserDefaults standardUserDefaults]setObject:accessToken forKey:#"SavedAccessHTTPBody"];
}
- (NSString *)loadAccessToken {
return [[NSUserDefaults standardUserDefaults]objectForKey:#"SavedAccessHTTPBody"];
}
4.Now you are ready to get your request, with the following method(in this method I created a Twitter search for some Hashtag, to get the screen_name for example):
- (void)listResults {
dispatch_async(GCDBackgroundThread, ^{
#autoreleasepool {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// the following line contains a FHSTwitterEngine method wich do the search.
dict = [[FHSTwitterEngine sharedEngine]searchTweetsWithQuery:#"#iOS" count:100 resultType:FHSTwitterEngineResultTypeRecent unil:nil sinceID:nil maxID:nil];
// NSLog(#"%#",dict);
NSArray *results = [dict objectForKey:#"statuses"];
// NSLog(#"array text = %#",results);
for (NSDictionary *item in results) {
NSLog(#"text == %#",[item objectForKey:#"text"]);
NSLog(#"name == %#",[[item objectForKey:#"user"]objectForKey:#"name"]);
NSLog(#"screen name == %#",[[item objectForKey:#"user"]objectForKey:#"screen_name"]);
NSLog(#"pic == %#",[[item objectForKey:#"user"]objectForKey:#"profile_image_url_https"]);
}
dispatch_sync(GCDMainThread, ^{
#autoreleasepool {
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Complete!" message:#"Your list of followers has been fetched" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
});
}
});
}
That's all.
I just got the screen_name from a search Query, you can get a timeline for a user using the following methods:
// statuses/user_timeline
- (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count;
- (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID;
instead of the search method above.
Note: see the FHSTwitterEngine.h to know what method you need to use.
Note: to get the <consumer_key> and the <consumer_secret> you need to to visit this link
to register your app in Twitter.
Got the solution after MKAlatrash revert, to get the user profile follow certain steps in the code as under :
[[FHSTwitterEngine sharedEngine]getProfileImageForUsername:username andSize:FHSTwitterEngineImageSizeNormal];
jump to definition of this function and replace the if ... else if part
if ([userShowReturn isKindOfClass:[NSError class]]) {
return [NSError errorWithDomain:[(NSError *)userShowReturn domain] code:[(NSError *)userShowReturn code] userInfo:[NSDictionary dictionaryWithObject:request forKey:#"request"]];
NSLog(#"user show return %#",userShowReturn);
} else if ([userShowReturn isKindOfClass:[NSDictionary class]]) {
return userShowReturn;
NSString *url = [userShowReturn objectForKey:#"profile_image_url"]; // normal
if (size == 0) { // mini
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#"_mini"];
} else if (size == 2) { // bigger
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#"_bigger"];
} else if (size == 3) { // original
url = [url stringByReplacingOccurrencesOfString:#"_normal" withString:#""];
}
id ret = [self sendRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
if ([ret isKindOfClass:[NSData class]]) {
return [UIImage imageWithData:(NSData *)ret];
}
return ret;
}
That really was helpful thanks

How Can i Know if GKAchievement is Completed?

I have built objectives for my game and everything works just fine accept the part of making the objectives not be called any more after any of them is completed.
I know there is a Property of the GKAchievement Class "completed" which is a boolean that returns yes when the Achievement is 100 percent done.
here is the method that called when a Achievement is 100 percent done it passes id which is the Achievement identifier and report the acheeee :
- (void)AchivmentDidAchive:(id)Achivment{
NSString *identifier = Achivment;
NSLog(#"%#",identifier);
self.achivment = [[GKAchievement alloc]initWithIdentifier:identifier];
self.achivment.showsCompletionBanner = YES;
if (!self.achivment.completed) {
self.achivment.percentComplete = 100;
NSLog(#"Reproting!");
[self.achivment reportAchievementWithCompletionHandler: ^(NSError *error)
{
}];
}
else {
NSLog(#"Achivment Completed!");
} }
what I am trying to do here is to set the percent completed to 100 and report it so in the next time ie want get called again.
but it always works... any better idea for how to handle this?
in interface add variable & property:
NSMutableDictionary *earnedAchievementCache;
#property (nonatomic, retain)NSMutableDictionary *earnedAchievementCache;
in .m:
#synthesize earnedAchievementCache;
- (void) submitAchievement: (NSString*) identifier percentComplete: (double) percentComplete
{
if(self.earnedAchievementCache == NULL)
{
[GKAchievement loadAchievementsWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if(error == NULL)
{
NSMutableDictionary* tempCache= [NSMutableDictionary dictionaryWithCapacity: [scores count]];
for (GKAchievement* score in scores)
{
[tempCache setObject: score forKey: score.identifier];
}
self.earnedAchievementCache= tempCache;
[self submitAchievement: identifier percentComplete: percentComplete];
}
}];
}
else
{
GKAchievement* achievement= [self.earnedAchievementCache objectForKey: identifier];
if(achievement != NULL)
{
if((achievement.percentComplete >= 100.0) || (achievement.percentComplete >= percentComplete))
{
achievement= NULL;
}
achievement.percentComplete= percentComplete;
}
else
{
achievement= [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
achievement.percentComplete= percentComplete;
[self.earnedAchievementCache setObject: achievement forKey: achievement.identifier];
}
if(achievement!= NULL)
{
//Submit the Achievement...
if (achievement.percentComplete>=100) {
//show banner
achievement.showsCompletionBanner = YES; //only in IOS 5+
}
[achievement reportAchievementWithCompletionHandler: ^(NSError *error)
{
if (error!=NULL){
NSLog(#"Error!!");
} else NSLog(#"all is well");
}];
}
}
}
in dealloc :
[self.earnedAchievementCache release];
i'm using the cache to not submit scores already submitted / completed
PS: the code is perfect just copy and paste it into your class and it will work
this is what I use in my helper Game Center class:
-(void) reportAchievementWithID:(NSString*) AchievementID {
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) {
if(error) NSLog(#"error");
for (GKAchievement *ach in achievements) {
if([ach.identifier isEqualToString:AchievementID]) { //already submitted
NSLog(#"Already submitted");
return ;
}
}
GKAchievement *achievementToSend = [[GKAchievement alloc] initWithIdentifier:AchievementID];
achievementToSend.percentComplete = 100;
achievementToSend.showsCompletionBanner = YES;
[achievementToSend reportAchievementWithCompletionHandler:NULL];
}];
}
note: I don't use percentages in my achievements, so you'd need to modify things a little bit if you do.