{"id":19614816,"url":"https://github.com/leancloud/paas.product","last_synced_at":"2026-05-10T20:54:58.072Z","repository":{"id":7729398,"uuid":"9095658","full_name":"leancloud/paas.product","owner":"leancloud","description":"Paas product release repo.","archived":false,"fork":false,"pushed_at":"2013-06-24T12:35:03.000Z","size":43521,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-01-09T10:33:03.306Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leancloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-03-29T09:19:24.000Z","updated_at":"2014-11-26T16:53:00.000Z","dependencies_parsed_at":"2022-09-10T05:22:37.381Z","dependency_job_id":null,"html_url":"https://github.com/leancloud/paas.product","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2Fpaas.product","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2Fpaas.product/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2Fpaas.product/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancloud%2Fpaas.product/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leancloud","download_url":"https://codeload.github.com/leancloud/paas.product/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240906847,"owners_count":19876683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T10:53:53.836Z","updated_at":"2026-05-10T20:54:53.025Z","avatar_url":"https://github.com/leancloud.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 欢迎使用AVOS Cloud\n\n本教程将会向您展示如何使用AVOS Cloud SDK开发一个简单的图片应用。 借助AVOS Cloud，您将不需要编写任何服务器端代码、也不需要维护任何服务器。一切将由AVOS Cloud帮您处理。\n\n# 申请AVOS Cloud帐号\n\n如果您还未拥有AVOS Cloud的帐号，请访问cn.avoscloud.com （中国区）或者us.avoscloud.com（美国区）申请开发人员帐号。\n\n请注意，目前中国区和美国区的数据并不能互通。 \n\n\n![apply account](images/apply-account.png)\n\n\n# 创建基于AVOS Cloud的移动App\n\n![create app](images/create-app.png)\n\n\n# 查看app keys\n\n![app keys](images/app-keys.png)\n\napp keys将会在您的代码中使用到，同时请注意保管好您的app keys，以免给您的应用带来损失。\n\n# 下载SDK\n\n```\ngit clone git@github.com:avos/paas.product.git\n```\n\n# 创建iOS工程\n\n![create app](images/create-app.png)\n\n# 将AVOS Cloud SDK加入到工程中\n\n### 使用Finder打开sdk所在的位置，如下图所示\n\n![add sdk](images/add-avoscloud-sdk.png)\n\n\n### 将SDK加入到project中，如下图所示\n\n![avos cloud framework](images/avoscloud-framework.png)\n\n# 初始化AVOS Cloud SDK\n\n## 引用头文件\n\n```\n#import \"AppDelegate.h\"\n#import \u003cAVOSCloud/AVOSCloud.h\u003e\n```\n\n## 初始化Keys\n\n```\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n    // Init AVOS Cloud with app id and app key.\n    [AVOSCloud setApplicationId:appID\n                   clientKey:appKey];\n    [AVOSCloud useAVCloudUS];\n    \n    // Override point for customization after application launch.\n    return YES;\n}\n\n```\n\n\n![init avos cloud](images/init-avos-cloud.png)\n\n\n# 增加LoginViewController\n\n```\n-(IBAction)logInPressed:(id)sender\n{\n    [AVUser logInWithUsernameInBackground:self.userTextField.text password:self.passwordTextField.text block:^(AVUser *user, NSError *error) {\n        if (user) {\n            //Open the wall\n             [self performSegueWithIdentifier:@\"LoginSuccesful\" sender:self];\n        } else {\n            //Something bad has ocurred\n            NSString *errorString = [[error userInfo] objectForKey:@\"error\"];\n            UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:@\"Error\" message:errorString delegate:nil cancelButtonTitle:@\"Ok\" otherButtonTitles:nil, nil];\n            [errorAlertView show];\n        }\n    }];\n}\n```\n\n# 增加RegisterViewController\n\n```\n\n////Sign Up Button pressed\n-(IBAction)signUpUserPressed:(id)sender\n{\n    AVUser *user = [AVUser user];\n    user.username = self.userRegisterTextField.text;\n    user.password = self.passwordRegisterTextField.text;\n    \n    [user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {\n        if (!error) {\n            //The registration was succesful, go to the wall\n            [self performSegueWithIdentifier:@\"SignupSuccesful\" sender:self];\n            \n        } else {\n            //Something bad has ocurred\n            NSString *errorString = [[error userInfo] objectForKey:@\"error\"];\n            UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:@\"Error\" message:errorString delegate:nil cancelButtonTitle:@\"Ok\" otherButtonTitles:nil, nil];\n            [errorAlertView show];\n        }\n    }];\n}\n```\n\n# 创建UploadImageViewController\n\n```\n\n-(IBAction)sendPressed:(id)sender\n{\n    [self.commentTextField resignFirstResponder];\n    \n    //Disable the send button until we are ready\n    self.navigationItem.rightBarButtonItem.enabled = NO;\n    \n    //Place the loading spinner\n    UIActivityIndicatorView *loadingSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];\n    \n    [loadingSpinner setCenter:CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0)];\n    [loadingSpinner startAnimating];\n    [self.view addSubview:loadingSpinner];\n    \n    //Upload a new picture\n    NSData *pictureData = UIImagePNGRepresentation(self.imgToUpload.image);\n    \n    AVFile *file = [AVFile fileWithName:@\"img\" data:pictureData];\n    [file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {\n        \n        if (succeeded){\n            \n            //Add the image to the object, and add the comments, the user, and the geolocation (fake)\n            AVObject *imageObject = [AVObject objectWithClassName:WALL_OBJECT];\n            [imageObject setObject:file forKey:KEY_IMAGE];\n            [imageObject setObject:[PFUser currentUser].username forKey:KEY_USER];\n            [imageObject setObject:self.commentTextField.text forKey:KEY_COMMENT];\n            \n            AVGeoPoint *point = [AVGeoPoint geoPointWithLatitude:52 longitude:-4];\n            [imageObject setObject:point forKey:KEY_GEOLOC];\n            \n            [imageObject saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {\n                \n                if (succeeded){\n                    //Go back to the wall\n                    [self.navigationController popViewControllerAnimated:YES];\n                }\n                else{\n                    NSString *errorString = [[error userInfo] objectForKey:@\"error\"];\n                    [self showErrorView:errorString];\n                }\n            }];\n        }\n        else{\n            NSString *errorString = [[error userInfo] objectForKey:@\"error\"];\n            [self showErrorView:errorString];\n        }\n        \n        [loadingSpinner stopAnimating];\n        [loadingSpinner removeFromSuperview];       \n        \n    } progressBlock:^(int percentDone) {\n        \n    }];\n}\n```\n\n# 创建ImagesViewController\n\n## 获取所有的图片列表\n\n```\n//Get the list of images\n-(void)getWallImages\n{\n    //Prepare the query to get all the images in descending order\n    AVQuery *query = [AVQuery queryWithClassName:WALL_OBJECT];\n    [query orderByDescending:KEY_CREATION_DATE];\n    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {\n        \n        if (!error) {\n            //Everything was correct, put the new objects and load the wall\n            self.wallObjectsArray = nil;\n            self.wallObjectsArray = [[NSArray alloc] initWithArray:objects];\n            \n            [self loadWallViews];\n            \n        } else {\n            //Remove the activity indicator\n            [self.activityIndicator stopAnimating];\n            [self.activityIndicator removeFromSuperview];\n            \n            //Show the error\n            NSString *errorString = [[error userInfo] objectForKey:@\"error\"];\n            [self showErrorView:errorString];\n        }\n    }];\n\n}\n```\n\n## 加载图片\n\n```\n-(void)loadWallViews\n{\n    //Clean the scroll view\n    for (id viewToRemove in [self.wallScroll subviews]){\n        \n        if ([viewToRemove isMemberOfClass:[UIView class]])\n            [viewToRemove removeFromSuperview];\n    }\n    \n    \n    //For every wall element, put a view in the scroll\n    int originY = 10;\n    \n    for (AVObject *wallObject in self.wallObjectsArray){\n        \n        \n        //Build the view with the image and the comments\n        UIView *wallImageView = [[UIView alloc] initWithFrame:CGRectMake(10, originY, self.view.frame.size.width - 20 , 300)];\n        \n        //Add the image\n        AVFile *image = (PFFile *)[wallObject objectForKey:KEY_IMAGE];\n        UIImageView *userImage = [[UIImageView alloc] initWithImage:[UIImage imageWithData:image.getData]];\n        userImage.frame = CGRectMake(0, 0, wallImageView.frame.size.width, 200);\n        [wallImageView addSubview:userImage];\n        \n        //Add the info label (User and creation date)\n        NSDate *creationDate = wallObject.createdAt;\n        NSDateFormatter *df = [[NSDateFormatter alloc] init];\n        [df setDateFormat:@\"HH:mm dd/MM yyyy\"];\n        \n        UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 210, wallImageView.frame.size.width,15)];\n        infoLabel.text = [NSString stringWithFormat:@\"Uploaded by: %@, %@\", [wallObject objectForKey:KEY_USER], [df stringFromDate:creationDate]];\n        infoLabel.font = [UIFont fontWithName:@\"Arial-ItalicMT\" size:9];\n        infoLabel.textColor = [UIColor whiteColor];\n        infoLabel.backgroundColor = [UIColor clearColor];\n        [wallImageView addSubview:infoLabel];\n        \n        //Add the comment\n        UILabel *commentLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 240, wallImageView.frame.size.width, 15)];\n        commentLabel.text = [wallObject objectForKey:KEY_COMMENT];\n        commentLabel.font = [UIFont fontWithName:@\"ArialMT\" size:13];\n        commentLabel.textColor = [UIColor whiteColor];\n        commentLabel.backgroundColor = [UIColor clearColor];\n        [wallImageView addSubview:commentLabel];\n        \n        [self.wallScroll addSubview:wallImageView];\n        \n        \n        originY = originY + wallImageView.frame.size.width + 20;\n        \n    }\n    \n    //Set the bounds of the scroll\n    self.wallScroll.contentSize = CGSizeMake(self.wallScroll.frame.size.width, originY);\n    \n    //Remove the activity indicator\n    [self.activityIndicator stopAnimating];\n    [self.activityIndicator removeFromSuperview];\n}\n```\n\n# 手工添加bundle\n\n为了可以在设备上正常运行app，您需要手工copy bundle\n\n![copy resource bundle](images/avoscloudui-bundle.png)\n\n# 下载完整示例\n\n```\ngit clone git@github.com:avos/paas.product.git\ncd paas.product/iOS/samples\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancloud%2Fpaas.product","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleancloud%2Fpaas.product","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancloud%2Fpaas.product/lists"}