Siêu tổng hợp iOS code snippets – Objective C

5/5 - (2 votes)

Đặc tính thông minh của Xcode 10

Mới ra bản beta nhưng mình thấy xcode 10 cải thiện khá thông minh, lần trước mình có phản hồi việc không folding được block code thế là team phát triển của Apple đã cải thiện nó (nói thật đấy). Sau đây là vài tính năng mình cảm nhận được:

  • Cho phép folding block code như vòng lặp for hay kiểm tra rẽ nhánh if.
  • Source Control thông minh hơn, cho phép discard 1 đoạn nhỏ mà không cần Source Tree.

Chưa quen:

  • cái quản lý đối tượng để dùng trong Main Storyboard đã tách riêng ra, không còn nằm bên phải bên dưới nữa.

Bản này chỉ có Dark mode khi cài trên Mac Mojave trở đi

Lỗi build app với tài khoản trả phí Paid

Khi build nó phát sinh ra lỗi signing, để giải quyết thì chỉ cần sang máy build được và  vào acc setting -> export ra cái developerprofile. Xong rồi vào máy không build được import là ok

Tham khảo:

https://stackoverflow.com/questions/10404931/copying-keys-and-certificates-to-another-one-mac-for-iphone-development/10405020#

Lỗi whose view is not in the window hierarchy

Khi show 1 popup trong UINavigation thì hay gặp lỗi này

Cách giải quyết là lấy thằng Vc trên cùng trong stack và hiện popup dựa trên đối tượng đó.

Tạo hàm:

- (UIViewController*) topMostController {
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    return topController;
}

Khi show popup:

 UIViewController *topVC = [self topMostController];
 [topVC presentViewController:alertVC animated:YES completion:nil];

Cách tạo 1 label chuẩn và lưu ý khi tạo label

UILabel *subformatLbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, (view_cha_cua_label).bounds.size.width, 50)];
    subformatLbl.textColor = [self colorFromHexString:@"#dbdbdb"];
    subformatLbl.text = @"Text Luon Center";
    subformatLbl.textAlignment = NSTextAlignmentCenter;
    [subformatLbl setFont:[UIFont systemFontOfSize:12]];
    [view_cha_cua_label addSubview:subformatLbl];

Một UIView có 1 điểm center

Điểm center sẽ bằng
center.x = frame.origin.x + (width/2)
center.y = frame.origin.y + (height/2)

Chú ý:

frame theo hệ quy chiếu bên trong superview

bound theo hệ quy chiếu bên trong chính nó, tức là bao gồm (x,y) (w,h)

Đọc thêm: https://stackoverflow.com/a/11282765/11119281

Các vấn đề liên quan đến ký tự khi làm đa ngôn ngữ với ứng dụng iot

  • 1 ký tự alphabet có số lượng bao nhiêu thì nặng bấy nhiêu tức là ký tự a có 1 ký tự và nặng 1 byte
  • 1 ký tự hiragana, katakana, kanji tiếng Nhật, kanji tiếng Trung nặng 3 bytes. Ví dụ: 日本語 nặng 9 bytes
  • 1 ký tự có dấu trong tiếng Việt nặng 2 byte. Ví dụ: ô nặng 2 bytes

Đếm số ký tự và số lượng byte trong ký tự tại đây https://mothereff.in/byte-counter#

Gặp lỗi malloc: *** error for object Invalid pointer dequeued from free list set a breakpoint in malloc_error_break to debug

Lỗi này là do sử dụng bộ nhớ không đủ khi khởi tạo char hoặc uint8_t cách giải quyết là khởi tạo mảng ban đầu lớn lên và sau khi dùng phải free cái mảng ấy:

đây là đoạn code đúng:

uint8_t* finalUnsignedChar = (unsigned char*)malloc(SET_LIST_PATH_STR_MAX);
    memset(finalUnsignedChar, 0x00, SET_LIST_PATH_STR_MAX);
    memset(myResult, 0x00, 3);
    int mySum = 0;
    for(int i = 0; i < countCharacter;i++){
        NSString * newString = [path substringWithRange:NSMakeRange(i, 1)];
        [self newConvertStrToThreeByte:newString];
        if(i==0){
            finalUnsignedChar[0] = myResult[0];
            finalUnsignedChar[1] = myResult[1];
            finalUnsignedChar[2] = myResult[2];
        }else{
            finalUnsignedChar[mySum]   = myResult[0];
            finalUnsignedChar[mySum+1] = myResult[1];
            finalUnsignedChar[mySum+2] = myResult[2];
        }
        mySum += 3;
    }
    data.setListPathStrLen = mySum;
    memcpy(data.setListPathStr, finalUnsignedChar, data.setListPathStrLen);
    free(finalUnsignedChar);

