Git Product home page Git Product logo

skygear-sdk-ios's Introduction

Skygear Logo

Skygear SDK for iOS

CocoaPods CocoaPods Build Status License

Skygear Server is a cloud backend for making web and mobile app development easier. https://skygear.io

The SKYKit (Skygear iOS SDK) library that gives you access to the Skygear Server from your iOS app.

Getting Started

To get started, you need to have the Skygear Server running and iOS SDK installed into your app. You can see detailed procedure at the getting started guide at https://docs.skygear.io/guides/intro/quickstart/ios/.

You can sign up the Skygear Hosting at the Skygear Developer Portal at https://portal.skygear.io

Installation with CocoaPods

You can install SKYKit via CocoaPods, first you need to install CocoaPods

$ gem install cocoapods

To integrate SKYKit into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

pod 'SKYKit'

Subspec

Podspec 'SKYKit' include everything you are required to interact with Skygear, that includes functionalities, like Facebook login and Forgot password. If you want to make the dependency slimmer, you can use the SKYKit/Core subspec.

# Install everything
pod `SKYKit`

# Only install the core functionality
pod `SKYKit/Core`

# You can pick which options do you want
pod `SKYKit/Facebook`
pod `SKYKit/ForgotPassword`

Then, run the following command:

$ pod install

For more detail and other installation guides, please refer to our Get Started Guide at the Skygear docs site.

Documentation

The full documentation for Skygear is available on our docs site. The iOS SDK get started guide is a good place to get started.

Support

For implementation related questions or technical support, please find us on the official forum or community chat.

If you believe you've found an issue with Skygear iOS SDK, please feel free to report an issue.

How to contribute

Pull Requests Welcome!

We really want to see Skygear grows and thrives in the open source community. If you have any fixes or suggestions, simply send us a pull request!

License & Copyright

Copyright (c) 2015-present, Oursky Ltd.
All rights reserved.

This source code is licensed under the Apache License version 2.0
found in the LICENSE file in the root directory of this source tree.
An additional grant of patent rights can be found in the PATENTS
file in the same directory.

skygear-sdk-ios's People

Contributors

a821246710 avatar b123400 avatar ben181231 avatar carmenlau avatar cheungpat avatar chpapa avatar cpandrewchung avatar cychiuae avatar david90 avatar howawong avatar joyzoursky avatar kaojohnny avatar limouren avatar rickmak avatar royuen avatar steven-chan avatar tensiuyan avatar wallacesky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

skygear-sdk-ios's Issues

[SKYDatabase-saveSubscription:completionHandler:] would always fail to save a subscription

Using the method to save subscription would always lead to the follow error:

Error Domain=SKYOperationErrorDomain Code=108 "The server is unable to process the data." UserInfo={SKYErrorName=InvalidArgument, SKYErrorMessage=empty device_id, NSErrorFailingURLKey=http://127.0.0.1:3000/subscription/save, SKYOperationErrorHTTPStatusCodeKey=400, arguments=<CFArray 0x79889ba0 [0x56181f8]>{type = immutable, count = 1, values = (
    0 : <CFString 0x798810f0 [0x56181f8]>{contents = "device_id"}
)}, NSLocalizedDescription=The server is unable to process the data.}

skygear-server now requires subscription:save to supply device_id, but saveSubscription:completionHandler: didn't, leading to this error.

Add Relation API

The following api should be exposed in container (or relation container), and can be called directly.

  • queryFriend
  • queryFollower
  • queryFollowing
  • addRelation
  • removeRelation

They are now existing as SKYAddRelationsOperation, SKYRemoveRelationsOperation and SKYQueryOperation+QueryUser in the sdk.

Persist current user information

I am suggesting that we persist current user information in SKYContainer. While the whoami action solves the problem for the client to find out the current user, asking the server each time the client want to figure out the username seems excessive.

The swift example app have this problem and it workaround this problem by storing the username outside of SKYContainer.

