寫在前前面
弄了下個人站...防止內容再次被鎖定...所有東西都在這里面
welcome~
個人博客
寫在前面
由于一些原因需要離職,準備重回大上海
忽然發現手頭上也沒什么獨立App,那就隨便寫個放到AppStore上吧,湊個數吧。哈哈哈。
這個App是無聊找配色的時候看到的一套圖
正好春節在家沒什么特別的事,編碼用了半天左右吧,數據錄入倒是也用了半天,于是就變成了這樣。
上架的時候再做點效果圖配點文字 就搞定了。
不得不說 我是白天提交的,到晚上就Review了
立馬就通過了變 ready for sale了。。。
可能是App太過于簡單了。也太好過審了。。。
廣告版集成了google的Admob (需要搭梯子)不過測試發現模擬器能正常顯示真機加了設備id也不能顯示,經常空加載。。
最近申請了騰訊的廣告 廣點通 提交了新的版本。就是注冊審核需要過個一兩天,關聯個APP要個一兩天。不過效果還是有的。
2.6提交的 ,今天(2.7)正式過審,就有收益了,估計都是自己和apple測試的時候展示的。
大家可能也看到了,這是個很簡單的App,無非就是幾個列表展示下分類的顏色和收藏的顏色,擔心功能太單一,所以又添加了自定義色。下面我們來講 項目 Demo吧。
效果
分析
感覺都沒什么好分析的了 ,就是個tableview自定義cell就行了 這里我直接用xib設置約束了
每個色塊有3個btn btn的顏色都是從plist中讀取,所以手工錄入還是挺耗時間的。
自定義顏色方面 直接獲取Touches的值做下計算
代碼部分
這里就貼一個自定義顏色部分。通過block回調選擇顏色的RGB值
#import <UIKit/UIKit.h>
@interface WSColorImageView : UIImageView
@property (copy, nonatomic) void(^currentColorBlock)(UIColor *color,NSString *rgbStr);
@end
#import "WSColorImageView.h"
@interface WSColorImageView()
@property (nonatomic,copy)NSString *rgbStr;
@end
@implementation WSColorImageView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.width)];
if (self) {
self.image = [UIImage imageNamed:@"palette"];
self.userInteractionEnabled = YES;
self.layer.cornerRadius = frame.size.width/2;
self.layer.masksToBounds = YES;
}
return self;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pointL = [touch locationInView:self];
if (pow(pointL.x - self.bounds.size.width/2, 2)+pow(pointL.y-self.bounds.size.width/2, 2) <= pow(self.bounds.size.width/2, 2)) {
UIColor *color = [self colorAtPixel:pointL];
if (self.currentColorBlock) {
self.currentColorBlock(color,self.rgbStr);
}
}
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pointL = [touch locationInView:self];
if (pow(pointL.x - self.bounds.size.width/2, 2)+pow(pointL.y-self.bounds.size.width/2, 2) <= pow(self.bounds.size.width/2, 2)) {
UIColor *color = [self colorAtPixel:pointL];
if (self.currentColorBlock) {
self.currentColorBlock(color,self.rgbStr);
}
}
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pointL = [touch locationInView:self];
if (pow(pointL.x - self.bounds.size.width/2, 2)+pow(pointL.y-self.bounds.size.width/2, 2) <= pow(self.bounds.size.width/2, 2)) {
UIColor *color = [self colorAtPixel:pointL];
if (self.currentColorBlock) {
self.currentColorBlock(color,self.rgbStr);
}
}
}
//獲取圖片某一點的顏色
- (UIColor *)colorAtPixel:(CGPoint)point {
if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.image.size.width, self.image.size.height), point)) {
return nil;
}
NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = self.image.CGImage;
NSUInteger width = self.image.size.width;
NSUInteger height = self.image.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * 1;
NSUInteger bitsPerComponent = 8;
unsigned char pixelData[4] = { 0, 0, 0, 0 };
CGContextRef context = CGBitmapContextCreate(pixelData,
1,
1,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
CGContextRelease(context);
CGFloat red = (CGFloat)pixelData[0] / 255.0f;
CGFloat green = (CGFloat)pixelData[1] / 255.0f;
CGFloat blue = (CGFloat)pixelData[2] / 255.0f;
CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
NSLog(@"%f***%f***%f***%f",red,green,blue,alpha);
NSLog(@"%d,%d,%d",pixelData[0],pixelData[1],pixelData[2]);
self.rgbStr = [NSString stringWithFormat:@"%d,%d,%d",pixelData[0],pixelData[1],pixelData[2]];
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}
- (void)setImage:(UIImage *)image {
UIImage *temp = [self imageForResizeWithImage:image resize:CGSizeMake(self.frame.size.width, self.frame.size.width)];
[super setImage:temp];
}
- (UIImage *)imageForResizeWithImage:(UIImage *)picture resize:(CGSize)resize {
CGSize imageSize = resize; //CGSizeMake(25, 25)
UIGraphicsBeginImageContextWithOptions(imageSize, NO,0.0);
CGRect imageRect = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
[picture drawInRect:imageRect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
return image;
}
@end
補充
給免費版添加了內購去廣告功能。
使用的是本地數據庫,自定義tableview的footview。
未購買標識為0,廣告位的frame高設為44;
購買成功就將標識設為1,廣告位frame高設為0;
都是tableview直接reload。
這里再給出內購的代碼。
注意:設置成訂閱類商品(非消耗)一定要添加恢復購買的代碼 不然審核會被拒
#import <StoreKit/StoreKit.h>
@interface ColorFavTableViewController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
#pragma mark - 內購
- (IBAction)clickPhures:(id)sender {
// [[CoreDataOperations sharedInstance] buyNoAds];
// [self.tableView reloadData];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"花費6元購買去廣告" preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"確定購買" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSString *product = @"123";
_currentProId = product;
if([SKPaymentQueue canMakePayments]){
[self requestProductData:product];
}else{
NSLog(@"不允許程序內付費");
}
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"已購買直接去廣告" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
//請求商品
- (void)requestProductData:(NSString *)type{
NSLog(@"-------------請求對應的產品信息----------------");
NSArray *product = [[NSArray alloc] initWithObjects:type,nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
}
//收到產品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"--------------收到產品反饋消息---------------------");
NSArray *product = response.products;
if([product count] == 0){
NSLog(@"--------------沒有商品------------------");
return;
}
NSLog(@"productID:%@", response.invalidProductIdentifiers);
NSLog(@"產品付費數量:%lu",(unsigned long)[product count]);
SKProduct *p = nil;
for (SKProduct *pro in product) {
NSLog(@"%@", [pro description]);
NSLog(@"%@", [pro localizedTitle]);
NSLog(@"%@", [pro localizedDescription]);
NSLog(@"%@", [pro price]);
NSLog(@"%@", [pro productIdentifier]);
if([pro.productIdentifier isEqualToString:_currentProId]){
p = pro;
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
NSLog(@"發送購買請求");
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
//請求失敗
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
NSLog(@"------------------錯誤-----------------:%@", error);
}
- (void)requestDidFinish:(SKRequest *)request{
NSLog(@"------------反饋信息結束-----------------");
}
//沙盒測試環境驗證
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式環境驗證
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
/**
* 驗證購買,避免越獄軟件模擬蘋果請求達到非法購買問題
*
*/
-(void)verifyPurchaseWithPaymentTransaction{
//從沙盒中獲取交易憑證并且拼接成請求體數據
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//轉化為base64字符串
NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接請求數據
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//創建請求到蘋果官方進行購買驗證
NSURL *url=[NSURL URLWithString:AppStore];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyData;
requestM.HTTPMethod=@"POST";
//創建連接并發送同步請求
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
NSLog(@"驗證購買過程中發生錯誤,錯誤信息:%@",error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
NSLog(@"購買成功!");
[[CoreDataOperations sharedInstance] buyNoAds];
[self.tableView reloadData];
NSDictionary *dicReceipt= dic[@"receipt"];
NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
NSString *productIdentifier= dicInApp[@"product_id"];//讀取產品標識
//如果是消耗品則記錄購買數量,非消耗品則記錄是否購買過
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([productIdentifier isEqualToString:@"123"]) {
int purchasedCount=[defaults integerForKey:productIdentifier];//已購買數量
[[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
}else{
[defaults setBool:YES forKey:productIdentifier];
}
//在此處對購買記錄進行存儲,可以存儲到開發商的服務器端
}else{
NSLog(@"購買失敗,未通過驗證!");
}
}
//監聽購買結果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
for(SKPaymentTransaction *tran in transaction){
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased:{
NSLog(@"交易完成");
[self verifyPurchaseWithPaymentTransaction];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
[[CoreDataOperations sharedInstance] buyNoAds];
[self.tableView reloadData];
}
break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加進列表");
break;
case SKPaymentTransactionStateRestored:{
NSLog(@"已經購買過商品");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
[[CoreDataOperations sharedInstance] buyNoAds];
[self.tableView reloadData];
}
break;
case SKPaymentTransactionStateFailed:{
NSLog(@"交易失敗");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
default:
break;
}
}
}
//交易結束
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
NSLog(@"交易結束");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
- (void)dealloc{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
Demo地址
廣告版免費,收費版1元,有興趣的可以下來玩玩
當然,Github公開無廣告版的源碼,歡迎點贊加星