Cách gọi 1 hàm trong ViewController khác trong NavigationVC

UIViewController * currentController = self.visibleViewController;
    if ([currentController isKindOfClass:[MenuViewController class]]) {
        [((MenuViewController *) currentController) didReceiveData];
    }

Tạo đối tượng mới và gọi hàm didReceiveData trong MenuVC

Lỗi Navigation Bar nằm đè lên TableView

Mình đã gặp lỗi này và giải quyết nhưu sau:

  • Mở storyboard đang dùng.
  • Chọn vào Navigation chính sau đó sang bên phải chọn Attributes Inspector
  • Trong phần Simulated Metrics thay đổi mục Top Bar từ “Inferred” thành “Opaque Navigation Bar”
  • Chọn vào View Controller chứa cái tableview đang bị đè, bỏ check Under Top Bars
    Ok Command+R

Tạo UIslider theo chiều dọc

 UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(2.9 * BU, (160 - 9) * BU, 6.4 * BU, 6.4 * BU)];
    [slider addTarget:self action:@selector(controlValueChanged:) forControlEvents:UIControlEventValueChanged];
    slider.minimumValue = 100.00;
    slider.maximumValue = 1000.00;
    CGAffineTransform trans = CGAffineTransformMakeRotation(M_PI_2);
    slider.transform = trans;
    [slider setMinimumTrackTintColor:[UIColor clearColor]];
    [slider setMaximumTrackTintColor:[UIColor clearColor]];
    slider.continuous = YES;
    [self.view addSubview:slider];

Xử lí sự kiện

-(void)controlValueChanged:(id)sender
{
    NSLog(@"controlValueChanged");
}

Tạo TableView trong ViewController

Trong VC thực hiện các delegate và gán data cho mảng.

#import "ViewController.h"

@interface ViewController () <UITableViewDelegate,UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tbView;
@property (strong,nonatomic) NSArray *content;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"My Tbl View";
    self.tbView.delegate = self;
    self.tbView.dataSource = self;
    self.content = @[ @"Monday", @"Tuesday", @"Wednesday",@"Thursday",@"Friday",@"Saturday",@"Sunday"];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _content.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cellIdentifier";
    
    UITableViewCell *cell = [self.tbView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        
    }
    cell.textLabel.text =  [_content objectAtIndex:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
    NSLog(@"title of cell %@", [_content objectAtIndex:indexPath.row]);
}

@end

Bên MainStoryboard:

  • thực hiện ánh xạ UITableView vào biến tbview
  • click chọn vào UITableView và tạo 1 prototype cell đồng thời gán cell ID cho nó.

Ẩn hiện TableView trong ios

Ẩn

[self.tbMenu setHidden:YES];

Hiện

[self.tbMenu setHidden:NO];

Đếm số ViewController trong Stack của NavigationVC

unsigned long count = [[self.navigationController viewControllers] count];
NSLog(@"controllers : %@", [self.navigationController viewControllers]);
NSLog(@"count : %ld", count);

2 câu lệnh trên lấy đc luôn cả VC hiện tại.

Chụp màn hình iPhone trong Obj-C

- (IBAction)captureAction:(id)sender {
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(self.view.bounds.size);
    }
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:@"snapshot.png" options:NSDataWritingWithoutOverwriting error:Nil];
    [data writeToFile:@"snapshot.png" atomically:YES];
    
    [screenShot setImage:image];
    [self.view addSubview:screenShot];
    
    UIImageWriteToSavedPhotosAlbum([UIImage imageWithData:data], nil, nil, nil);
}

Nhớ thêm Privacy trong Info.plist

      <key>NSPhotoLibraryUsageDescription</key>
    <string>Grant Access Album</string>
    <key>NSPhotoLibraryAddUsageDescription</key>
    <string>Grant Access Album</string>