Ambiguous API for `accessControl.setNoAccessForXXX()`

In current implementation, accessControl.setNoAccessForUser(userID) and accessControl.setNoAccessForRole(someRole) does not deny the access of specific user / role. What it actually does is remove the access control entry for specific user / role.

[OAuth] Add new APIs for logging in to Facebook and Google

connect SkygearIO/features#5

  • -[SKYContainer loginWithFacebook:(NSDictionary*)options] and
  • -[SKYContainer loginWithGoogle:(NSDictionary*)options]
    • options
      • uxMode - Either popup(default), or redirect, popup means in-app-browser (SFSafariViewController/WKWebView) and redirect means Safari.app
      • clientID
      • scope
      • version - FB Client SDK only
      • cookiePolicy - Google Client SDK only
      • use3rdPartyClient - whether to use 3rd party client, e.g. Facebook iOS SDK. Default false
    • Returns the user logged in via delegate.

[OAuth] Add APIs for SSO integration

connect SkygearIO/features#5

  • -[SKYContainer loginWithOAuthProvider:(NSString*)providerID, options:(NSDictionary*)options completion:(void(^)(NSError*, SKYUser*))]
    • Create or login a new skygear user, associated with the provider
    • providerID - A string that identify the login provider
      • We will provide com.facebook, com.google
    • options
      • uxMode - Either popup(default), or redirect, popup means in-app-browser (SFSafariViewController/WKWebView) and redirect means Safari.app
      • clientID
      • scope
      • version - FB Client SDK only
      • cookiePolicy - Google Client SDK only
    • This function returns a skygear user, and an access token of the service, via a delegate.
  • -[SKYContainer loginWithOAuthProvider:(NSString*)providerID, accessToken:(NSString*)accessToken completion:(void(^)(NSError*, SKYUser*))]
    • accessToken - Client calls this API if it already has an access token, skygear will try to login directly instead of going through the OAuth flow.
  • -[SKYContainer associateAccountWithProvider:(NSString*)providerID options:(NSDictionary*)options completion:(void(^)(NSError*, SKYUser*))]
    • Add a new auth provider to the user by going through the auth flow
    • providerID - A string that identify the login provider
    • options
      • uxMode - Either popup(default), or redirect, popup means in-app-browser (SFSafariViewController/WKWebView) and redirect means Safari.app
      • clientID
      • scope
      • version - FB Client SDK only
      • cookiePolicy - Google Client SDK only
    • This function returns a skygear user, and an access token of the new service, via delegate.
  • -[SKYContainer getOAuthTokensWithCompletion:(void(^)(NSError*, NSDictionary*))]
    • Return tokens

      [container getOAuthTokensWithCompletion:^(NSDictionary *tokens){
        //tokens['com.facebook'] is FB's access token
      }];
      

SKYLambdaOperation should accept null result

In the following lambda,

def handle_delete_conversation_lambda(conversation_id):
    __validate_user_is_admin(conversation_id)
     conversation = Conversation.fetch_one(conversation_id)
     handle_admins_lambda(conversation_id, conversation['admin_ids'], False)
     handle_remove_participants(conversation_id,
     conversation['participant_ids'])

the response is

{"result": null}

However, SKYLambdaOperation throws an error.

The expected result should be returning nil.

Make SKYNotification.subscriptionID public

Re-open it from oursky/skygear-SDK-iOS#260

-[SKYNotification subscriptionID] is put inside a private header, it would be useful if we can get the subscription id from a notification.

We actually need it here: oursky/ufo#848

New user profile design: Update skygear.auth api

feature: SkygearIO/features#48
server issue: SkygearIO/skygear-server#393

  • add signup(authData, password, [profile])
  • add login(authData, password)
  • update current signWithXXX and loginWithXXX to call new server api
  • return User record in signup, login and whoami response
  • remove APIs that are calling server user:xxx
    • remove saveUser
    • remove getUserByXXX
  • remove User object (the original user object returned in signup/login api), the followings are needed to replace the api provided by the original User object
    • add add/get/deleteRoles api to skygear.auth, work with user id and role object
    • make ACL and Relation object consumes User record instead of User object

