I have integrated the Google Plus iOS SDK v1.2.1 into my iOS app. After authentication I am trying to fetch the user's activity feed. My code is the following:
GTLServicePlus* plusService = [[GTLServicePlus alloc] init];
[plusService setAuthorizer:[GPPSignIn sharedInstance].authentication];
plusService.retryEnabled = YES;
GTLQueryPlus *query = [GTLQueryPlus queryForActivitiesListWithUserId:#"me" collection:kGTLPlusCollectionPublic];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusActivityFeed *data,
NSError *error) {
for (GTLPlusActivity *activity in data.items) {
// ITERATE THROUGH THE ACTIVITIES
NSString *publishedDate = activity.published; <---- ERROR
// "PROPERTY 'published' CANNOT BE FOUND
// IN FORWARD CLASS OBJECT "GTLPLusActivity""
// WHY ARE THE VARIABLES SUCH AS published, placeName,
// title, actor etc NOT ACCESSIBLE
}
}];
I am able to successfully retrieve the posts of the user. The GTLPlusActivity class has many properties as shown in the image:
Whenever I try to access the properties using the "." operator such as "activity.actor" in the for loop, it gives the error "Property 'actor' cannot be found in forward class object 'GTLPlusActivity'". Why am I unable to access the properties? I need to display them in a UITableView.
EDIT: Code Snapshot. Error clearly displayed in Red.
Firstly, check the error condition and make sure the error code is nil. I have tried your code, and it works correctly on my end, so most likely, there is a problem with the response you are getting back. Generally activity.actor will return a GTLPlusActivityActor.
Try something like:
if (error) {
NSLog(#"Status: Error: %#", error);
}
else
<Do stuff>
EDIT: Also, our iOS quick-start is a great resource for seeing how we handle certain parts of the code. The ListMoments bit is pretty similar to dealing with Activities.
https://developers.google.com/+/quickstart/ios
EDIT 2: Also, make sure you have all of the right imports. Try
#import "GTLPlusActivity.h"
or
#import "GTLPlus.h"
Related
This is my code:
// Create a service object for executing queries
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Services which do not require sign-in may need an API key from the
// API Console
service.APIKey = #"AIzaSyD9pvsUtnegJvwv5z5XrBO5vFTBVpErYN8";
// Create a query
GTLQueryYouTube *query = [GTLQueryYouTube queryForSearchListWithPart:#"id"];
query.maxResults = 50;
query.q = #"hiking boots";
//query.country = #"US";
// Execute the query
GTLServiceTicket *ticket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
// This callback block is run when the fetch completes
if (error == nil) {
GTLYouTubeSearchListResponse *products = object;
// iteration of items and subscript access to items.
for (GTLYouTubeSearchResult *item in products) {
//NSLog(#"%#",item.identifier); - THIS WORKS, BUT GIVES ME THE WHOLE IDENTIFIER, I JUST WANT THE VIDEO ID
NSLog(#"%#",item.identifier.videoId);
}
}else{
NSLog(#"Error: %#", error.description);
}
}];
If you'll notice the comment above my first NSLog, I'm able to print out a number of things without any issue. But if I try to print out a property of item.identifier, the app crashes completely.
The crash log is this:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[GTLYouTubeVideo videoId]: unrecognized selector sent
Now, item.identifier is a GTLYouTubeResourceId, so why is it thinking that I'm trying to get properties from a GTLYoutubeVideo???
Thanks for the help!
Try accessing the JSON of the identifier object directly. There appears to be a "videoId" value in there.
like this:
[item.identifier.JSON objectForKey:#"videoId"]
Now, item.identifier is a GTLYouTubeResourceId
Apparently, it isn't.
so why is it thinking that I'm trying to get properties from a GTLYoutubeVideo???
Because you wrote three consecutive question marks. Because it's a GTLYoutubeVideo instance, in fact. Sorry, C (and thus Objective-C) is not a very type-safe language. You can declare objects to be of some type, and they can be assigned a pointer to some other kind of object at runtime.
Here, I suspect you either misread something in the documentation or there's a bug in the client library or this is a weird memory management error, but one thing is sure: the runtime is always right.
I have the following cpde:
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, ABRecordGetRecordID(self.recordRef_));
CFErrorRef error = NULL;
if ([self.nameTextField_.text isNotNull]){
NSArray *nameStringArray = [self.nameTextField_.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef)([nameStringArray objectAtIndex:0]), NULL);
if ([nameStringArray count] > 1){
ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFTypeRef)([nameStringArray lastObject]), &error);
}
}
However, after this code it gives me this error:
Error Domain=ABAddressBookErrorDomain Code=0 "The operation couldn’t be completed. (ABAddressBookErrorDomain error 0.)"
Any idea why this is?
The error message seems to be pretty useless, but as the rest of your code looks to be valid, my guess is that your application hasn't been authorized by the user to access the Address Book database. Use code like the following to check your authorization status before attempting to access the Adress Book:
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// We're good to go
} else {
// Hasn't been authorized by the user
// You can check the exact authorization status for more information on the
// exact reason why you can't access the Address Book (e.g. denied, restricted, etc.)
}
This happens when the Contact backend that you are using doesn't handle the field you are trying to add to the contact. In your case, I suspect your backend doesn't handle write operations at all.. which is quite the surprise.
See Apple documentation on the subject:
enum {
kABOperationNotPermittedByStoreError = 0,
kABOperationNotPermittedByUserError
};
kABOperationNotPermittedByStoreError
The operation is not allowed by the Address Book database, because the contact’s source does not support it.
Available in iOS 2.0 and later.
kABOperationNotPermittedByUserError
The operation is not allowed because the user denied access to the Address Book database.
Available in iOS 6.0 and later.
I'm trying to create a reminder calendar so I can add and delete reminders. It is actually working well on the devices I use (iPhone 5/4S/4) but on certain client devices which are still iPhones - I'm getting this error below about the account not supporting reminders.
Here is the workflow:
* Init the event store.
* Request permission (check its granted for Reminder types) (iOS6+) for lower we just init.
* Create a new calendar, local storage, type = Reminder
* Save calendar to get its Identifier.
Works most of the time, this appears on some devices -
Error Domain=EKErrorDomain Code=24 “That account does not support reminders.”
Permissions are granted and checked under Settings, Privacy, Reminders. I can't find anything in the docs about the conditions under which you'd get this error.
Thanks!
Not sure if you still need this but here is what i ran into.
First of all i'm pretty sure that reminders cannot be set on a calendar with a local source. I kept getting the "That account does not support reminders". Even after setting all non read only properties on the calendar before committing to the event store it still didn't work. The source needs to be calDav. Then I tried Devfly's response and it didn't work either but for a different reason. It kept fetching my gmail calendar which does not allow setting reminders (i think its actually read only for events and reminders). So i used the following code to get the actual iCloud source
for (EKSource *source in sources) {
NSLog(#"source %#",source.title);
if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:#"iCloud"]) {
localSource = source;
break;
}
}
This setting this source on my new reminders calendar worked for me. hope it helps someone
First, just a check: you are creating a "new calendar" (a whole calendar), not just a "new reminder", right?
Second: are you using iOS6? Reminders are available (in EventKit) only starting from iOS6: link
As commented by Jesse Rusak, this happens because you are probably creating the new calendar inside an account/source that doesn't support reminders.
How do you create the new calendar?
Do you set the source property?
the first thing you can try, is to loop all sources until you find a suitable one.
EKSourceTypeLocal supports reminders. iCal too.
Here a list of EKSourceType
typedef enum {
EKSourceTypeLocal,
EKSourceTypeExchange,
EKSourceTypeCalDAV,
EKSourceTypeMobileMe,
EKSourceTypeSubscribed,
EKSourceTypeBirthdays
} EKSourceType;
Find a suitable one:
// find local source for example
EKSource *localSource = nil;
for (EKSource *source in store.sources)
{
if (source.sourceType == EKSourceTypeLocal) // or another source type that supports
{
localSource = source;
break;
}
}
Then, create the new calendar setting the right source
EKCalendar *cal;
if (identifier == nil)
{
cal = [EKCalendar calendarForEntityType:EKEntityTypeReminder eventStore:store];
cal.title = #"Demo calendar";
cal.source = localSource;
[store saveCalendar:cal commit:YES error:nil];
}
Try and let me know
What solved my problem is not saving the calendar to the local source, but instead to EKSourceTypeCalDAV (iCloud). It works, and it's synced across all devices.
The local store may not support reminders. This is reproducible if iCloud is enabled.
This is the most reliable solution I could find, without hard-coding any assumptions:
let calendar = EKCalendar(forEntityType: .Reminder, eventStore: eventStore)
if eventStore.sources.count == 0 { // reproducible after Reset Content and Settings
calendar.source = EKSource()
}
else {
calendar.source = eventStore.defaultCalendarForNewReminders().source
}
eventStore.saveCalendar(calendar, commit: true)
Alright I've been debugging the whole day but can't figure out what the problem is with my code.
The goal is to send a POST with RestKit to the Heroku API with a username/password to retrieve the API key.
The problem is that I'm only able to sent the request once. When sending the request the second time I get errors. (So first time I do get the API key binded to my object, but the second time just a error)
I'm using the current version of RestKit (0.10)
The code:
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObject:(id)object
{
Account *account = (Account *)object;
NSLog(#"API_KEY: %#", account.apiKey);
}
- (IBAction) login:(id)sender
{
Account *account = [[Account alloc] init];
account.email = [emailField text];
account.password = [passwordField text];
[[RKObjectManager sharedManager] postObject:account delegate:self];
}
LOG
/// ---> FIRST CLICK
2012-05-25 14:57:00.028 HerokuApp[11154:fb03] API_KEY: 1234567890
/// ---> SECOND CLICK
2012-05-25 14:57:03.427 HerokuApp[11154:fb03] W restkit.network:RKObjectLoader.m:281 Unable to find parser for MIME Type 'text/html'
2012-05-25 14:57:03.427 HerokuApp[11154:fb03] W restkit.network:RKObjectLoader.m:309 Encountered unexpected response with status code: 200 (MIME Type: text/html -> URL: https://api.heroku.com/login -- https://api.heroku.com -- https://api.heroku.com -- https://api.heroku.com)
2012-05-25 14:57:03.429 HerokuApp[11154:fb03] didFailWithError: Error Domain=org.restkit.RestKit.ErrorDomain Code=4 "The operation couldn’t be completed. (org.restkit.RestKit.ErrorDomain error 4.)"
Can anybody help me explaining why this behaviour is occuring?
Perhaps the API behaves differently when you are logged in. From your log messages, it is appearing to return back text/html content, and not something that RestKit knows how to deal with.
Run in the simulator on a machine where Wireshark is capturing packets. Reproduce the error, then find the TCP stream where this is happening and look at it. If you need help, update your question with the result of "Follow Stream" in Wireshark so that we can see the full HTTP traffic.
hi everyone i am new to iphone development and started with some sample application.
In sample application i am using webservices..i went through this tutorial http://code.google.com/p/wsdl2objc/wiki/UsageInstructions and understood about wsdl2objc..
but this tutorial is too short so can anyone suggest similar like tutorial or examples so tat is still more clear...
thank u
All depends on your web service class name etc as wsdl2objc makes up alot of your NSObjects and methods based upon this, however,
suggesting that you are using soap 1.2 bindings and your web service was called 'SimpleService', the following would call a web method named 'MobileTestService and return back the integer value from the xml generated.
-(NSString *)returnThatStringFromWebServiceResult {
SimpleServiceSoap12Binding * binding = [SimpleService SimpleServiceSoap12Binding];
binding.logXMLInOut = YES; // shows all in the console log.
SimpleService_concat * testParams = [[SimpleService_concat new]autorelease];
testParams.s1 = someTextField.text; // parameters all become properties of this testParams object
testParams.s2 = anotherTextField.text;
SimpleServiceSoap12BindingResponse * response= [binding SimpleService_concatUsingParameters:testParams];
[response self]; // removes compile error
NSArray * responseBodyParts = response.bodyParts;
NSError * responseError = response.error;
if (responseError!=NULL) {
return #""; // if error from ws use [responeError code]; for http err code
}
for (id bodyPart in responseBodyParts)
{
if ([bodyPart isKindOfClass:[SimpleService_concat_Response class]])
{
SimpleService_concatResponse* body = (SimpleService_concatResponse*) bodyPart;
return body.SimpleService_concatResult; // if you are returning a string from your WS then this value will be a string,
}
}
}