Kinh nghiệm khi tạo nhiều Label

Khi tạo label mà cần update cho nó thì nên tạo riêng biệt, ko nên vì sự tiện lợi tạo hàng loạt thông qua hàm. Có thể gặp lỗi ko thể update đc label.

Hẹn giờ chạy 1 hàm Obj-c

  -(void)Chay{
  [NSTimer scheduledTimerWithTimeInterval:2.0
                                     target:self
                                   selector:@selector(hidePreviewScreenshot:)
                                   userInfo:nil
                                    repeats:NO];
}

-(void)hidePreviewScreenshot:(NSTimer *)timer {
    [screenShot removeFromSuperview];
}

Hiển thị ảnh với border và radius border

 screenShot = [[UIImageView alloc]initWithFrame:CGRectMake(3*HBU, 110*HBU, 100, 200)];
    [screenShot setContentMode:UIViewContentModeScaleAspectFit];
    [screenShot.layer setBorderColor: [[UIColor blackColor] CGColor]];
    [screenShot.layer setBorderWidth: 6.0];
    screenShot.layer.cornerRadius = 10;
    UIImage *image = [UIImage imageNamed:@"YourImageName"];
    [screenShot setImage:image];
    [self.view addSubview:screenShot];

Thêm gạch chân cho UIlabel

        lbl = [[UILabel alloc] initWithFrame:CGRectMake(pointX*WBU, pointY*HBU, widthLbl*WBU, 6*HBU)];
        lbl.text = str;
        NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:str];
        [text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
        lbl.attributedText = text;
        [self.view addSubview:lbl];

Tạo button bằng code objc

    calibrateBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [calibrateBtn addTarget:self action:@selector(calibrateAction:) forControlEvents:UIControlEventTouchUpInside];
    [calibrateBtn setTitle:@"Calibrate" forState:UIControlStateNormal];
    calibrateBtn.backgroundColor = [self colorFromHexString:@"#63aeed"];
    [calibrateBtn setTitleColor:[self colorFromHexString:@"#FF0000"] forState:UIControlStateNormal];
    calibrateBtn.titleLabel.font = [UIFont systemFontOfSize:30];
    calibrateBtn.frame = CGRectMake(4.5*WBU, 40*HBU, 80*WBU, 15*HBU);
    calibrateBtn.clipsToBounds = YES;
    calibrateBtn.layer.cornerRadius = 10;
    calibrateBtn.layer.borderColor = [self colorFromHexString:@"#63aeed"].CGColor;
    calibrateBtn.layer.borderWidth=2.0f;
    [self.view addSubview:calibrateBtn];
- (IBAction)calibrateAction:(id)sender
{
    NSLog(@"calibrateAction act");
}

Tạo ảnh bằng code obj

    bleIconImg  = [[UIImageView alloc] initWithFrame:CGRectMake(62*WBU, 142*HBU, 25*WBU, 8*HBU)];
    [bleIconImg setImage:[UIImage imageNamed:@"bluetooth_on"]];
    [bleIconImg setContentMode:UIViewContentModeScaleAspectFit];
    bleIconImg.center = CGPointMake(self.view.frame.size.width  / 2, (148*HBU));
    [[self view] addSubview:bleIconImg];

Hiển thị màu với mã Hex

- (UIColor *)colorFromHexString:(NSString *)hexString {
    unsigned rgbValue = 0;
    NSScanner *scanner = [NSScanner scannerWithString:hexString];
    [scanner setScanLocation:1]; // bypass '#' character
    [scanner scanHexInt:&rgbValue];
    return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}

cách dùng:

self.view.backgroundColor = [self colorFromHexString:@"#bdc3c7"];

show ra 1 ký tự char ở dạng hex (convert char to hex)

NSLog(@"hex la: |%02X|", buf[5]);

buf là 1 mảng ký tự ở định dạng char không âm: (unsigned char*)buf

ở đây tôi in phần tử thứ 5 trong mảng.

tham khảo thêm: https://stackoverflow.com/questions/6645013/objective-c-convert-char-to-nsstring-in-hex-format

Lấy chiều rộng và cao màn hình iPhone, iPad

CGFloat fullWidth;
CGFloat fullHeight;

- (void)viewDidLoad {
    [super viewDidLoad];
    CGFloat statusBarHeight = [self statusBarHeight];
    fullWidth = [UIScreen mainScreen].bounds.size.width;
    fullHeight = [UIScreen mainScreen].bounds.size.height;
}

Lấy chiều cao status bar của iPhone, iPad

-(float) statusBarHeight
{
    CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
    return MIN(statusBarSize.width, statusBarSize.height);
}

Thêm ảnh vào dự án ios

Click chuột phải vào nơi bạn muốn thêm -> chọn Add files to… là ok.

* Chú ý:

bluetooth_on@2x~iphone.png: định dạng này thì chỉ có iphone hiển thị

bluetooth_on@2x~ipad.png: định dạng này thì chỉ có ipad hiển thị

Cái 2x, 3x hay không có 2x, 3x như thế này bluetooth_off~ipad.png đằng sau là ipad nó sẽ tự nhận ra có retina hay không.

2x là 2 lần ảnh gốc.
3x là 3 lần ảnh gốc.

tham khảo

Underline 1 label

 // To underline text in UILable
        NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:str];
        [text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
        lbl.attributedText = text;

Cách dùng Notification để thông báo

Cách này để kích hoạt 1 hàm nào đó, hay thông báo cho ViewController khác biết task đã xong.

Phát đi:

[[NSNotificationCenter defaultCenter] postNotificationName:@"PostStudentObject" object:self.student];

Bên nhận:

Luôn nghe ngóng:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getNotification:) name:@"PostStudentObject" object:nil];