Make class doc comment consistent

It appears there are two style of comments:

 /**
  Comment here.
  */
 /**
  * Comment here.
  */

Personally, I prefer the second style despite the fact that many of my comments in the file are made with the former style.

API/api doc change for register/unregister device

A developer is confused which API to call for registering/unregistering device:

  • registerRemoteNotificationDeviceToken:completionHandler:
    • should add a method registerDeviceWithDeviceToken:completionHandler: to be consistent with other APIs
    • mention that this method is for registering remote notification (i.e. push notification)
    • mention that app should call unregisterDeviceCompletionHandler: to unregister device
  • registerDeviceCompletionHandler:
    • mention that this method is for registering the device if user denied push notification permission / to register device for pubsub
    • mention that app should call unregisterDeviceCompletionHandler: to unregister device
  • unregisterDevice
    • should be deprecated, call unregisterDeviceCompletionHandler: with nil parameter
  • unregisterDeviceCompletionHandler:
    • mention that this method should be called to unregister device

Update SDK API Grouping

SkygearIO/features#71

  • Update Container api with the following grouping
  • Update Test
  • Update Example

Grouping:

Container:

  state:
    url
    apiKey
    timeoutOptions
    auth(AuthContainer)
    relation(RelationContainer)
    db(DatabaseContainer)
    pubsub(PubsubContainer)
    push(PushContainer)
    chat(ChatContainer)
    analytics(AnalyticsContainer)

  api:
    config
    configApiKey
    lambda
    sendRequestObject
    makeRequest


AuthContainer:

  state:
    accessToken
    user(User)

  api:
    signupWithUsername
    signupWithEmail
    signupWithUsernameAndProfile
    signupWithEmailAndProfile
    signupAnonymously
    loginWithUsername
    loginWithEmail
    loginWithProvider
    logout
    changePassword
    forgotPassword
    // following api would be affected by https://github.com/SkygearIO/features/pull/68
    saveUser
    whoami
    getUsersByEmail
    getUsersByUsername
    discoverUserByEmails
    discoverUserByUsernames


RelationContainer:

  api:
    queryFriend
    queryFollower
    queryFollowing
    addRelation
    removeRelation


DatabaseContainer:

  state:
    public(PublicDatabase)
    private(PrivateDatabase)
    cacheResponse(Boolean)

  api:
    makeUploadAssetRequest


PublicDatabase:

  state:
    cacheStore

  api:
    setAdminRole
    setDefaultRole
    getDefaultACL
    setDefaultACL
    setRecordCreateAccess
    setRecordDefaultAccess
    getRecordByID
    save
    query
    del
    clearCache
    fetchSubscriptionWithID
    saveSubscription
    deleteSubscriptionWithID


PrivateDatabase:

  state:
    cacheStore

  api:
    getRecordByID
    save
    query
    del
    clearCache
    fetchSubscriptionWithID
    saveSubscription
    deleteSubscriptionWithID


PubsubContainer:

  state:
    channel
    internalChannel
    autoPubsub(Boolean)

  api:
    on
    off

PushContainer:

  state:
    deviceToken
    deviceID

  api:
    registerDevice
    unregisterDevice
    sendPushNotification

ChatContainer:


AnalyticsContainer:

Example:

// Call API
#import <SKYKit/SKYKit.h>

SKYContainer *container = [SKYContainer defaultContainer];
[container.auth loginWithEmail:@"[email protected]" password:@"secret" completion:nil];
[container.auth forgotPasswordWithEmail:@"[email protected]" completion:nil];
[container.pubsub subscribeTo:"channel" handler:nil];

