iOS Today Extension keeps crashing on iPhone, not in simulator - ios

I'm trying to build an iOS Today Extension that shows three images with some text. In the simulator it runs fine, but when I run it on my iPhone, it flashes three times and then displays Unable to Load. What am I doing wrong?
TodayViewController.m
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"
#interface TodayViewController () <NCWidgetProviding>
#property (strong, nonatomic) UILabel *descriptionLabel;
#property (strong, nonatomic) UIImageView *firstImage;
#property (strong, nonatomic) UIImageView *secondImage;
#property (strong, nonatomic) UIImageView *thirdImage;
#property (strong, nonatomic) UILabel *firstImageLabel;
#property (strong, nonatomic) UILabel *secondImageLabel;
#property (strong, nonatomic) UILabel *thirdImageLabel;
#property (strong, nonatomic) UILabel *firstImageOwnerLabel;
#property (strong, nonatomic) UILabel *secondImageOwnerLabel;
#property (strong, nonatomic) UILabel *thirdImageOwnerLabel;
#property (strong, nonatomic) NSDictionary *dataOne;
#property (strong, nonatomic) NSDictionary *dataTwo;
#property (strong, nonatomic) NSDictionary *dataThree;
#property (nonatomic) NSInteger quarterSize;
#property (nonatomic) NSInteger eightSize;
#end
#implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.preferredContentSize = CGSizeMake(self.view.frame.size.width, 320);
[self updateNumberLabelText];
if ([self.dataOne count] == 0) {
UILabel *noContent = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width/2)-150, 93, 300, 44)];
noContent.text = #"You haven't opened the app yet.";
[self.view addSubview:noContent];
} else {
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:#"iPhone"] || [deviceType isEqualToString:#"iPhone Simulator"])
{
self.quarterSize = self.view.frame.size.width/4;
self.eightSize = self.quarterSize/4;
} else if([deviceType isEqualToString:#"iPad"] || [deviceType isEqualToString:#"iPad Simulator"])
{
self.quarterSize = self.view.frame.size.width/5;
self.eightSize = self.quarterSize/4;
}
self.descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.eightSize, 15, self.view.frame.size.width-self.quarterSize, 20)];
self.descriptionLabel.text = #"Some new images just for you!";
self.descriptionLabel.textColor = [UIColor whiteColor];
[self.view addSubview:self.descriptionLabel];
UIView *firstView = [[UIView alloc] initWithFrame:CGRectMake(self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openFirstImage:)];
[firstView addGestureRecognizer:singleFingerTap];
if ([[self.dataOne objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageOne = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageOne.backgroundColor = [self paperColorLightBlue500];
[firstView addSubview:noImageOne];
} else {
self.firstImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.firstImage;
[self.firstImage sd_setImageWithURL: [NSURL URLWithString:[self.dataOne objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.firstImage.contentMode = UIViewContentModeScaleAspectFill;
[self.firstImage setClipsToBounds:YES];
[firstView addSubview:self.firstImage];
}
UIView *secondView = [[UIView alloc] initWithFrame:CGRectMake(firstView.frame.origin.x + firstView.frame.size.width + self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *secondFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openSecondImage:)];
[secondView addGestureRecognizer:secondFingerTap];
if ([[self.dataTwo objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageTwo = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageTwo.backgroundColor = [self paperColorLightBlue500];
[secondView addSubview:noImageTwo];
} else {
self.secondImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.secondImage;
[self.secondImage sd_setImageWithURL: [NSURL URLWithString:[self.dataTwo objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.secondImage.contentMode = UIViewContentModeScaleAspectFill;
[self.secondImage setClipsToBounds:YES];
[secondView addSubview:self.secondImage];
}
UIView *thirdView = [[UIView alloc] initWithFrame:CGRectMake(secondView.frame.origin.x + secondView.frame.size.width + self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *thirdFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openThirdImage:)];
[thirdView addGestureRecognizer:thirdFingerTap];
if ([[self.dataThree objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageThird = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageThird.backgroundColor = [self paperColorLightBlue500];
[thirdView addSubview:noImageThird];
} else {
self.thirdImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.thirdImage;
[self.thirdImage sd_setImageWithURL: [NSURL URLWithString:[self.dataThree objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.thirdImage.contentMode = UIViewContentModeScaleAspectFill;
[self.thirdImage setClipsToBounds:YES];
[thirdView addSubview:self.thirdImage];
}
self.firstImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImage.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.firstImageLabel.text = [self.dataOne objectForKey:#"title"];
self.firstImageLabel.numberOfLines = 2;
self.firstImageLabel.textColor = [UIColor whiteColor];
self.firstImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.firstImageLabel sizeToFit];
[firstView addSubview:self.firstImageLabel];
self.secondImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImage.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.secondImageLabel.text = [self.dataTwo objectForKey:#"title"];
self.secondImageLabel.numberOfLines = 2;
self.secondImageLabel.textColor = [UIColor whiteColor];
self.secondImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.secondImageLabel sizeToFit];
[secondView addSubview:self.secondImageLabel];
self.thirdImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImagele.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.thirdImageLabel.text = [self.dataThree objectForKey:#"title"];
self.thirdImageLabel.numberOfLines = 2;
self.thirdImageLabel.textColor = [UIColor whiteColor];
self.thirdImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.thirdImageLabel sizeToFit];
[thirdView addSubview:self.thirdImageLabel];
self.firstImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.firstImageOwnerLabel.text = [self.dataOne objectForKey:#"owner"];
self.firstImageOwnerLabel.numberOfLines = 1;
self.firstImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.firstImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[firstView addSubview:self.firstImageOwnerLabel];
[self.view addSubview:firstView];
self.secondImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.secondImageOwnerLabel.text = [self.dataTwo objectForKey:#"owner"];
self.secondImageOwnerLabel.numberOfLines = 1;
self.secondImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.secondImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[secondView addSubview:self.secondImageOwnerLabel];
[self.view addSubview:secondView];
self.thirdImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.thirdImageOwnerLabel.text = [self.dataThree objectForKey:#"owner"];
self.thirdImageOwnerLabel.numberOfLines = 1;
self.thirdImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.thirdImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[thirdView addSubview:self.thirdImageOwnerLabel];
[self.view addSubview:thirdView];
}
}
- (UIColor *)paperColorLightBlue500 { return UIColorFromRGB(0x03a9f4); }
- (void)openFirstImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the First Image");
}
- (void)openSecondImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the Second Image");
}
- (void)openThirdImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the Third Image");
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
return self;
}
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
return UIEdgeInsetsZero;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
self.firstImageLabel = nil;
self.secondImageLabel = nil;
self.thirdImageLabel = nil;
self.firstImageOwnerLabel = nil;
self.secondImageOwnerLabel = nil;
self.thirdImageOwnerLabel = nil;
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
- (void)userDefaultsDidChange:(NSNotification *)notification {
[self updateNumberLabelText];
}
- (void)updateNumberLabelText {
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.testapp.TodayExtensionDefaults"];
self.dataOne = [defaults objectForKey:#"dataOne"];
self.dataTwo = [defaults objectForKey:#"dataTwo"];
self.dataThree = [defaults objectForKey:#"dataThree"];
for (id key in self.dataOne) {
NSLog(#"key: %#, value: %# \n", key, [self.dataOne objectForKey:key]);
}
for (id key in self.dataThree) {
NSLog(#"key: %#, value: %# \n", key, [self.dataThree objectForKey:key]);
}
}
#end
The only error I get is that the Extension is Terminated due to Memory Error.

Extensions have much lower memory limits than normal apps. You'll have to investigate why you extension is using so much memory. Perhaps there's a leak.

Related

NSAttributedString with image attachment and NSTextTab, text not aligned

I'm trying to have a UIlabel with an image and title on the left and a list of descriptions with bullets on the right.
To do that I'm using NSAttributedString like this :
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops =
#[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:tabLocation options:[NSDictionary dictionary]] ];
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:#"test_image"];
textAttachment.bounds = CGRectMake(0, -3, 15, 15);//resize the image
attString = [NSAttributedString attributedStringWithAttachment:textAttachment].mutableCopy;
[attString appendAttributedString:[[NSAttributedString alloc]
initWithString:[NSString stringWithFormat:#"title\t\u2022 %#",
[#[ #"description1", #"description2" ]
componentsJoinedByString:#"\n\t\u2022 "]]
attributes:#{NSParagraphStyleAttributeName : pStyle}]];
label.attributedText = attString;
I expect the list on the right to be left aligned but that's not the case, here is the result I get:
What I expect is the list to be aligned like this:
The issue is with location parameter in NSTextTab
According to description, location parameter helps to position text from left margin. So this is what we needed, just replace below lines
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:tabLocation options:[NSDictionary dictionary]] ];
with
pStyle.tabStops = #[[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:[self getTextLocationFor:#"test"] options:[NSDictionary dictionary]] ];
Add getTextLocationFor: method to calculate location as follows
-(CGFloat)getTextLocationFor:(NSString *)inputStr{
CGSize maximuminputStringWidth = CGSizeMake(FLT_MAX, 30);
CGRect textRect = [inputStr boundingRectWithSize:maximuminputStringWidth
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont systemFontOfSize:15]}
context:nil];
UIImageView * testImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"close_red"]];//Change image name with yours
return textRect.size.width + testImage.frame.size.width +2;
}
That's it we are ready to go run your project now everything will be fine.
RESULT:
if I understand you correctly then try these code:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 460, 460)];
label.numberOfLines = 0;
[self.view addSubview:label];
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:40 options:#{}] ];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:#"img"];
textAttachment.bounds = CGRectMake(0, -3, 30, 30);
NSString *string = [NSString stringWithFormat:#"title\n\r\u2022 %#", [#[ #"description1", #"description2" ] componentsJoinedByString:#"\n\r\u2022 "]];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] mutableCopy];
[attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:string attributes:#{NSParagraphStyleAttributeName : pStyle}]];
label.attributedText = attributedString;
Here is result
UPDATE
You can only achieve this using TextKit (NSTextLayoutManager) and specify area which should be use to draw text, or use simple solution and subclass from UIView.
Here is solution with view
ListView.h
#interface ListView : UIView
#property(nonatomic,strong) UIImage *image;
#property(nonatomic,strong) NSString *title;
#property(nonatomic,strong) NSArray *list;
#end
ListView.m
static const CGFloat ImageWidth = 13.f;
#interface ListView()
#property (nonatomic,weak) UIImageView *imageView;
#property (nonatomic,weak) UILabel *titleLabel;
#property (nonatomic,weak) UILabel *listLabel;
#end
#implementation ListView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
[self setup];
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
[self setup];
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
- (void)setup {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:imageView];
self.imageView = imageView;
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
titleLabel.numberOfLines = 0;
[titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:titleLabel];
self.titleLabel = titleLabel;
UILabel *listLabel = [[UILabel alloc] init];
listLabel.translatesAutoresizingMaskIntoConstraints = NO;
listLabel.numberOfLines = 0;
[listLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[listLabel setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:listLabel];
self.listLabel = listLabel;
NSDictionary *views = NSDictionaryOfVariableBindings(imageView,titleLabel,listLabel);
NSDictionary *metrics = #{ #"ImageHeight" : #(ImageWidth) };
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[imageView(ImageHeight)]-0-[titleLabel]-0-[listLabel]-0-|" options:0 metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[imageView(ImageHeight)]" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[titleLabel]" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[listLabel]-0-|" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
}
- (void)setImage:(UIImage *)image {
_image = image;
self.imageView.image = image;
[self setNeedsLayout];
}
- (void)setTitle:(NSString *)title {
_title = title;
self.titleLabel.text = title;
[self setNeedsLayout];
}
- (void)setList:(NSArray *)list {
_list = list;
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:40 options:#{}] ];
NSString *string = [NSString stringWithFormat:#"\u2022 %#", [list componentsJoinedByString:#"\n\u2022 "]];
self.listLabel.attributedText = [[NSAttributedString alloc] initWithString:string attributes:#{NSParagraphStyleAttributeName : pStyle}];
[self setNeedsLayout];
}
#end

How to retrieve data properly using realm

I had a problem to retrieve data using realm. What i wanna do is caching the data so that i can use it when user first load the app or user does not have internet connection. Below is the logic what i wanna do.
request from fb api -> fb return 10 data -> display returned data and cache returned data -> if user doesn't have internet connection display cache data or if user have internet connection fetch new data.
below is my code :
FBVideo.h
#import <Realm/Realm.h>
#interface FBVideo : RLMObject
#property (nonatomic, strong) NSString *pageBefore;
#property (nonatomic, strong) NSString *pageAfter;
#property (nonatomic, strong) NSString *thumbnailsURI;
#property (nonatomic, strong) NSString *titleDescription;
#property NSString *id;
#end
FBVideo.m
#import "FBVideo.h"
#implementation FBVideo
+ (NSString *)primaryKey {
return #"id";
}
// Specify default values for properties
+ (NSDictionary *)defaultPropertyValues {
return #{#"pageBefore":#"", #"pageAfter":#"", #"thumbnailsURI":#"", #"titleDescription":#""};
}
+ (NSArray *)ignoredProperties {
return #[];
}
#end
PageVideosCVC.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import "FBVideo.h"
#interface PageVideosCVC : UICollectionViewController
#property (strong, nonatomic) NSMutableArray *videoArray;
#property (strong, nonatomic) NSString *pageID;
#property (strong, nonatomic) NSString *pageName;
#property (strong, nonatomic) MPMoviePlayerController *playerController;
#property (assign, nonatomic) CATransform3D initialTransformation;
#property (nonatomic, strong) NSMutableSet *shownIndexes;
//#property (strong, nonatomic) FBVideo *fbVideoRealm;
#end
PageVideosCVC.m
#import "PageVideosCVC.h"
#import "facebook.h"
#import "MBProgressHUD.h"
#import "Reachability.h"
#import <AFNetworking/AFNetworking.h>
#import <AVFoundation/AVFoundation.h>
#import <SDWebImage/UIImageView+WebCache.h>
#import <QuartzCore/QuartzCore.h>
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
#interface PageVideosCVC () <UICollectionViewDataSource,UICollectionViewDelegate> {
NSString *pageBefore;
NSString *pageAfter;
NSString *thumbnailsURI;
Reachability *internetReachable;
NSDictionary *videoInfoToSaveInRealm;
// RLMResults *videoResultsFrom
}
#end
#implementation PageVideosCVC
#synthesize videoArray;
static NSString * const reuseIdentifier = #"Cell";
- (void) viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
videoArray = [NSMutableArray array];
/* Make a card effect, rotate the angle of the collectionviewcell to -15
1) Start with an identity transform, which is a fancy math term for “do nothing.”
2) Call CATransform3DRotate to apply a rotation of -15 degrees (in radians), where the negative value indicates a clockwise rotation.
3) Apply the rotation around the axis 0.0, 0.0, 1.0; this represents the z-axis, where x=0, y=0, and z=1.
4) Applying just the rotation to the card isn’t enough, as this simply rotates the card about its center. To make it look like it’s tipped over on a corner, add a translation or shift where the negative values indicate a shift up and to the left.
*/
CGFloat rotationAngleDegrees = -15;
CGFloat rotationAngleRadians = rotationAngleDegrees * (M_PI/180);
CGPoint offsetPositioning = CGPointMake(-20, -20);
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, rotationAngleRadians, 0.0, 0.0, 1.0);
transform = CATransform3DTranslate(transform, offsetPositioning.x, offsetPositioning.y, 0.0);
_initialTransformation = transform;
_shownIndexes = [NSMutableSet set];
}
- (void)viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
navBar.barTintColor = UIColorFromRGB(0x266593);
// Altering the font style of the navigation bar title
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
shadow.shadowOffset = CGSizeMake(0, 1);
[[UINavigationBar appearance] setTranslucent:NO];
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], NSForegroundColorAttributeName,
shadow, NSShadowAttributeName,
[UIFont fontWithName:#"HelveticaNeue-CondensedBlack" size:21.0], NSFontAttributeName, nil]];
[self.view addSubview: navBar];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"Down Arrow.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(backButtonTapped:)];
// UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:#"Back"
// style:UIBarButtonItemStylePlain
// target:self
// action:#selector(backButtonTapped:)];
[cancelItem setTintColor:[UIColor whiteColor]];
// UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:#"Done"
// style:UIBarButtonItemStyleBordered
// target:self action:nil];
NSString *selectedPageName = [[NSString alloc] initWithFormat:#"%#", self.pageName];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:selectedPageName];
// navItem.rightBarButtonItem = doneItem;
navItem.leftBarButtonItem = cancelItem;
navBar.items = [NSArray arrayWithObjects: navItem,nil];
[UIBarButtonItem appearance].tintColor = [UIColor blueColor];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[self loadVideo:#"a" pagesID:self.pageID];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if ([pageBefore isEqual:pageBefore]) {
return videoArray.count;
}
return videoArray.count + 1;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [videoArray count] - 1) {
NSLog(#"page after : %#", pageAfter);
[self loadVideo:pageAfter pagesID:self.pageID];
}
if (![self.shownIndexes containsObject:indexPath]) {
[self.shownIndexes addObject:indexPath];
// Transform collectionviewcell layer
UIView *card = [(UICollectionViewCell*)cell contentView];
card.layer.transform = self.initialTransformation;
card.layer.opacity = 0.5;
[UIView animateWithDuration:0.5 animations:^{
card.layer.transform = CATransform3DIdentity;
card.layer.opacity = 1;
}];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
__weak typeof(self) weakSelf = self;
if (indexPath.row == [videoArray count]) {
NSLog(#"this is last cell, later make it UIActivityIndicatorView");
} else {
// RLMResults *objects;
//
// objects = [FBVideo allObjects];
// FBVideo *fbVideoRealm = objects[indexPath.row];
//
// UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
// NSURL *thumbnailImage = [NSURL URLWithString:fbVideoRealm.thumbnailsURI];
// [imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
//
// UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
// titleDescription.text = fbVideoRealm.titleDescription;
NSDictionary *videoData = weakSelf.videoArray[indexPath.row];
NSDictionary *videoThumbnails = [videoData valueForKey:#"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:#"data"][0];
thumbnailsURI = [thumbnailsData valueForKey:#"uri"];
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:thumbnailsURI];
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
titleDescription.text = videoData[#"description"];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *videoSource = videoArray[indexPath.row];
NSURL *videoURL = [NSURL URLWithString:[videoSource valueForKey:#"source"]];
self.playerController = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[[self.playerController view] setFrame:[self.view bounds]]; // Frame must match parent view
[self.view addSubview:[self.playerController view]];
self.playerController.movieSourceType = MPMovieSourceTypeStreaming;
self.playerController.controlStyle = MPMovieControlStyleFullscreen;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doneButtonClick:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.playerController play];
// Play the video using AVPlayer iOS9 above
// AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// playerLayer.frame = self.view.bounds;
// [self.view.layer addSublayer:playerLayer];
// [player play];
}
- (void)doneButtonClick:(NSNotification*)aNotification{
NSNumber *reason = [aNotification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonUserExited) {
// Your done button action here
// [self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"done button tapped");
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[self.playerController stop];
[self.playerController.view removeFromSuperview];
}
}
- (IBAction)backButtonTapped:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Helper Methods
- (void)loadVideo:(NSString*)currentPage pagesID:(NSString*)pagesID{
__weak typeof(self) weakSelf = self;
NSString *fbToken = [facebook currentFBAccessToken];
NSString *fbNextVideoURL = [NSString stringWithFormat:#"https://graph.facebook.com/v2.5/%#/videos?access_token=%#&pretty=0&fields=source,description,thumbnails.limit(1),length&limit=10&after=%#", pagesID, fbToken, currentPage];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:fbNextVideoURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *videoDict = [[NSDictionary alloc] initWithDictionary:responseObject];
if (responseObject != nil) {
[weakSelf.videoArray addObjectsFromArray:[videoDict valueForKeyPath:#"data"]];
pageBefore = [videoDict valueForKeyPath:#"paging.cursors.before"];
pageAfter = [videoDict valueForKeyPath:#"paging.cursors.after"];
// Caching pageBefore, pageAfter, thumbnailsURI, titleDescription data to REALM
for (videoInfoToSaveInRealm in weakSelf.videoArray) {
NSDictionary *videoThumbnails = [videoInfoToSaveInRealm valueForKey:#"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:#"data"][0];
[[RLMRealm defaultRealm] transactionWithBlock:^{
[FBVideo createOrUpdateInDefaultRealmWithValue:#{#"id": self.pageID, #"titleDescription": videoInfoToSaveInRealm[#"description"], #"thumbnailsURI": [thumbnailsData valueForKey:#"uri"], #"pageBefore": pageBefore, #"pageAfter": pageAfter}];
}];
[self retrieveDataFromRealm];
}
//NSLog(#"first product's image: %#", (FBVideo *)[FBVideo allObjects]);
// Update UICollectionView UI
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self.collectionView reloadData];
});
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (void)retrieveDataFromRealm {
RLMResults *objects;
objects = [FBVideo allObjects];
FBVideo *fbVideoRealm = [[FBVideo alloc] init];
for (fbVideoRealm in objects) {
// NSLog(#"realm object count : %d", (int)objects.count);
NSLog(#"realm description : %#", fbVideoRealm.titleDescription);
NSLog(#"realm thumbnails URi : %#", fbVideoRealm.thumbnailsURI);
NSLog(#"realm page before : %#", fbVideoRealm.pageBefore);
NSLog(#"realm page after : %#", fbVideoRealm.pageAfter);
};
}
#end
Thank you in advance.
You should store the Facebook API response directly in Realm (don't display it right away), and then you can follow the pattern demonstrated in Realm's "TableView" example to back your UITableView with an RLMResults, and update the table when its data changes.
Since you'll always be loading data from the Realm this way, you get offline mode "for free".

Aztec Code not scaaning

I am trying to scan Aztec code using the Apple native API. But I am not able to scan it. In the Apple guideline, I have read it, you can scan the Aztec code. But it is not working.
Please check the code which i am using.
#import <UIKit/UIKit.h>
#interface igViewController : UIViewController
#end
#import <AVFoundation/AVFoundation.h>
#import "igViewController.h"
#interface igViewController () <AVCaptureMetadataOutputObjectsDelegate>
{
AVCaptureSession *_session;
AVCaptureDevice *_device;
AVCaptureDeviceInput *_input;
AVCaptureMetadataOutput *_output;
AVCaptureVideoPreviewLayer *_prevLayer;
UIView *_highlightView;
UILabel *_label;
}
#end
#implementation igViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_highlightView = [[UIView alloc] init];
_highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
_highlightView.layer.borderColor = [UIColor greenColor].CGColor;
_highlightView.layer.borderWidth = 3;
[self.view addSubview:_highlightView];
_label = [[UILabel alloc] init];
_label.frame = CGRectMake(0, self.view.bounds.size.height - 40, self.view.bounds.size.width, 40);
_label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
_label.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.65];
_label.textColor = [UIColor whiteColor];
_label.textAlignment = NSTextAlignmentCenter;
_label.text = #"(none)";
[self.view addSubview:_label];
_session = [[AVCaptureSession alloc] init];
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
_input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
if (_input) {
[_session addInput:_input];
} else {
NSLog(#"Error: %#", error);
}
_output = [[AVCaptureMetadataOutput alloc] init];
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[_session addOutput:_output];
_output.metadataObjectTypes = [_output availableMetadataObjectTypes];
for (NSString* avail in _output.metadataObjectTypes) {
NSLog(#"Avail...%#", avail);
}
_prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_prevLayer.frame = self.view.bounds;
_prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:_prevLayer];
[_session startRunning];
[self.view bringSubviewToFront:_highlightView];
[self.view bringSubviewToFront:_label];
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSLog(#"Failed...");
CGRect highlightViewRect = CGRectZero;
AVMetadataMachineReadableCodeObject *barCodeObject;
NSString *detectionString = nil;
NSArray *barCodeTypes = #[AVMetadataObjectTypeAztecCode];
for (AVMetadataObject *metadata in metadataObjects) {
NSLog(#".....%#", metadata.type);
for (NSString *type in barCodeTypes) {
if ([metadata.type isEqualToString:type])
{
barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer transformedMetadataObjectForMetadataObjectAVMetadataMachineReadableCodeObject *)metadata];
highlightViewRect = barCodeObject.bounds;
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
break;
}
}
if (detectionString != nil)
{
_label.text = detectionString;
break;
}
else
_label.text = #"(none)";
}
//_label.text = #"(nonessss)";
_highlightView.frame = highlightViewRect;
}
#end
This is my first answer on SO and I'm a total beginner with Objective-C and iOS development, so be a little gentle with me, please.
I can't actually help you fix errors in your code, as it is still very hard for me as a beginner to see what's going on, but I wanted to tell you that just a few days ago I successfully followed this tutorial on how to do exactly what you need. I adjusted the tutorials code and added comments where I needed them, so it should be easy to follow in case you'd like to try. As it is seems it is frowned upon to only post a link here, so I'm posting my code.
This is a ViewController that directly opens a scan view and reacts if a barcode (aztec in my case) is found. It should be easy to adjust to your needs. In the tutorial they used AVMetadataObjectTypeQRCode, but to scan Aztec codes, simply replace by AVMetadataObjectTypeAztecCode. I have done that already in my code.
ScanVC.h (in your case igViewController)
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ScanVC : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
#property (retain, nonatomic) UILabel *scannerWindow;
#property (retain, nonatomic) UILabel *statusLabel;
#property (retain, nonatomic) UIButton *cancelButton;
#end
ScanVC.m
#import "ScanVC.h"
#interface ScanVC ()
#property (nonatomic) BOOL isReading;
#property (nonatomic, strong) AVCaptureSession *captureSession;
#property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;
#end
#implementation ScanVC
#synthesize cancelButton;
#synthesize statusLabel;
#synthesize scannerWindow;
- (void)viewDidLoad {
[super viewDidLoad];
_isReading = NO;
_captureSession = nil;
//place a close button
cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
[cancelButton addTarget:self action:#selector(closeScan) forControlEvents:UIControlEventTouchUpInside];
[cancelButton setTitle:#"Close" forState:UIControlStateNormal];
cancelButton.frame = CGRectMake(0, 410, 250, 40);
[self.view addSubview:cancelButton];
//place a status label
statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 340, 250, 40)];
statusLabel.text = #"Currently not scanning";
[self.view addSubview:statusLabel];
//place the scanner window (adjust the size)
scannerWindow = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 250, 250)];
scannerWindow.text = #"Camera Capture Window";
[self.view addSubview:scannerWindow];
//start the scan immediately when the view loads
[self startStopScan];
}
- (void)closeScan {
if(_isReading) {
[self stopReading];
}
_isReading = !_isReading;
//dismiss the view controller here?
}];
}
- (void)startStopScan {
if (!_isReading) {
if([self startReading]) {
[statusLabel setText:#"Scanning for Barcode"];
}
} else {
[self stopReading];
}
_isReading = !_isReading;
}
- (BOOL)startReading {
NSError *error;
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if(!input) {
NSLog(#"%#", [error localizedDescription]);
return NO;
}
_captureSession = [[AVCaptureSession alloc] init];
[_captureSession addInput:input];
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[_captureSession addOutput:captureMetadataOutput];
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeAztecCode]];
//show the preview to the user
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPreviewLayer setFrame:scannerWindow.layer.bounds];
[scannerWindow.layer addSublayer:_videoPreviewLayer];
[_captureSession startRunning];
return YES;
}
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
if (metadataObjects != nil && [metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeAztecCode]) {
[statusLabel performSelectorOnMainThread:#selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(stopReading) withObject:nil waitUntilDone:NO];
_isReading = NO;
//do things after a successful scan here
NSLog(#"scanner output %#", [metadataObj stringValue]);
}
}
}
- (void)stopReading {
[_captureSession stopRunning];
_captureSession = nil;
[_videoPreviewLayer removeFromSuperlayer];
}
#end

Play audio from Parse via UIButton

I've been working on an app that allows audio to be played from Parse (like a social network), but am having trouble getting the code to not have errors.
My .h file
#import <UIKit/UIKit.h>
#interface TalklineViewController : UIViewController
#property (nonatomic, strong) IBOutlet UIScrollView *wallScroll;
#end
My .m file
#interface TalklineViewController ()
#property (nonatomic, retain) NSArray *wallAudioArray;
#end
#implementation TalklineViewController
#synthesize wallAudioArray = _wallAudioArray;
#synthesize wallScroll = _wallScroll;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)getWallAudio
{
//Prepare the query to get all the images in descending order
//1
PFQuery *query = [PFQuery queryWithClassName:#"AudioObject"];
//2
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//3
if (!error) {
//Everything was correct, put the new objects and load the wall
self.wallAudioArray = nil;
self.wallAudioArray = [[NSArray alloc] initWithArray:objects];
[self loadWallViews];
} else {
//4
NSString *errorString = [[error userInfo] objectForKey:#"error"];
UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[errorAlertView show];
}
}];
}
-(void)loadWallViews
{
//Clean the scroll view
for (id viewToRemove in [self.wallScroll subviews]){
if ([viewToRemove isMemberOfClass:[UIView class]])
[viewToRemove removeFromSuperview];
}
//For every wall element, put a view in the scroll
int originY = 10;
for (PFObject *audioObject in self.wallAudioArray){
//1
//Build the view with the image and the comments
UIView *wallAudioView = [[UIView alloc] initWithFrame:CGRectMake(10, originY, self.view.frame.size.width - 20 , 300)];
//2
//Add the image
PFFile *audio = (PFFile *)[audioObject objectForKey:#"audio"];
UIButton *userAudio = [[UIButton alloc][[UIButton buttonWithType:UIButtonTypeSystem audioWithData:audio.getData]];
userAudio.frame = CGRectMake(0, 0, wallAudioView.frame.size.width, 200);
[wallAudioView addSubview:userAudio];
//3
//Add the info label (User and creation date)
NSDate *creationDate = audioObject.createdAt;
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm dd/MM yyyy"];
//4
UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 210, wallAudioView.frame.size.width,15)];
infoLabel.text = [NSString stringWithFormat:#"Uploaded by: %#, %#", [audioObject objectForKey:#"user"], [df stringFromDate:creationDate]];
infoLabel.font = [UIFont fontWithName:#"Arial-ItalicMT" size:9];
infoLabel.textColor = [UIColor whiteColor];
infoLabel.backgroundColor = [UIColor clearColor];
[wallAudioView addSubview:infoLabel];
//5
//Add the comment
UILabel *commentLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 240, wallAudioView.frame.size.width, 15)];
commentLabel.text = [audioObject objectForKey:#"comment"];
commentLabel.font = [UIFont fontWithName:#"ArialMT" size:13];
commentLabel.textColor = [UIColor whiteColor];
commentLabel.backgroundColor = [UIColor clearColor];
[wallAudioView addSubview:commentLabel];
//6
[self.wallScroll addSubview:wallAudioView];
originY = originY + wallAudioView.frame.size.width + 20;
}
//7
//Set the bounds of the scroll
self.wallScroll.contentSize = CGSizeMake(self.wallScroll.frame.size.width, originY);
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
The problem line is:
UIButton *userAudio = [[UIButton alloc][[UIButton buttonWithType:UIButtonTypeSystem audioWithData:audio.getData]];
Any help is greatly appreciated!
UIButton doesn't have an audioWithData method, so that's the biggest issue here; instead, add a target to the button to play the audio with a seperate method:
UIButton *userAudio = [UIButton buttonWithType:UIButtonTypeSystem];
[userAudio setFrame:CGRectMake(20, 20, 100, 44)];
[userAudio setTitle:#"Play Audio!" forState:UIControlStateNormal];
[userAudio addTarget:self action:#selector(playAudio) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:userAudio];
- (void)playAudio
{
// Your audio data and playing code here
// audio.getData
}

Custom UIButton(CheckBox) add responder to action iOS SDK

I have custom UIButton class:
CheckBox.h
#interface CheckBox : UIButton {
BOOL isChecked;
IBOutlet UIWebView *webview;
IBOutlet UIImageView *img;
NSMutableString *labelText;
NSInteger fontSize;
NSInteger heightWebView;
}
#property (nonatomic,retain) NSMutableString *labelText;
#property (nonatomic,retain) UIImageView *img;
#property (nonatomic,retain) UIWebView *webview;
#property (nonatomic,assign) BOOL isChecked;
-(IBAction) checkBoxClicked;
-(void)addText:(NSString *) text redLetter:(NSInteger)redLetter isBold:(NSInteger)
isBold;
-(BOOL)getStatus;
-(NSString*)getText;
-(void)setFontSize:(NSInteger)setFontSizeValue;
#end
CheckBox.m look on IBAction i need implement functionality there
#import "CheckBox.h"
#implementation CheckBox
#synthesize isChecked, webview, img, labelText, delegate;
- (id)initWithFrame:(CGRect)frame {
if (self == [super initWithFrame:frame]) {
// Initialization code
fontSize = 2;
self.isChecked = NO;
self.labelText = [[NSMutableString alloc] init];
self.contentHorizontalAlignment =
UIControlContentHorizontalAlignmentLeft;
img = [[UIImageView alloc] initWithFrame:CGRectZero];
img.image = [UIImage imageNamed:#"checkbox.png"];
[self addSubview:img];
webview = [[UIWebView alloc] initWithFrame:frame];
webview.backgroundColor = [UIColor clearColor];
[webview setOpaque:NO];
webview.userInteractionEnabled = NO;
[self addSubview:webview];
/* [self setImage:[UIImage imageNamed:
#"checkbox.png"]
forState:UIControlStateNormal];*/
[self addTarget:self action:
#selector(checkBoxClicked)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(IBAction) checkBoxClicked{
if(self.isChecked ==NO){
self.isChecked =YES;
img.image = [UIImage imageNamed:#"checkbox-checked.png"];
}else{
self.isChecked =NO;
img.image = [UIImage imageNamed:#"checkbox.png"];
}
}
-(BOOL)getStatus{
return self.isChecked;
}
-(NSString*)getText{
return [NSString stringWithFormat:#"%#",self.labelText];
}
-(void)setFontSize:(NSInteger)setFontSizeValue {
fontSize = setFontSizeValue;
if (fontSize >2) {
heightWebView = fontSize+2;
}
}
-(void)addText:(NSString *) text redLetter:(NSInteger)redLetter isBold:(NSInteger)isBold
{
[self.labelText setString:text];
if (redLetter != 0) {
NSString *first;
NSString *red;
NSString *second;
first = [text substringWithRange:NSMakeRange(0, redLetter-1)];
red = [text substringWithRange:NSMakeRange(redLetter-1, 1)];
second = [text substringWithRange:NSMakeRange(redLetter, [text length] - redLetter )];
if(isBold == 0) {
NSString *html = [NSString stringWithFormat:#"<font size=\"%d\"><p>%#<span style=\"color:red;\">%#</span>%#</p></font>",fontSize, first,red,second];
[webview loadHTMLString:html baseURL:nil];
}else{
NSString *html = [NSString stringWithFormat:#"<font size=\"%d\"><p>%#<span style=\"color:red;\">%#</span>%#</p></font>",fontSize, first,red,second];
[webview loadHTMLString:html baseURL:nil];
}
}else {
if(isBold == 0) {
NSString *html = [NSString stringWithFormat:#"<font size=\"%d\"><p>%#</p></font>",fontSize, text];
[webview loadHTMLString:html baseURL:nil];
}else{
NSString *html = [NSString stringWithFormat:#"<font size=\"%d\"><p>%#</p></font>",fontSize, text];
[webview loadHTMLString:html baseURL:nil];
}
}
}
- (void)layoutSubviews {
img.frame = CGRectMake(0, 5, 18 , 18);
webview.frame = CGRectMake(12, 0-heightWebView, self.bounds.size.width- 11 , 25+heightWebView);
}
- (void)dealloc {
[webview release];
[img release];
[super dealloc];
}
#end
I need to add functionality to this class, that when user click on button in class where i implement CheckBox class will call some void.
Let me explain better i want to implement here functionality like in UIAlertView where you click on button calls
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
I need something like
- (void)checkBox:(CheckBox *)checkBox didStatusChanged:(BOOL)checkBoxStatus
Sounds like you want to implement a delegate protocol. This would go at the top of checkbox.h above your #interface
#protocol CheckBoxDelegate
#optional
- (void)checkBox:(CheckBox *)checkBox didStatusChanged:(BOOL)checkBoxStatus;
#end
You'd then want to add this to your checkbox.h #interface
#property (monatomic, assign) NSObject <CheckBoxDelegate> delegate;
You could then implement the
checkBox:(CheckBox *)checkBox didStatusChanged:(BOOL)checkBoxStatus
function in your ViewController or whatever is creating the checkboxes, and for each checkbox do
[checkbox setDelegate:self];
Then inside -(IBAction) checkBoxClicked you can call
[delegate checkBox:self didStatusChanged:self.isChecked];
and this would call that method on the class spawning the checkboxes/delegate.
Hope this is extensive enough.
Tim

Resources