Tạo hàm sẽ chạy:

- (void) getNotification:(NSNotification *)notification {
student = [notification object];
NSLog(@"%@", student.name);
}

* Chú ý:

Nghe ngóng tại:

- (void)viewWillAppear:(BOOL)animated
{
        [super viewWillAppear:animated];
        [NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(doSomething:)
        name:@"notificationName"
        object: nil];
}

Không theo dõi nữa tai:

- (void)viewWillDisappear:(BOOL)animated
{
[NSNotificationCenter defaultCenter] removeObserver:self
name:@"notificationName"
object: nil];
}

Xoá bỏ các đường phân cách trong Tableview ios

Chỉ cần thêm

self.tableView.tableFooterView = [UIView new];

Vào hàm ViewDidLoad là ok.

Tham khảo:

https://stackoverflow.com/questions/1369831/eliminate-extra-separators-below-uitableview

Cách cài Cocoa Pod cho dự án

1. Đầu tiên cần cài cocoa pod cho hệ điều hành

sudo gem install cocoapods

2. Vào thư mục của proj

cd /project path

3. Khởi tạo file mới tên là Podfile

pod init

4. Vào thư mục project và mở ra, thay thế nội dung này vào file Podfile hoặc bất kỳ thư viện nào.

platform :ios, '10.3'
use_frameworks!

target 'LocationInfo' do
    pod 'SwiftyJSON'
    pod 'Alamofire', '~> 4.5'
    pod 'ReachabilitySwift'
    pod 'Google-Mobile-Ads-SDK'
end

5. Và cuối cùng thực hiện chạy file Podfile

pod install

Mỗi lần thêm 1 thư viện vào hay xoá thư viện Podfile đi thì cần chạy lại pod install

Note về Cocoa pod:

Nếu thêm mới 1 pods mới thì chạy pod install, lần sau nếu xoá 1 pods nào đó đi cũng chạy pod install
pod update chỉ dùng để nâng cấp các phiên bản của thư viện pod chứ không phải update file pod của dự án hiện tại.

tham khảo:
https://guides.cocoapods.org/using/pod-install-vs-update.html

Introduction
Many people starting with CocoaPods seem to think pod install is only used the first time you setup a project using CocoaPods and pod update is used afterwards. But that’s not the case at all.

The aim of this guide is to explain when you should use pod install and when you should use pod update.

TL;DR:

Use pod install to install new pods in your project. Even if you already have a Podfile and ran pod install before; so even if you are just adding/removing pods to a project already using CocoaPods.
Use pod update [PODNAME] only when you want to update pods to a newer version.

Khi làm việc với NavigationController

  • Biến vẫn sống khi chuyển sang ViewController mới.

Bật tắt nút BACK  trên Navigation

Enable:
self.navigationController.view.userInteractionEnabled = YES;
self.navigationController.navigationBar.alpha = 1;