SKYRecord *sampleItem = [SKYRecord recordWithRecordType:@"SampleItem"];
[container.db.public saveRecord:sampleItem completion:nil];
// Retrieve contexts
#import <SKYKit/SKYKit.h>

SKYContainer *container = [SKYContainer defaultContainer];
NSString *apiKey = [container apiKey];
NSString *currentAccessToken = [container.auth currentAccessToken];
NSDictionary *publicDBCache = [container.db.public cache];

Deserializing record to custom subclass

From the chat SDK, there is some code to copy a SKYRecord and create a custom subclass (such as SKYMessage. I suggest that we make ``SKYRecordDeserializer deserializer]` to return a singleton object and SDK user can register subclass to be used for deserialization when the deserializer encounter certain types:

id der = [SKYRecordDeserializer deserializer];
[der registerRecordClass:[SKYMessage class] forType:@"message"];

id record = [der recordWithDictionary:recordDict];
[record isKindOfClass:[SKYMessage class]]; // true

`configAddress` should support https

Current implementation always prefix with http. Since the input is NSString, I expect the program will detect if I supply protocol prefix and don't append http as protocol if I already provided https://

Support App Groups

Currently the sdk saves accessToken and currentRecordID in [NSUserDefaults standardUserDefaults], which not accessible across apps in app group, in case I want to add extension to existing app.

Record deserialization when encountering un-deserializables

follows #64

The iOS SDK expects the server to send valid response. In case the server sends a response that the iOS SDK does not expect, SKYDataSerialization returns nil (which IMHO is the expected behavior). This caused nil being added to NSDictionary, which is illegal.

The SKYRecordDeserializer should, on encountering a nil value, do one of the following (your pick):

  • set [NSNull null]
  • not set the key
  • set SKYUnknownValue maybe not this one

and also emits a log stating that the value of the key failed to deserialize.

Confusing error message when asset being uploaded is nil

Swift code:

let asset = SKYAsset(name: "profile-picture", data: UIImagePNGRepresentation(UIImage()))
asset.mimeType = "image/png"

Error message:

Error Domain=SKYOperationErrorDomain Code=9 "The data sent by the server cannot be processed." UserInfo={SKYErrorName=InvalidData, NSLocalizedDescription=The data sent by the server cannot be processed., SKYErrorMessage=Uploaded asset does not have a name associated with it.}

Remember and apply default ACL settings to records

When calling -[SKYContainer defineDefaultAccessWithRecordType] the SDK should remember the settings and apply default ACL settings to record when needed (see below). The default ACL settings does not need to persist across application relaunch because it is expected that the developer will always call this method when the app launches.

The default ACL should not be applied to a record when it is instantiated. The default ACL should only apply when the the developer tries to mutate the record ACL.

Since -[SKYRecord accessControl] is readonly and nil when record is instantiated, it is not reasonable to expect the developer to change the record ACL using methods provided in SKYAccessControl. To make the iOS SDK to match the design of the JS/Android SDK, we should add -[SKYRecord set[Public](No|ReadOnly|Write)Access[For(User|Role)]] that implement record ACL mutation.

When default ACL for the record type is not defined, the fallback ACL will apply. The fallback ACL is public-readable.

If record ACL is null, getting the record ACL will not cause the record ACL to change. Return the default ACL or fallback ACL in this case.

Implement -[SKYRecord get[Public](No|ReadOnly|Write)Access[For(User|Role)]] for getting record ACL.

In earlier versions of the SDK, +[SKYAccessControl (set|get)DefaultAccessControl] sets and gets the default ACL that applies to all record types. These methods should be retained but deprecated. These methods should alter the fallback ACL. In other words, calling these methods will override the fallback ACL of public-readable.

Issue on "performCachedQuery"

I have some issues when I tried to do “performCachedQuery” on the table News.

It seems to be fine for the first time but it crashed the app afterwards.
Below is the log of the issue:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* setObjectForKey: object cannot be nil (key: photo)'

Seems that there are some troubles in SKYRecordDeserializer. May you take a look on this issue?
And the code snippet is attached as follow. Thanks a lot!

screen shot 2016-07-20 at 5 25 22 pm

Fix unable to upload asset

The following error could happen when uploading asset:

SkygearTest[10488:377789] error uploading asset: Error Domain=SKYOperationErrorDomain Code=108 “The server is unable to process the data.” UserInfo={arguments=(
    “content-size”
), NSErrorFailingURLKey=http://localhost:3000/asset/put, SKYErrorMessage=Missing content size or content size is invalid, SKYErrorName=InvalidArgument, SKYOperationErrorHTTPStatusCodeKey=400, NSLocalizedDescription=The server is unable to process the data.}

Crash when use SKYRecordStorage to save a record that contains SKYSequence

error message:

-[SKYSequence encodeWithCoder:]: unrecognized selector sent to instance 0x7fc9236d42e0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SKYSequence encodeWithCoder:]: unrecognized selector sent to instance 0x7fc9236d42e0'

code:

let todo = SKYRecord(recordType: "todo")
todo.setObject(title!, forKey: "title")
todo.setObject(SKYSequence(), forKey: "order")
todo.setObject(false, forKey: "done")

self.recordStorage.saveRecord(todo)

SKYDatabase saveSubscription failed

error message :
Failed to subscribe for my todo: Error Domain=SKYOperationErrorDomain Code=108 "The server is unable to process the data." UserInfo={arguments=<CFArray 0x125dae0f0 [0x19fcfa150]>{type = immutable, count = 1, values = (    0 : device_id )}, NSErrorFailingURLKey=https://todolist.skygeario.com/subscription/save, SKYErrorMessage=empty device_id, SKYErrorName=InvalidArgument, SKYOperationErrorHTTPStatusCodeKey=400, NSLocalizedDescription=The server is unable to process the data.}

 func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        print("Registered for Push notifications with token: \(deviceToken)");
        SKYContainer.defaultContainer().registerRemoteNotificationDeviceToken(deviceToken) { (deviceID, error) in
            if error != nil {
                print("Failed to register device token: \(error)")
                return
            }

            print("deviceID : \(deviceID)")  // has deviceID
            let query = SKYQuery(recordType: "todo", predicate: nil)
            let sortDescriptor = NSSortDescriptor(key: "order", ascending: false)
            query.sortDescriptors = [sortDescriptor]
            let subscription = SKYSubscription(query: query, subscriptionID: "my todos")
            SKYContainer.defaultContainer().privateCloudDatabase.saveSubscription(subscription,completionHandler: { (subscription, error) in
                if error != nil {
                    print("Failed to subscribe for my todo: \(error)")  // error occur
                    return
                }

                print("Subscription successful.")
            })
        }
    }

`-[SKYContainer registerRemoteNotificationDeviceToken:existingDeviceID:completionHandler:]`'s retry makes no differences

In the SKYContainer's register device method [1], if we try to register an existing device and the server couldn't find the supplied device ID, SKYContainer would re-register the device without supplying the device ID, in an attempt to register a new device.

However, subscription-related operations maintain a default itself, and would supply the device ID if it is not provided in the operation [2]. So SKYContainer's attempt to re-register a new device would fail in vain.

  1. https://github.com/SkygearIO/skygear-SDK-iOS/blob/master/Pod/Classes/SKYContainer.m#L509
  2. https://github.com/SkygearIO/skygear-SDK-iOS/blob/master/Pod/Classes/Operations/SKYRegisterDeviceOperation.m#L84-L89

SKYSequence should implements NSValue

SKYSequence is an object used by SDK users to denote a value that is finalized when saving at the server side. It should behaves like a NSValue returning an Integer. Currently it subclasses NSObject.

This causes problem in SKYRecordStorage because the record storage would try to sort an attribute consists of both NSValue and SKYSequence. Having SKYSequence implements NSValue will solve this problem.

This issue is reported by @a821246710.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.