Disabled:
self.navigationController.view.userInteractionEnabled = NO;
self.navigationController.navigationBar.alpha = 0.5;

Lưu ý khi dùng Enum

enum {
    tutang1 = 1,
    tutang2,
    tutang3
};

Các biến tự tăng tutang1, tutang2, tutang3 sẽ có giá trị lần lượt là 1, 2, 3

Trường hợp gán lưng chừng

enum {
            bien1 = 0,
            bien2,
            bien3,
            bien4 = 4,
            bien5,
            bien6,
        };

log---

Lan luot: 0
Lan luot: 1
Lan luot: 2
Lan luot: 4
Lan luot: 5
Lan luot: 6

Hiển thị và ẩn popup trong iOS

- (void)logoutButtonPressed
{
    UIAlertController * alert = [UIAlertController
                                 alertControllerWithTitle:@"Logout"
                                 message:@"Are You Sure Want to Logout!"
                                 preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* yesButton = [UIAlertAction
                                actionWithTitle:@"Yes"
                                style:UIAlertActionStyleDefault
                                handler:^(UIAlertAction * action) {
                                }];
    
    UIAlertAction* noButton = [UIAlertAction
                               actionWithTitle:@"Cancel"
                               style:UIAlertActionStyleDefault
                               handler:^(UIAlertAction * action) {
                                   //Handle no, thanks button
                               }];
    [alert addAction:yesButton];
    [alert addAction:noButton];
    
    [self presentViewController:alert animated:YES completion:nil];
}


Gọi [self logoutButtonPressed]; để hiện

Tạo background dạng trong suốt full màn hình

    CGRect screenBound = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenBound.size;
    CGFloat screenWidth = screenSize.width;
    CGFloat screenHeight = screenSize.height;

    bgView = [[UIView alloc] initWithFrame:CGRectMake(0,0,screenWidth,screenHeight)];
    bgView.backgroundColor = UIColorFromRGB(0x0c0c0c);
    bgView.alpha = 0.5;
    [self.view addSubview:bgView];

Ẩn popup view và phần trong suốt đi

-(void) hidePopupView
{
    [bgView removeFromSuperview];
    [popupView removeFromSuperview];
}

Assigning to ‘NSMutableArray *__strong’ from incompatible

type ‘void’

Lỗi này là do remove phần tử trong NSMutableArray mà nhận dữ liệu về, ko cần phải nhận về mà sau khi remove thì cái mảng chính nó tự remove vì vậy việc gán vào đâu là ko cần thiết.

Khi log debug

unsigned char Khi log thì để là %u là ok

unsigned long Khi log thì để là %lu là ok

Hiển thị dữ liệu bằng tableview cần lưu ý

  • File xib đã được kết nối tới file ViewController nào chưa?
  • Đã sửa tên đúng cho file header và file implement chưa?
  • Đã có mảng dữ liệu chưa?
  • Đã dùng phương thức có tham số numberOfRowsInSection trong delegate chưa?
  • Đã dùng phương thức có tham số cellForRowAtIndexPath trong delegate chưa?
  • Đã tạo ra layout cho từng cell chưa? CustomTableViewCell *cell = [[CustomTableViewCell alloc] initFromXib];

Tham khảo vài trường hợp khác liên quan đến tableview

https://iosprogrammingknowledge.blogspot.jp/2016/06/thu-tu-goi-cac-method-delegate-trong_84.html

https://iosprogrammingknowledge.blogspot.jp/2016/06/trong-table-view-co-cac-cap-reload-nao.html?view=magazine

Khi click vào các phụ kiện bên phải của cell TbView

Khi dùng phụ kiện thông tin UITableViewCellAccessoryDetailDisclosureButton

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath

Khi làm việc với tableview cần chú ý

Nếu dùng tableview để cho người dùng chọn và gửi lên server hay các thiết bị ngoại vi thông qua bluetooth thì cần chú ý đến dữ liệu hiển thị và dữ liệu gửi đi là gì?
Khi làm việc hay QA với khách hàng có cái để hỏi mà estimate công cho hợp lý.

Quy tắc viết hàm trong obj-c

Mọi tham số phải đặt sau dấu 2 chấm : như thế này:

  • (void)someMethod:(int)i; // có một đối số
  • (void)someMethod:(int)i withString:(NSString *)string; // có 2 đối số. đối số thứ nhất kiểu nguyên + có 1 joining arg + đối số thứ 2 kiểu string
  • (void)someMethod:(int)i :(int)i2 :(int)i3; // có 3 đối số kiểu nguyên nhưng ko đối số nào có join arg. ko nên làm thế này.
  • Nếu + là static và – là hàm thành viên, không phải hàm class
  • cứ có dấu * là con trỏ trỏ đến 1 đối tượng như NSString,…
  • Cứ liên quan đến string là dùng @

OOP trong obj-c
– Phân biệt biến thể hiện và thuộc tính. Biến thể hiện khai báo trong {} của header (tức là file .h) còn thuộc tính của đối tượng bắt đầu với từ khoá  @property bên ngoài { } tại file header.h.
– Khai báo class bằng cách định nghĩa nguyên mẫu trong file .h sau đó định nghĩa thực sự 1 class trong file .m

-Nếu khai báo thuộc tính hoặc phương thức trong nguyên mẫu trong file .h thì có thể gọi được khắp nơi miễn là nơi đó import file .h này. Ví dụ: nếu là -(void) tên_hàm thì cần tạo đối tượng còn nếu là +(void) tên_hàm thì gọi trực tiếp qua tên class như ngôn ngữ khác (giống static bên Java).

-Để tạo hàm tạo construct thì dùng cú pháp:

-(instancetype) tên_mong_muốn:

Trong file .h

-(instancetype)hamKhoiTao;

Trong file .m

-(instancetype)hamKhoiTao{

    self = [super init];

    LOG *vidu = [[LOG alloc] init];

    [vidu ASTRING3:@”vidu construct initWithNameHAHA”];

    return self;

}

Gọi:

LOG *log = [[LOG alloc] hamKhoiTao];

Theo lý thuyết chúng ta phải định nghĩa cả prototype và định nghĩa thì ta mới gọi được ở file khác hay trong hàm static tại class đó.

-Với thuộc tính thì cần có từ khóa @property để nói rằng thuộc tính của tôi sẽ tự tạo getter và setter (bên định nghĩa .m cần chỉ rõ thuộc tính @synthesize còn ko nó sẽ tạo tự động cho mình 1 cái thuộc tính là _tênthuoctinh dùng cái này thay vì tên thuộc tinh nguyên mẫu)

-Gọi lấy giá trị thuộc tính bằng tên getter là chính tên nguyên mẫu hoặc _tenthuoctinh

-Gọi set giá trị cho thuộc tính bằng setTenThuocTinh cái chứ set tự thêm vào bất ký thuộc tính nào.

-“+” trước hàm là static gọi thông qua tên Class

-Tóm lại muốn gọi method hay thuộc tính cần phải định nghĩa trong .h dù là hàm tạo đi chăng nữa: [[class alloc] init], [[class alloc] initWithSomename:(NSString *) aaa];

Điểm vào của ứng dụng

  • vào hàm main trong file main.m
  • vào didFinishLaunchingWithOptions trong AppDelegate.m
  • Sau đó vào viewDidLoad của ViewController mà nó đến

Vòng đời app (trong appdelegate) và và vòng đời view

controller

OPEN APP
application khoi dong app
loadView 0
viewDidLoad 1
viewWillAppear 2
viewWillLayoutSubviews 2.1
viewDidLayoutSubviews 2.2
viewDidAppear 3
applicationDidBecomeActive 5

ẤN HOME
applicationWillResignActive 2
applicationDidEnterBackground 3

Mở lại app
applicationWillEnterForeground 4
applicationDidBecomeActive 5

Sang VIEW CONTROLLER khác
viewWillDisappear 4
viewDidDisappear 5

Trở lại VIEW CONTROLLER
loadView 0
viewDidLoad 1
viewWillAppear 2
viewWillLayoutSubviews 2.1
viewDidLayoutSubviews 2.2
viewWillLayoutSubviews 2.1
viewDidLayoutSubviews 2.2
viewDidAppear 3

NHÁY ĐUP HOME VÀ CHỌN LẠI
applicationWillResignActive 2
applicationDidBecomeActive 5

NHÁY ĐUP HOME VÀ CHỌN APP KHÁC
applicationWillResignActive 2
applicationDidEnterBackground 3

KILL APP
applicationDidEnterBackground
applicationWillTerminate 6

Ngoài ra:

Nếu muốn chạy các sự kiện trong app delegate thì cần tạo đối tượng View Controller muốn chạy trong App Delegate sau đó gọi trong các sự kiện cảu App Delegate.

Các dấu trong Obj-C

https://content.pivotal.io/blog/rails-to-ios-what-the-are-these-symbols-in-my-code

Tại sao chúng ta nên dùng Interface Builder (XIB) thay vì Storyboard?
https://techmaster.vn/posts/34247/tai-sao-chung-ta-nen-dung-interface-builder-xib-thay-vi-storyboard

https://techmaster.vn/posts/34348/ban-chat-cua-delegate-va-data-source-trong-swift

https://techmaster.vn/posts/34191/1482475322195

https://techmaster.vn/posts/34190/cau-hoi-tuyen-dung-pho-bien-cho-junior-ios-developer-phan-1

https://techmaster.vn/posts/359

Các khái niệm về từ khoá
https://www.ios-blog.co.uk/tutorials/objective-c/variable-property-attributes-or-modifiers/

Thứ Tự Gọi Các Method Delegate Trong UITableView Khi Gọi

Reload

Đầu tiên call đến:
– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

để kiểm tra xem số lượng các section trong table view là bao nhiêu

Sau đó call đến:
– (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Rồi call đến:
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Sau đó call đến một số phương thức khác nếu có

Gặp trường hợp:

ko thấy gọi đến method cellForRowAtIndexPath: khi table view gọi reload, các bạn cần chú ý:

1. table view có bị nil không?
2. table view có frame chuẩn ko?
3. table view đã được set tableview.datasource và tableview.delegate chưa?
4. numberOfSectionsInTableView có = 0 không?
5. Chiều cao của các row
6. rồi mới tới cellForRowAtIndexPath

Reference:

https://iosprogrammingknowledge.blogspot.jp/2016/06/thu-tu-goi-cac-method-delegate-trong_84.html?view=magazine

http://iphonedevsdk.com/forum/iphone-sdk-development/18342-tableview-reloaddata-method-doesnt-call-cellforrowatindexpath.html

Tạo icon loading cho iOS (UIActivityIndicatorView)

Định nghĩa:

- (void) initIndicatorLoading
{
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    spinner.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
    [self.view addSubview:spinner];
}

Để đảm bảo rằng icon này nằm ở giữa màn hình cần phải khởi tạo khi các view đã sẵn sàng, do đó gọi trong hàm này:

- (void)viewWillAppear:(BOOL)animated {

    [self initIndicatorLoading];

    [spinner startAnimating];

}

Để dừng icon này gọi:

[spinner stopAnimating];

Rất đơn giản khi đã biết rồi.

Đếm ký tự online

Cái này đếm luôn cả khoảng trắng

https://mothereff.in/byte-counter

Khai báo mảng ký tự 30 phần tử

char str[30] = “123456789”;

printf(“%s\n”, str+1); // in từ phần tử thứ 1

Lưu ý với memset và memcpy

void* memset(void* dest, int value, std::size_t count);
set ở đây nghĩa là ghi đè lên cái string dest, với số lượng count ký tự và ghi đè bằng giá trị value

Có thể hiểu là fill vào mảng

#include <stdio.h>
#include <string.h>

int main()
{
    char str[] = "trinh thanh do";
    printf("%s\n", str);

    memset(str, '1', 10); // đè 10 byte từ vị trí thứ 0 của str thành 1
    printf("%s\n", str);
    
    return 0;
}

void* memcpy(void* dest, const void* src, std::size_t count);
copy số count ký tự (cả phần null) của src vào dest. hàm strcpy thì ko copy null vậy nên cần chú ý.

#include <stdio.h>
#include <string.h>

int main()
{
    char str1[30] = "trinh thanh do";
    char str2[30] = "World";

    memcpy(str1, str2, 5);
    printf("%s\n", str1);

    return 0;
}

Trong thực tế được áp dụng để reset 1 mảng sau đó mới copy dữ liệu vào mảng ấy.

ví dụ: reset thằng buf và copy dữ liệu từ thằng rcvBuf

unsigned char buf[20];
memset(buf, 0x00, sizeof(buf));
memcpy(buf, rcvBuf, size);

Cách dùng memmove

copy mảng 2 vào mảng 1 ở vị trí index nào đó. Có thể copy index lớn về index nhỏ và ngược lại.

Ví dụ: copy 11 ký tự từ mảng str vị trí 15 vào mảng str ở vị trí 20, mảng str này được sửa ngay lập tức

minh hoạ
char str[] = "memmove can be very useful......";
memmove (str + 20, str + 15, 11);
cout << str;

memmove can be very useful……
xxxxxxxxxxxxxxxxxxx useful…… str1[20]
xxxxxxxxxxxxxx very useful…… str2[15]
memmove can be very very useful.

kết quả: memmove can be very very useful.

Vì mảng str có 32 phần tử nên còn 1 dấu chấm ở cuối. Chú ý tránh tràn mảng thì mảng str cần có size lớn hơn số ký tự cộng vào 11. (20+11 = 31 vẫn nhỏ hơn 32)

Tham khảo thêm: https://cplusplus.com/reference/cstring/memmove/

Ghi chú:

  1. memcpy: copy block của bộ nhớ
  2. memchr: tìm ký tự trong block của bộ nhớ
  3. memcmp: so sánh 2 blocks của bộ nhớ
  4. memset: Fill block của bộ nhớ
  5. strncpy: copy các ký tự từ string

Cách dùng nsuserdefault

Khởi tạo và lưu:

int maxLenght = 100;
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; // khởi tạo
[userDefault setInteger:maxLenght forKey:@”maxLenghtKey”]; // gán
[ud synchronize];// lưu

Lấy ra:

NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
int maxLengthOfText = [[userDefault objectForKey:@”maxLenghtKey”] intValue];

Xoá đi:

[userDefault removeObjectForKey:@”maxLenghtKey”];

Kiểm tra xem 1 sub view có trong view chính hay không

if(![self.myView isDescendantOfView:self.view]) { 
        [self.view addSubview:self.myView];
    } else {
        [self.myView removeFromSuperview];
    }

Ẩn hiện bàn phím

UITextView does not have any methods which will be called when the user hits the return key. If you want the user to be able to add only one line of text, use a UITextField. Hitting the return and hiding the keyboard for a UITextView does not follow the interface guidelines.

Even then if you want to do this, implement the textView:shouldChangeTextInRange:replacementText: method of UITextViewDelegate and in that check if the replacement text is \n, hide the keyboard.

There might be other ways but I am not aware of any.

https://stackoverflow.com/questions/703754/how-to-dismiss-keyboard-for-uitextview-with-return-key

Khi làm việc với F8 Controller cần chú ý

  • SD card phải định dạng FAT32 nó mới nhận
  • Nâng cấp firmware cho máy F8 thì nhấn PLAY và NGUỒN
  • Sau khi factory reset thì cần phải cái lại bluetooth Add-on cho nó bằng cách lên trang chủ download về và cho vào thẻ nhớ. Tắt máy và nhấn đồng thời MENU và nút NGUỒN

Khi muốn hiển thị 1 VC trong Main Storyboard

Để cái này trong app delegate là ok.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.navigationController = [[ZRNavigationController alloc] init];
    self.window.rootViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"myVC"];
    [self.window makeKeyAndVisible];
    
    [self initNavigationbar];
    [UIApplication sharedApplication].idleTimerDisabled = YES;
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    return YES;
}

VIệc còn lại là sửa trong Main.storyboard cho khớp với View controller storyboard ID

Tham khảo thêm https://stackoverflow.com/questions/41407841/navigation-controller-showing-black-screen

Các bài viết không xem thì tiếc:

Xem thêm
今日の話したいトピックは起業です。直近、テレビを見たり(Shark Tank Viet Nam)、新聞を読んだり、ベトナムでは起業している若者たちが多いが分かっています。特別な分野はIOTを使う農業です。例えば、甘いトマトを育てるとか。 また、ベトナムの政府から応援されています。私にとっては国の経済が成長して行くのが嬉しいです。 いつか、日本のような綺麗な食べ物がたくさんあるし、環境も良くなると思います。 以上です。
 
 
 
 
Facetime iPhone

Main Menu